Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


Info
titleРутокен SDK

Расширенный набор примеров для встраивания содержится в Комплекте разработчика Рутокен

Table of Contents
maxLevel4
outlinetrue
stylenone

...

  1. pLabel, pSeed – строки задающие параметры label и seed.
  2. ulR –  количество байт в счетчике итераций, с возможными значениями 1, 2, 3, 4.
  3. ulL – необходимая байтовая длина вырабатываемого ключевого материала.
  4. ulOffset – байтовое смещение, в последовательности ключевого материала, начиная с которого полученные байты используются для получения диверсифицированного ключа.

CKM

...

_GOST_KEG

Механизм CKM_VENDOR_GOST_KEG позволяет вырабатывать двойственный ключ из закрытого ключа отправителя и открытого ключа получателя.

...

Для задания параметров механизма используется структура CK_VENDORECDH1_GOST_KEGDERIVE_PARAMS:


Code Block
languagecpp
titleструктура CK_VENDORECDH1_GOST_KEGDERIVE_PARAMS
typedef struct CK_VENDORECDH1_GOST_KEGDERIVE_PARAMS {
	  CK_EC_BYTEKDF_PTRTYPE pPublicDatakdf;
	  CK_ULONG ulPublicDataLenulSharedDataLen;
	  CK_BYTE_PTR pUKMpSharedData;
	  CK_ULONG ulUKMLenulPublicDataLen;
}  CK_VENDOR_GOST_KEG_PARAMSBYTE_PTR pPublicData;
};


  1. pPublicData – открытый ключ получателя
  2. pUKM – синхропосылка.

...

Code Block
languagebash
titleВыработка общего ключа парной связи по схеме ключевого обмена VKO GOST 34.10-2001 на стороне отправителя
/* Размер синхропосылки в байтах */
#define UKM_LENGTH					8

#define DERIVE_PARAMS_256_LENGTH	84

/*************************************************************************
* Параметры для выработки ключа обмена по схеме VKO GOST R 34.10-2012-256*
* Содержат в себе данные по диверсификации ключа, открытый ключ и UKM    *
*************************************************************************/
CK_BYTE deriveParameters2012_256[DERIVE_PARAMS_256_LENGTH] = { 0x00, };

const CK_ULONG keyLengthOffset = 4;       // Смещение длины ключа в массиве
const CK_ULONG publicKeyValueOffset = 8;  // Смещение значения ключа в массиве
const CK_ULONG ukmLengthOffset = 72;      // Смещение длины UKM в массиве
const CK_ULONG ukmDataOffset = 76;        // Смещение UKM в массиве

/*************************************************************************
* Функция записи четырёхбайтного значения длины в буфер                  *
*************************************************************************/
void ulongToBuffer(CK_BYTE_PTR buffer, CK_ULONG value)
{
	buffer[0] = value & 0xFF;
	buffer[1] = (value >> 8) & 0xFF;
	buffer[2] = (value >> 16) & 0xFF;
	buffer[3] = (value >> 24) & 0xFF;
}

/* Механизм выработки ключа обмена по алгоритму VKO GOST R 34.10-2012 */
CK_MECHANISM gostR3410_12DerivationMech = { CKM_GOSTR3410_12_DERIVE, NULL_PTR, 0 };

/* Значение открытого ключа получателя */
CK_BYTE cbPubRecipientKey[] = { 0xFF, 0x8D, 0xAB, 0x7F, 0x1C, 0x0B, 0x74, 0xA5, 0xAD, 0x7F, 0x0B, 0x5F, 0x8D, 0x5B, 0x3C, 0x44,
								0x58, 0x37, 0x98, 0xC9, 0x25, 0x86, 0x40, 0x7E, 0xEC, 0x6E, 0xAF, 0x00, 0xCB, 0x44, 0x65, 0xA5,
								0x22, 0x9A, 0x53, 0x56, 0x32, 0x97, 0x35, 0x80, 0x99, 0xCA, 0x1E, 0x17, 0x21, 0x3A, 0x96, 0x0E,
								0x21, 0xFB, 0xC6, 0x0F, 0x25, 0x5B, 0x5D, 0x99, 0x4E, 0xC4, 0x5C, 0x42, 0x08, 0x7D, 0x06, 0x04 };

