Page tree

Versions Compared

Key

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

...

Code Block
languagecpp
titleШаблон закрытого ключа ГОСТ Р 34.10-2012
CK_OBJECT_CLASS	ocPrivKey	 			= CKO_PRIVATE_KEY;
CK_UTF8CHAR 	PrivKeyLabel[]			 = { "GOST Private Key" }; 
CK_BYTE 		KeyPairID[] 			= { "GOST keypair" }; 
CK_KEY_TYPE 	keyTypeGostR3410		 = CKK_GOSTR3410;		// Для закрытого ключа длиной 256 бит
CK_KEY_TYPE 	keyTypeGostR3410_512 	= CKK_GOSTR3410_512;	// Для закрытого ключа длиной 512 бит
CK_BBOOL 		bTrue 					= CK_TRUE; 

/* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(256) */
CK_BYTE 		parametersGostR3410_2012_256[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 };

/* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(512) */
CK_BYTE 		parametersGostR3410_2012_512[] = { 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x01 }; 

/* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(256) */
CK_BYTE 		parametersGostR3411_2012_256[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 };

/* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(512) */
CK_BYTE 		parametersGostR3411_2012_512[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 };
 

CK_ATTRIBUTE GOST34_10_2012_256_PrivateKey[] = { 					// Шаблон для ключа длиной 256 бит
	{ CKA_CLASS, &ocPrivKey, sizeof(ocPrivKey)}, 					// Объект закрытого ключа 
	{ CKA_LABEL, &PrivKeyLabel, sizeof(PrivKeyLabel) - 1}, 			// Метка ключа 
	{ CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, 					// Идентификатор ключевой пары #1 (должен совпадать у открытого и закрытого ключей) 
	{ CKA_KEY_TYPE, &keyTypeGostR3410, sizeof(keyTypeGostR3410)}, 	// Тип ключа 
	{ CKA_TOKEN, &bTrue, sizeof(bTrue)},							// Ключ является объектом токена 
	{ CKA_PRIVATE, &bTrue, sizeof(bTrue)}, 							// Ключ доступен только после авторизации на токене 
	{ CKA_DERIVE, &bTrue, sizeof(bTrue)}, 							// Ключ поддерживает деривацию (из него могут быть получены другие ключи) 
	{ CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_256, sizeof(parametersGostR3410_2012_256)}, // Параметры алгоритма 
	{ CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_256, sizeof(parametersGostR3411_2012_256)} 	// Параметры алгоритма ГОСТ Р 34.11-2012(256)
};
 
CK_ATTRIBUTE GOST34_10_2012_512_PrivateKey[] = { 					// Шаблон для ключа длиной 512 бит
	{ CKA_CLASS, &ocPrivKey, sizeof(ocPrivKey)}, 					// Объект закрытого ключа 
	{ CKA_LABEL, &PrivKeyLabel, sizeof(PrivKeyLabel) - 1}, 			// Метка ключа 
	{ CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, 					// Идентификатор ключевой пары #1 (должен совпадать у открытого и закрытого ключей) 
	{ CKA_KEY_TYPE, &keyTypeGostR3410_512, sizeof(keyTypeGostR3410)_512)},   	// Тип ключа 
	{ CKA_TOKEN, &bTrue, sizeof(bTrue)},							// Ключ является объектом токена 
	{ CKA_PRIVATE, &bTrue, sizeof(bTrue)}, 							// Ключ доступен только после авторизации на токене 
	{ CKA_DERIVE, &bTrue, sizeof(bTrue)}, 							// Ключ поддерживает деривацию (из него могут быть получены другие ключи) 
	{ CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_512, sizeof(parametersGostR3410_2012_512)}, // Параметры алгоритма
	{ CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_512, sizeof(parametersGostR3411_2012_512)}  	// Параметры алгоритма ГОСТ Р 34.11-2012(512)
};

...

Code Block
languagecpp
titleШаблон открытого ключа ГОСТ Р 34.10-2012
CK_OBJECT_CLASS ocPubKey 				= CKO_PUBLIC_KEY; 
CK_UTF8CHAR 	PubKeyLabel[] 			= { "GOST Public Key" }; 
CK_BYTE 		KeyPairID[] 			= { "GOST keypair" }; 
CCKCK_KEY_TYPE 	keyTypeGostR3410		 = CKK_GOSTR3410;			// Для закрытого ключа длиной 256 бит
CK_KEY_TYPE 	keyTypeGostR3410_512 	= CKK_GOSTR3410_512;	// Для закрытого ключа длиной 512 бит
CK_BBOOL 		bTrue 					= CK_TRUE; 
CK_BBOOL 		bFalse 					= CK_FALSE; 

/* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(256) */
CK_BYTE 		parametersGostR3410_2012_256[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 };

/* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(512) */
CK_BYTE 		parametersGostR3410_2012_512[] = { 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x01 }; 

/* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(256) */
CK_BYTE 		parametersGostR3411_2012_256[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 };

/* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(512) */
CK_BYTE 		parametersGostR3411_2012_512[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 };
 
 
CK_ATTRIBUTE GOST34_10_2012_256_PublicKey[] = {						// Шаблон для открытого ключа, соответствуюзегосоответствующего закрытому длиной 256 бит
	{ CKA_CLASS, &ocPubKey, sizeof(ocPubKey)}, 						// Объект открытого ключа 
	{ CKA_LABEL, &PubKeyLabel, sizeof(PubKeyLabel) - 1}, 				// Метка ключа 
	{ CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, 					// Идентификатор ключевой пары 
	{ CKA_KEY_TYPE, &keyTypeGostR3410, sizeof(keyTypeGostR3410)}, 	// Тип ключа 
	{ CKA_TOKEN, &bTrue, sizeof(bTrue)}, 							// Ключ является объектом токена 
	{ CKA_PRIVATE, &bFalse, sizeof(bFalse)}, 						// Ключ доступен без авторизации на токене 
	{ CKA_DERIVE, &bTrue, sizeof(bTrue)}, 							// Ключ поддерживает деривацию (из него могут быть получены другие ключи)
	{ CKA_GOSTR3410_PARAMS, paramsGostR3410parametersGostR3410_2012_256, sizeof(paramsGostR3410parametersGostR3410_2012_256)},			// Параметры алгоритма 
	{ CKA_GOSTR3411_PARAMS, paramsGostR3411parametersGostR3411_2012_256, sizeof(paramsGostR3411parametersGostR3411_2012_256)} 	// Параметры алгоритма 
};
 
CK_ATTRIBUTE GOST34_10_2012_512_PublicKey[] = {						// Шаблон для открытого ключа, соответствуюзегосоответствующего закрытому длиной 512бит
	{ CKA_CLASS, &ocPubKey, sizeof(ocPubKey)}, 						// Объект открытого ключа 
	{ CKA_LABEL, &PubKeyLabel, sizeof(PubKeyLabel) - 1}, 				// Метка ключа 
	{ CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, 					// Идентификатор ключевой пары 
	{ CKA_KEY_TYPE, &keyTypeGostR3410_512, sizeof(keyTypeGostR3410_512)}, 	    // Тип ключа 
	{ CKA_TOKEN, &bTrue, sizeof(bTrue)}, 							// Ключ является объектом токена 
	{ CKA_PRIVATE, &bFalse, sizeof(bFalse)}, 						// Ключ доступен без авторизации на токене 
	{ CKA_DERIVE, &bTrue, sizeof(bTrue)}, 							// Ключ поддерживает деривацию (из него могут быть получены другие ключи)
	{ CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_512, sizeof(parametersGostR3410_2012_512)}, // Параметры алгоритма
	{ CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_512, sizeof(parametersGostR3411_2012_512)}  // Параметры алгоритма ГОСТ Р 34.11-2012(512)
};

...

Code Block
languagecpp
titleГенерация ключевой пары ГОСТ Р 34.10-2012
/* Вычисление размера массива */
#define 		 arraysize(a)   (sizeof(a)/sizeof(a[0]))
 
CK_MECHANISM     gostR3410_256KeyPairGenMech 		= { CKM_GOSTR3410_KEY_PAIR_GEN, NULL_PTR, 0 }; 		// Механизм генерации ключевой пары ГОСТ Р 34.10-2012(256)
CK_MECHANISM 	 gostR3410_512KeyPairGenMech	 = { CKM_GOSTR3410_512_KEY_PAIR_GEN, NULL_PTR, 0 };  	// Механизм генерации ключевой пары ГОСТ Р 34.10-2012(512) */

 
CK_OBJECT_HANDLE hPublicKey_256	 = NULL_PTR;    		// Хэндл открытого ключа
CK_OBJECT_HANDLE hPrivateKey_256 = NULL_PTR;    	// Хэндл закрытого ключа
CK_OBJECT_HANDLE hPublicKey_512	 = NULL_PTR;    		// Хэндл открытого ключа
CK_OBJECT_HANDLE hPrivateKey_512 = NULL_PTR;    	// Хэндл закрытого ключа

... 

printf("Generating 256 bit key pair");
rv = pFunctionList->C_GenerateKeyPair(hSession,									 // Хэндл открытой сессии
	&gostR3410_256KeyPairGenMech,				// Используемый механизм генерации ключевой                      &gostR3410KeyPairGenMech,                  // Используемый механизм генерации ключевой пары 
				                      GOST34_10_2012_256_PublicKey,              пары 
	GOST34_10_2012_256_PublicKey,				// Шаблон открытого ключа
			                          arraysize(GOST34_10_2012_256_PublicKey),   	// Размер шаблона открытого ключа
			                          GOST34_10_2012_256_PrivateKey,             				// Шаблон закрытого ключа 
			                          arraysize(GOST34_10_2012_256_PrivateKey),  	// Размер шаблона закрытого ключа
			                          &hPublicKey_256,                  		 &hPublicKey_256,							// Хэндл открытого ключа
			                          &hPrivateKey_256);                    	 							// Хэндл закрытого ключа

if (rv != CKR_OK)
	printf(" -> Failed\n");
else
	printf(" -> OK\n");
 
printf("Generating 512 bit key pair");
rv = pFunctionList->C_GenerateKeyPair(hSession,                             	 // Хэндл открытой сессии
			                          &gostR3410_512KeyPairGenMech,              				// Используемый механизм генерации ключевой пары 
	GOST34_10_2012_512_PublicKey,				// Шаблон                     GOST34_10_2012_512_PublicKey,              // Шаблон открытого ключа
			                          открытого ключа
	arraysize(GOST34_10_2012_512_PublicKey),   	// Размер шаблона открытого ключа
			                          GOST34_10_2012_512_PrivateKey,             				// Шаблон закрытого ключа 
			                          arraysize(GOST34_10_2012_512_PrivateKey),  	// Размер шаблона закрытого ключа
	&hPublicKey_512,							// Хэндл открытого ключа
	&hPrivateKey_512);							// Хэндл закрытого ключа

if (rv                   &hPublicKey_512,                  		 // Хэндл открытого ключа
			                          &hPrivateKey_512);                    	 // Хэндл закрытого ключа
if (rv != CKR_OK!= CKR_OK)
	printf(" -> Failed\n");
else
	printf(" -> OK\n");

...

Code Block
languagecpp
titleШаблон секретного ключа ГОСТ 28147-89
CK_OBJECT_CLASS ocSecKey 		= CKO_SECRET_KEY; 
CK_UTF8CHAR 	SecKeyLabel[] 	= {"GOST Secret Key"}; 
CK_BYTE 		SecKeyID[] 		= {"GOST Secret Key"}; 
CK_KEY_TYPE 	KeyType 		= CKK_GOST28147; 
CK_BBOOL 		bTrue 			= CK_TRUE; 
CK_BBOOL 		bFalse 			= CK_FALSE; 
 
/* Набор параметров КриптоПро A алгоритма ГОСТ 28147-89 */
CK_BYTE 	GOST28147params[]	= { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 }; 
  
CK_ATTRIBUTE attrGOST28147_89SecKey[] =
{
	{ CKA_CLASS, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)},              // Объект секретного ключа ГОСТ 28147-89
	{ CKA_LABEL, &SecKeyLabel, sizeof(SecKeyLabel) - 1},    // Метка ключа
	{ CKA_ID, &SecKeyID, sizeof(SecKeyID) - 1},             // Идентификатор ключа
	{ CKA_KEY_TYPE, &KeyType, sizeof(KeyType)},       		// Тип ключа
	{ CKA_ENCRYPT, &bTrue, sizeof(bTrue)},                  // Ключ предназначен для зашифрования
	{ CKA_DECRYPT, &bTrue, sizeof(bTrue)},                  // Ключ предназначен для расшифрования
	{ CKA_TOKEN, &bTrue, sizeof(bTrue)},                    // Ключ является объектом токена
	{ CKA_PRIVATE, &bFalse, sizeof(bFalse)},                // Ключ доступен без авторизации на токене
	{ CKA_GOST28147_PARAMS, GOST28147params, sizeof(GOST28147params)} // Параметры алгоритма 
};

...

Для выработки сеансового ключ (CEK) в оперативной памяти токена, зашифрованного на KEK с имитовставкой CEK, необходимо использовать функцию расширения C_EX_WrapKey().

Параметры механизма согласования ключей задаются отдельной структурой типа CKCKM_GOSTR3410_2012_DERIVE _PARAMS, которая содержит:

...

задаются байтовым массивом, который имеет следующую структуру:

  1.  4 байта (little-endian, т.е. младшие байты сначала) представляют собой значение KDF. Значение определяет механизм диверсификации:
    • CKD_NULL - нет диверсификации
    • CKM_KDF_4357
    • CKD_CPDIVERSIFY_KDF
    • CKM_KDF_GOSTR3411_2012_256
  2. 4 байта (little-endian) задают длину открытого ключа в байтах. (64 либо 128)
  3. открытый ключ (n-байтовый вектор в little-endian), длина которого определена предыдущим полем
  4. 4 байта (little-endian) задают длину UKM (от 8 байт )
  5. UKM (n-байтовый вектор в little-endian) , длина определена выше

...

  1. .

Пример выработки общего ключа парной связи по алгоритму VKO GOST R 34.10-2012

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, FF0x8D, 8D0xAB, AB0x7F, 7F0x1C, 1C0x0B, 0B0x74, 740xA5, A5 AD0xAD, 7F0x7F, 0B0x0B, 5F0x5F, 8D0x8D, 5B0x5B, 3C0x3C, 44 0x44,
								0x58, 0x37, 0x98, 0xC9, 580x25, 370x86, 980x40, C90x7E, 250xEC, 860x6E, 400xAF, 7E EC0x00, 6E0xCB, AF0x44, 00 CB 44 65 A5 
0x65, 0xA5,
								0x22, 0x9A, 0x53, 0x56, 220x32, 9A0x97, 530x35, 560x80, 320x99, 970xCA, 350x1E, 800x17, 990x21, CA0x3A, 1E 17 21 3A 96 0E 0x96, 0x0E,
								0x21, 0xFB, 0xC6, 0x0F, 0x25, 0x5B, 0x5D, 0x99, 210x4E, FB0xC4, C60x5C, 0F0x42, 250x08, 5B0x7D, 5D 99 4E C4 5C 42 08 7D 06 040x06, 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, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)},                      // Объект секретного ключа ГОСТ 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_1 = NULL_PTR;           					// Хэндл выработанного на стороне отправителя общего ключа