CK_OBJECT_CLASS ocSecKey = CKO_SECRET_KEY;
CK_UTF8CHAR 	DerivedKeyLabel[] = { "Derived Key" };
CK_BYTE 		SecKeyID[] = { "GOST Secret Key" };
CK_KEY_TYPE 	KeyType = CKK_GOST28147;
CK_BBOOL 		bTrue = CK_TRUE;
CK_BBOOL 		bFalse = CK_FALSE;

/* Шаблон для создания общего ключа */
CK_ATTRIBUTE attrGOST28147DerivedKey[] =
{
	{ CKA_CLASS, &ocSecKey, sizeof(ocSecKey)},                      // Объект секретного ключа ГОСТ 28147-89
	{ CKA_LABEL, &DerivedKeyLabel, sizeof(DerivedKeyLabel) - 1},    // Метка ключа
	{ CKA_KEY_TYPE, &KeyType, sizeof(KeyType)},               		// Тип ключа
	{ CKA_TOKEN, &bFalse, sizeof(bFalse)},                          // Ключ является объектом сессии
	{ CKA_MODIFIABLE, &bTrue, sizeof(bTrue)},                       // Ключ может быть изменен после создания
	{ CKA_PRIVATE, &bFalse, sizeof(bFalse)},                        // Ключ доступен без авторизации
	{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue)},                      // Ключ может быть извлечен и зашифрован
	{ CKA_SENSITIVE, &bFalse, sizeof(bFalse)}                       // Ключ не может быть извлечен в открытом виде
};

CK_ATTRIBUTE 		attrDerivedKeyValue = { CKA_VALUE, NULL_PTR, 0 }; 	// Структура данных типа CK_ATTRIBUTE для хранения значения атрибута CKA_VALUE
CK_BYTE 			ukm[UKM_LENGTH];									// Буфер, содержащий UKM
CK_OBJECT_HANDLE 	hDerivedKey = NULL_PTR;           					// Хэндл выработанного общего ключа
CK_OBJECT_HANDLE 	hObject;											// Хэндл объекта

...

/*************************************************************************
* Установить параметры в структуре типа CK_GOSTR3410_DERIVE_PARAMS       *
* для выработки ключа обмена                                             *
*************************************************************************/
rv = pFunctionList->C_GenerateRandom(hSession, ukm, sizeof(ukm));
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}


/*************************************************************************
* Поместить в структуру типа CK_MECHANISM параметры, необходимые         *
* для выработки ключа обмена                                             *
*************************************************************************/
ulongToBuffer(deriveParameters2012_256, CKM_KDF_GOSTR3411_2012_256);
ulongToBuffer(deriveParameters2012_256 + keyLengthOffset, sizeof(cbPubRecipientKey));
memcpy(deriveParameters2012_256 + publicKeyValueOffset, cbPubRecipientKey, sizeof(cbPubRecipientKey));
ulongToBuffer(deriveParameters2012_256 + ukmLengthOffset, sizeof(ukm));
memcpy(deriveParameters2012_256 + ukmDataOffset, ukm, sizeof(ukm));
gostR3410_12DerivationMech.pParameter = deriveParameters2012_256;
gostR3410_12DerivationMech.ulParameterLen = sizeof(deriveParameters2012_256);

/* Выработать общий ключ ГОСТ 28147-89 на основании закрытого ключа отправителя и открытого ключа получателя */
printf("C_DeriveKey");
rv = pFunctionList->C_DeriveKey(hSession,	// Хэндл открытой с правами Пользователя сессии 
	&gostR3410_12DerivationMech,  			// Механизм ключевого обмена
	hPrivateKey,							// Хэндл закрытого ключа отправителя
	attrGOST28147DerivedKey,				// Шаблон создания общего ключа
	arraysize(attrGOST28147DerivedKey), 	// Размер шаблона
	&hDerivedKey);						// Хэндл общего выработанного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}
printf(" -> OK\n");

/* Получить размер буфера для хранения значения атрибута CKA_VALUE*/
printf("Getting object value size");
rv = pFunctionList->C_GetAttributeValue(hSession,	// Хэндл открытой с правами Пользователя сессии 
	hDerivedKey,									// Хэндл общего ключа
	&attrDerivedKeyValue,							// Шаблон получения значения атрибута
	1);												// Количество атрибутов в шаблоне
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}
printf(" -> OK\n");

/* Выделить необходимое количество памяти для значения атрибута */
attrDerivedKeyValue.pValue = (CK_BYTE*)malloc(attrDerivedKeyValue.ulValueLen);
if (attrDerivedKeyValue.pValue == NULL)
{
	printf("Memory allocation for attrDerivedKeyValue failed! \n");
	goto exit;
}
memset(attrDerivedKeyValue.pValue,
	0,
	(attrDerivedKeyValue.ulValueLen * sizeof(CK_BYTE)));

/* Получить значение общего ключа ГОСТ 28147-89 */
printf("Getting object value");
rv = pFunctionList->C_GetAttributeValue(hSession,	// Хэндл открытой с правами Пользователя сессии 
	hDerivedKey,									// Хэндл общего ключа
	&attrDerivedKeyValue,							// Шаблон получения значения атрибута
	1);												// Количество атрибутов в шаблоне
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}
printf(" -> OK\n");
/* Распечатать буфер со значением общего ключа ГОСТ 28147-89 */
printf("Derived key data is:\n");
for (size_t i = 0; i < attrDerivedKeyValue.ulValueLen; i++)
{
	printf("%02X ", ((CK_BYTE_PTR) attrDerivedKeyValue.pValue)[i]);
	if ((i + 1) % 8 == 0)
		printf("\n");
}

exit:
if (attrDerivedKeyValue.pValue)
{
	free(attrDerivedKeyValue.pValue);
	attrDerivedKeyValue.pValue = NULL_PTR;
	attrDerivedKeyValue.ulValueLen = 0;
}

if (rv != CKR_OK)
{
	pFunctionList->C_DestroyObject(hSession,
		hDerivedKey);
	hDerivedKey = NULL_PTR;
}
if (rv != CKR_OK)
	printf("\nDeriving failed!\n\n");
else
	printf("Deriving has been completed successfully.\n\n");

Пример выработки двойственного ключа по алгоритму

...

KEG

Code Block
languagebash
titleВыработка двойственного ключа по алгоритму KegKEG
/* Размер синхропосылки в байтах */
#define UKM_KEG_LENGTH				24 // Значение для ключа ГОСТ 2012-256
//#define UKM_KEG_LENGTH				16 // Значение для ключа ГОСТ 2012-512

CK_UTF8CHAR derivedKuznechikTwinKeyLabel[] = { "Derived Kuznechik twin key" };
CK_UTF8CHAR derivedMagmaTwinKeyLabel[] = { "Derived Magma twin key" };
CK_OBJECT_CLASS secretKeyObject = CKO_SECRET_KEY;
CK_KEY_TYPE keyTypeKuznechikTwin = CKK_KUZNECHIK_TWIN_KEY;
CK_KEY_TYPE keyTypeMagmaTwin = CKK_MAGMA_TWIN_KEY;
CK_BBOOL attributeTrue = CK_TRUE;
CK_BBOOL attributeFalse = CK_FALSE;