CK_OBJECT_HANDLE 	hObject,               ;											// Хэндл объекта

...

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

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


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

/* Получить размер буфера для хранения значения атрибута CKA_VALUE*/
printf("Getting object value size*
*************************************************************************/
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_GetAttributeValueDeriveKey(hSession,				// Хэндл открытой с правами Пользователя сессии 
	&gostR3410_12DerivationMech,  			// Механизм ключевого обмена
	hPrivateKey,							// Хэндл закрытого ключа отправителя
	attrGOST28147DerivedKey,				// Шаблон создания общего ключа
	arraysize(attrGOST28147DerivedKey), 	//                          hDerivedKey_1,Размер шаблона
	&hDerivedKey);						// Хэндл общего выработанного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto                                   &attrDerivedKeyValue,	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_1,			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 (ckDeriveParams.pPublicData)
{
	free(ckDeriveParams.pPublicData);
	ckDeriveParams.pPublicData = NULL_PTR;
	ckDeriveParams.ulPublicDataLen = 0;
}
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_1	hDerivedKey);
	hDerivedKey_1 = NULL_PTR;
}
if (rv != CKR_OK)
	printf("\nDeriving failed!\n\n");
else
	printf("Deriving has been completed successfully.\n\n");
		

Маскирование секретного ключа