/* Значение открытого ключа получателя для ГОСТ 2012-256*/
CK_BYTE cbPubRecipientKey[] = { 0xFF, 0x8D, 0xAB, 0x7F, 0x1C, 0x0B, 0x74, 0xA5, 0xAD, 0x7F, 0x0B, 0x5F, 0x8D, 0x5B, 0x3C, 0x44,
								0x58, 0x37, 0x98, 0xC9, 0x25, 0x86, 0x40, 0x7E, 0xEC, 0x6E, 0xAF, 0x00, 0xCB, 0x44, 0x65, 0xA5,
								0x22, 0x9A, 0x53, 0x56, 0x32, 0x97, 0x35, 0x80, 0x99, 0xCA, 0x1E, 0x17, 0x21, 0x3A, 0x96, 0x0E,
								0x21, 0xFB, 0xC6, 0x0F, 0x25, 0x5B, 0x5D, 0x99, 0x4E, 0xC4, 0x5C, 0x42, 0x08, 0x7D, 0x06, 0x04 };

/*************************************************************************
* Шаблон для создания двойственного Значение открытого ключа экспортаполучателя типадля Кузнечик         ГОСТ 2012-512*/
/*CK_BYTE cbPubRecipientKey[] = {	0xFC, 0xD5, 0xD3, 0x91, 0xEF, 0x58, 0x66, 0x50, 0x26, 0x59, 0x6C, 0x71, 0xE5, 0x89, 0x35, 0xC7,
								0x35, 0x71, 0x28, 0xA4, 0xAD, 0x3C, 0xD5, 0x0A, 0xA3, 0xF8, 0xB1, 0xD9, 0xC1, 0x77, 0xB3, 0x17,
								0x65, 0x0C, 0x7E, 0x6E, 0x11, 0x12, 0xC2, 0x62, 0xB3, 0xDF, 0x43, 0x32, 0x54, 0xB4, 0x7C, 0x7D,
								0xF3, 0x3C, 0x1F, 0xD7, 0xEA, 0x02, 0xE7, 0x70, 0x15, 0xCC, 0xFC, 0x28, 0xC6, 0xAE, 0x91, 0x29,
								0x58, 0xFB, 0x75, 0x14, 0x7B, 0x0E, 0x99, 0x59, 0xF9, 0x4B, 0xE9, 0x80, 0xA5, 0xBB, 0x18, 0x8E,
								0xED, 0x43, 0xCC, 0x8D, 0x9E, 0x39, 0x14, 0x6A, 0xBA, 0xC7, 0x5F, 0xFF, 0x02, 0x4C, 0x1C, 0x9E,
								0xFE, 0x71, 0xF2, 0xC3, 0xFD, 0xD6, 0x1C, 0x76, 0xBE, 0xCF, 0x77, 0xB6, 0xD7, 0x5D, 0xFF, 0x35,
								0x3C, 0x35, 0x70, 0x78, 0x03, 0xED, 0x6E, 0x0A, 0x03, 0x65, 0xDC, 0xA4, 0xAA, 0x59, 0x8B, 0xDB };*/

/*************************************************************************
* Шаблон для создания двойственного ключа экспорта типа Кузнечик         *
*************************************************************************/
CK_ATTRIBUTE derivedTwinKeyTemplate[] =
{
	{ CKA_LABEL, &derivedKuznechikTwinKeyLabel, sizeof(derivedKuznechikTwinKeyLabel) - 1},  // Метка ключа
	{ CKA_CLASS, &secretKeyObject, sizeof(secretKeyObject) },								// Класс - секретный ключ
	{ CKA_KEY_TYPE, &keyTypeKuznechikTwin, sizeof(keyTypeKuznechikTwin)},					// Тип ключа - двойственный Кузнечик
	{ CKA_TOKEN, &attributeFalse, sizeof(attributeFalse)},									// Ключ является объектом сессии
	{ CKA_MODIFIABLE, &attributeTrue, sizeof(attributeTrue)},								// Ключ может быть изменен после создания
	{ CKA_PRIVATE, &attributeTrue, sizeof(attributeTrue)},									// Ключ доступен только после аутентификации на токене
	{ CKA_EXTRACTABLE, &attributeTrue, sizeof(attributeTrue)},								// Ключ может быть извлечен в зашифрованном виде
	{ CKA_SENSITIVE, &attributeFalse, sizeof(attributeFalse)}								// Ключ может быть извлечен в открытом виде
};