...

В этом примере мы генерируем случайным образом сессионный ключ (CEK), а затем маскируем его общим ключом KEK, полученным из функции C_Derive() .() .

Code Block
languagecpp
titleМаскирование общего выработанного ключа
/* Размер синхропосылки в байтах */
#define UKM_LENGTH			8
/* Размер симметричного ключа
Code Block
languagecpp
titleМаскирование общего выработанного ключа
/* Размер симметричного ключа ГОСТ 28147-89 в байтах */
#define     GOST_28147_KEY_SIZE     0x20
 
/* Набор параметров КриптоПро A алгоритма ГОСТ 28147-89 */
CK_BYTE 	GOST28147params[]	= { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 }; 
 
/* Параметры для механизма маскирования/демаскирования */
CK_GOSTR3410_KEY_WRAP_PARAMS  ckWrapParams = { GOST28147params;			// Указатель параметры (OID) алгоритма ГОСТ 28147-89 (используетсяв только для C_WrapKey) 
																		// Если NULL_PTR, то используется CKA_GOSTR3411PARAMS. Для C_UnwrapKey должно быть NULL_PTR
 											   sizeof(GOST28147params);	// Длина объектного идентификатора
 											   cbUKM;					// Вектор инициализации (синхропосылки), если NULL_PTR -- используется случайное значение длиной 8 байт
 											   arraysize(cbUKM);		// Длина синхропосылки (в байтах, кратно 8)
 											   hKey;					// Хэндл ключа 
}
 байтах */
#define	GOST_28147_KEY_SIZE	0x20

/* Набор параметров КриптоПро A алгоритма ГОСТ 28147-89 */
CK_BYTE GOST28147params[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 };

CK_BYTE ukm[UKM_LENGTH] = {0x01, 0x02 ,0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; // Синхропосылка

/* Механизм для маскирования/демаскирования ключа */
CK_MECHANISM    ckmWrapMech                 = { CKM_GOST28147_KEY_WRAP, NULL_PTR, 0 };	
 
CK_OBJECT_CLASS ocSecKey 		= CKO_SECRET_KEY; 
CK_UTF8CHAR 	WrapKeyLabel[] 	= { "GOST Wrapped Key" }; 
CK_UTF8CHAR 	UnWrapKeyLabel[] = { "GOST Unwrapped Key" }; 
CK_KEY_TYPE 	KeyType 		= CKK_GOST28147; 
CK_BBOOL 		bTrue 			= CK_TRUE; 
CK_BBOOL 		bFalse 			= CK_FALSE; 

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

/* Шаблон демаскированного ключа */
CK_ATTRIBUTE attrGOST28147UnwrappedKey[] =
{
	{ CKA_CLASS, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)},                    // Объект секретного ключа ГОСТ 28147-89
	{ CKA_LABEL, &UnWrapLabelGOSTUnWrapKeyLabel, sizeof(UnWrapLabelGOSTUnWrapKeyLabel) - 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 для хранения значения атрибута CKA_VALUE */
CK_ATTRIBUTE attrValue = { CKA_VALUE, NULL_PTR, 0 };  
        
CK_OBJECT_HANDLE hDerivedKey_2;           			 // Хэндл выработанного на стороне получателя общего ключа
CK_BYTE_PTR pbtSessionKey = NULL_PTR;                // Указатель на буфер, содержащий сессионный ключ
CK_BYTE_PTR pbtWrappedKey = NULL_PTR;                // Указатель на буфер, содержащий маскированный на стороне отправителя сессионный ключ
CK_ULONG ulWrappedKeySize = 0;                       // Размер буфера со значением маскированного на стороне отправителя сессионного ключа, в байтах
CK_BYTE_PTR pbtUnwrappedKey = NULL_PTR;              // Указатель на буфер, содержащий демаскированный на стороне получателя сессионный ключ
CK_ULONG ulUnwrappedKeySize = 0;                     // Размер буфера со значением демаскированного на стороне получателя сессионного ключа, в байтах
CK_OBJECT_HANDLE hTempKey = NULL_PTR;                // Хэндл ключа, который будет маскироваться/демаскироваться

...

/*Установить параметры в структуре типа CK_MECHANISM /*Установить синхропосылку для маскирования ключа*/
ckmWrapMech.ulParameterLen = 8sizeof(ukm);
GenerateRandomData(ckmWrapMech.ulParameterLen,pParameter (PBYTE *)&ckmWrapMech.pParameter)= ukm;
		
/* Заполнить шаблон сессионного ключа случайными данными */
GenerateRandomData(GOST_28147_KEY_SIZE, &pbtSessionKey);
for (int i = 0;
	 i < arraysize(attrGOST28147KeyToWrap);
	 i++)
	if (attrGOST28147KeyToWrap[i].type == CKA_VALUE)
	{
		attrGOST28147KeyToWrap[i].pValue = pbtSessionKey;
		attrGOST28147KeyToWrap[i].ulValueLen = GOST_28147_KEY_SIZE;
		break;
	}


/*************************************************************************
* Маскирование ключа                                                     *
*************************************************************************/

/* Создать ключ, который будет маскирован */
printf("Creating the GOST 28147-89 key to wrap");
rv = pFunctionList->C_CreateObject(hSession,							// Хэндл сессии, открытой с правами Пользователя
		                           attrGOST28147KeyToWrap,				// Шаблон создаваемого ключа
		                           arraysize(attrGOST28147KeyToWrap),	// Размер шаблона
		                           &hTempKey);							// Хэндл созданного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto wrap_exit;
}
printf(" -> OK\n");
 
/* Получить размер буфера, содержащего значение маскированного ключа */
printf("Defining wrapping key size");
rv = pFunctionList->C_WrapKey(hSession,					// Хэндл сессии, открытой с правами Пользователя		
		                      &ckmWrapMech,				// Механизм маскирования
		                      hDerivedKey_1,			// Хэндл ключа, которым будет маскироваться ключ
		                      hTempKey,	/ Хэндл ключа, которым будет маскироваться ключ
	hTempKey,				// Хэндл ключа, который будет маскирован
		                      NULL_PTR,					// Указатель на буфер с маскированным ключом
		                      &ulWrappedKeySize);		// Размер маскированного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto wrap_exit;
}
printf(" -> OK\n");
 