/*************************************************************************
* Шаблон для создания двойственного ключа экспорта типа Магма            *
*************************************************************************/
//CK_ATTRIBUTE derivedTwinKeyTemplate[] =
//{
//	{ CKA_LABEL, &derivedMagmaTwinKeyLabel, sizeof(derivedMagmaTwinKeyLabel) - 1},          // Метка ключа
//	{ CKA_CLASS, &secretKeyObject, sizeof(secretKeyObject) },								// Класс - секретный ключ
//	{ CKA_KEY_TYPE, &keyTypeMagmaTwin, sizeof(keyTypeMagmaTwin)},							// Тип ключа - двойственный Магма
//	{ CKA_TOKEN, &attributeFalse, sizeof(attributeFalse)},									// Ключ является объектом сессии
//	{ CKA_MODIFIABLE, &attributeTrue, sizeof(attributeTrue)},								// Ключ может быть изменен после создания
//	{ CKA_PRIVATE, &attributeTrue, sizeof(attributeTrue)},									// Ключ доступен только после аутентификации на токене
//	{ CKA_EXTRACTABLE, &attributeTrue, sizeof(attributeTrue)},								// Ключ может быть извлечен в зашифрованном виде
//	{ CKA_SENSITIVE, &attributeFalse, sizeof(attributeFalse)}								// Ключ может быть извлечен в открытом виде
//};

CK_ECDH1_DERIVE_PARAMS keg256DeriveParams;
CK_MECHANISM gostKegDerifivationMech = { CKM_VENDOR_GOST_KEG, NULL_PTR&keg256DeriveParams, 0 };
CK_VENDOR_GOST_KEG_PARAMS keg256DeriveParamssizeof(keg256DeriveParams)};
CK_ATTRIBUTE 		attrDerivedKeyValue = { CKA_VALUE, NULL_PTR, 0 }; 	// Структура данных типа CK_ATTRIBUTE для хранения значения атрибута CKA_VALUE
CK_BYTE 			ukm[UKM_KEG_LENGTH];									// Буфер, содержащий UKM
CK_OBJECT_HANDLE 	hDerivedKey = NULL_PTR;           					// Хэндл выработанного общего ключа
CK_OBJECT_HANDLE 	hObject;											// Хэндл объекта

...

/*************************************************************************
* Установить параметры в структуре типа CK_VENDOR_GOST_KEG_PARAMS        *
* для выработки двлйственногодвойственного ключа                                      *
*************************************************************************/
rv = pFunctionList->C_GenerateRandom(hSession, ukm, sizeof(ukm));
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}


/*************************************************************************
* Поместить в структуру типа CK_MECHANISM параметры, необходимые         *
* для выработки ключа обмена                                             *
*************************************************************************/

keg256DeriveParams.kdf = CKD_NULL;
keg256DeriveParams.pPublicData = cbPubRecipientKey;
keg256DeriveParams.ulPublicDataLen = sizeof(cbPubRecipientKey);
keg256DeriveParams.pUKM = ukm;
keg256DeriveParams.ulUKMLen = sizeof(ukm);

gostR3410_12DerivationMechgostKegDerifivationMech .pParameter = &keg256DeriveParams;
gostR3410_12DerivationMechgostKegDerifivationMech .ulParameterLen = sizeof(keg256DeriveParams);

/* Выработать общий двойственный ключ ГОСТ 28147-89 на основании закрытого ключа отправителя и открытого ключа получателя */
printf("C_DeriveKey");
rv = pFunctionList->C_DeriveKey(hSession,	// Хэндл открытой с правами Пользователя сессии 
	&gostR3410_12DerivationMechgostKegDerifivationMech,  			// Механизм ключевого обмена
	hPrivateKey,							// Хэндл закрытого ключа отправителя
	derivedTwinKeyTemplate,					// Шаблон создания общего ключа
	arraysize(derivedTwinKeyTemplate), 		// Размер шаблона
	&hDerivedKey);							// Хэндл общего выработанного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}