pbtWrappedKey = (CK_BYTE*)malloc(ulWrappedKeySize);
if (pbtWrappedKey == NULL)
{
	printf("Memory allocation for pbtWrappedKey failed! \n");
	goto wrap_exit;
}		
memset(pbtWrappedKey,
 	  0,
   	  ulWrappedKeySize * sizeof(CK_BYTE));
	
/* Получить маскированный ключ на стороне отправителя */
printf("Wrapping key");
rv = pFunctionList->C_WrapKey(hSession,					// Хэндл сессии, открытой с правами Пользователя		
		                 	  &ckmWrapMech,				// Механизм маскирования
		                      hDerivedKey_1,			// Хэндл ключа, которым будет маскироваться ключ
		                      hTempKey,					// Хэндл ключа, который будет маскирован
		                      pbtWrappedKey,			// Указатель на буфер с маскированным ключом
		                       будет маскирован
	pbtWrappedKey,			// Указатель на буфер с маскированным ключом
	&ulWrappedKeySize);		// Размер маскированного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto wrap_exit;
}
printf(" -> OK\n");
 
/* Распечатать буфер, содержащий маскированный ключ */
printf("Wrapped key data is:\n");
for (int i = 0;
	 i < ulWrappedKeySize;
  		 i++)
{
	printf("%02X ", pbtWrappedKey[i]);
	if ((i + 1) % 9 == 0)
		printf("\n");
}


wrap_exit:
if (hTempKey)
{
	pFunctionList->C_DestroyObject(hSession,
		                           hTempKey);
	hTempKey = NULL_PTR;
}
	
if (rv == CKR_OK)
	printf("\nWrapping has been completed successfully.\n");
else
{
	printf("\nWrapping failed!\n");
	goto exit;
}
 

/*************************************************************************
* Демаскирование ключа                                                   *
*************************************************************************/
printf("Unwrapping key");
rv = pFunctionList->C_UnwrapKey(hSession,								// Хэндл сессии, открытой с правами Пользователя	
	                            &ckmWrapMech,							// Механизм маскирования
	                            hDerivedKey_2,							// Хэндл ключа, которым был маскирован ключ
	                            pbtWrappedKey,							// Указатель на буфер с маскированным ключом
	                            ulWrappedKeySize,						// Размер буфера с маскированным ключом
	                            	// Размер буфера с маскированным ключом
	attrGOST28147UnwrappedKey,				// Указатель на шаблон для демаскированного ключа
	                            arraysize(attrGOST28147UnwrappedKey),	// Размер шаблона для демаскированного ключа
	                            &hTempKey);								// Указатель на буфер с маскированным ключом
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto unwrap_exit;
}
printf(" -> OK\n");
		
/* Получить буфер со значением демаскированного ключа */
printf("Getting unwrapped key value...\n");

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

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