printf(" -> OK\n");

/* Получить размер буфера для хранения значения атрибута CKA_VALUE*/
printf("Getting object value size");
rv = pFunctionList->C_GetAttributeValue(hSession,	// Хэндл открытой с правами Пользователя сессии 
	hDerivedKey,									// Хэндл общего ключа
	&attrDerivedKeyValue,							// Шаблон получения значения атрибута
	1);												// Количество атрибутов в шаблоне
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}
printf(" -> OK\n");

/* Выделить необходимое количество памяти для значения атрибута */
attrDerivedKeyValue.pValue = (CK_BYTE*)malloc(attrDerivedKeyValue.ulValueLen);
if (attrDerivedKeyValue.pValue == NULL)
{
	printf("Memory allocation for attrDerivedKeyValue failed! \n");
	goto exit;
}
memset(attrDerivedKeyValue.pValue,
	0,
	(attrDerivedKeyValue.ulValueLen * sizeof(CK_BYTE)));

/* Получить значение общего двойственного ключа ГОСТ 28147-89 */
printf("Getting object value");
rv = pFunctionList->C_GetAttributeValue(hSession,	// Хэндл открытой с правами Пользователя сессии 
	hDerivedKey,									// Хэндл общего ключа
	&attrDerivedKeyValue,							// Шаблон получения значения атрибута
	1);												// Количество атрибутов в шаблоне
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto exit;
}
printf(" -> OK\n");
/* Распечатать буфер со значением общего двойственного ключа ГОСТ 28147-89 */
printf("Derived key data is:\n");
for (size_t i = 0; i < attrDerivedKeyValue.ulValueLen; i++)
{
	printf("%02X ", ((CK_BYTE_PTR)attrDerivedKeyValue.pValue)[i]);
	if ((i + 1) % 8 == 0)
		printf("\n");
}

exit:
if (attrDerivedKeyValue.pValue)
{
	free(attrDerivedKeyValue.pValue);
	attrDerivedKeyValue.pValue = NULL_PTR;
	attrDerivedKeyValue.ulValueLen = 0;
}

if (rv != CKR_OK)
{
	pFunctionList->C_DestroyObject(hSession,
		hDerivedKey);
	hDerivedKey = NULL_PTR;
}
if (rv != CKR_OK)
printf("\nDeriving failed!\n\n");
else
printf("Deriving has been completed successfully.\n\n");

...

  • CKM_MD2 для хеширования алгоритмом MD2 (только программно),
  • CKM_MD5 для хеширования алгоритмом MD5 (только программно),
  • CKM_SHA_1 для хеширования алгоритмом SHA-1 (только программно),
  • CKM_SHA256 для хеширования алгоритмом SHA-256 (только программно),
  • CKM_SHA512 для хеширования алгоритмом SHA-512 (только программно),
  • CKM_GOSTR3411 для хеширования алгоритмом ГОСТ Р 34.11.94 (программно и аппаратно),
  • CKM_GOSTR3411_12_256 для хеширования алгоритмом ГОСТ Р 34.11.2012 с длиной значения 256 бит (только программно и аппаратно),
  • CKM_GOSTR3411_12_512 для хеширования алгоритмом ГОСТ Р 34.11.2012 с длиной закрытого ключа 512 бит (только программно и аппаратно).

Хеширование данных 

...

Подпись данных отдельными механизмами хеширования и подписи

...

Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 отдельными механизмами хеширования и подписи для всех устройств Рутокен

...

При использовании совместного механизма и хеширование, и подпись выполняются функцией C_Sign(). Сначала в функцию C_SignInit() передается совместный механизм (например, CKM_GOSTR3410_WITH_GOSTR3411), а затем в функцию C_Sign() – сообщение.

Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 совместным механизмом хеширования и подписи

...

Пример подписи данных по алгоритму ECDSA отдельными механизмами хеширования и подписи

...