/* Получить значение атрибута CKA_VALUE */
printf("Getting object value");
rv = pFunctionList->C_GetAttributeValue(hSession,   // Хэндл сессии, открытой с правами Пользователя
                                        	hTempKey,	// Хэндл объекта, значение атрибутов которых требуется получить 
                                        	&attrValue, // Указатель на шаблон с атрибутами, значение которых требуется получить
                                        	1);			// Количество строк в шаблоне
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto unwrap_exit;
}
printf(" -> OK\n");
	/* Распечатать буфер со значением демаскированного ключа  */
printf("Unwrapped key data:\n");
for (int i = 0;
     i < attrValue.ulValueLen;
     i++)
{
	printf("%02X ", ((CK_BYTE_PTR)attrValue.pValue)[i]);
	if ((i + 1) % 8 == 0)
		printf("\n");
}

unwrap_exit:
if (hTempKey)
{
	pFunctionList->C_DestroyObject(hSession,
		                           hTempKey);
	hTempKey = NULL_PTR;
}
if (rv == CKR_OK)
	printf("Unwrapping has been completed successfully.\n\n");
else
{
	printf("\nUnwrapping failed!\n\n");
	goto exit;
}
 
/* Сравнить первоначальное значение сессионного ключа со значением демаскированного ключа */
if ((ulUnwrappedKeySize != GOST_28147_KEY_SIZE)
	|| (memcmp(pbtSessionKey,
	           	attrValue.pValue,
	           	GOST_28147_KEY_SIZE) != 0))
	printf("\nThe unwrapped key is not equal to the session key!\n");
else
	printf("The unwrapped key is equal to the session key.\n");

exit:
	printf("Finish");

Вычисление значения хеш-функции

...

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

...

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

...

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

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

...