Page tree

Versions Compared

Key

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

...

  1. kdf – идентификатор механизма диверсификации. Может быть использован один из двух механизмов:
    • CKD_NULL - нет диверсификации
    • CKD_CPDIVERSIFY_KDF
  2. pPublicData – открытый ключ получателя
  3. pUKM – имитовставкасинхропосылка

VKO GOST R  34.10-2012 (256 бит и 512 бит)

...

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

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

...

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

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

...

Code Block
languagecpp
titleМаскирование общего выработанного ключа
/* ИмитовставкаСинхропосылка для механизма импорта и экспорта ключа алгоритма KExp15 на двойственном ключе Кузнечик */
CK_BYTE gostKuznechikKExp15Ukm[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* ИмитовставкаСинхропосылка для механизма импорта и экспорта ключа алгоритма KExp15 на двойственном ключе Магма */
CK_BYTE gostMagmaKExp15Ukm[] = { 0x00, 0x00, 0x00, 0x00 };

/* Механизм импорта и экспорта ключа по алгоритму KExp15 на двойственном ключе Кузнечик */
CK_MECHANISM gostKuznechikKExp15Mech = { CKM_KUZNECHIK_KEXP_15_WRAP, &gostKuznechikKExp15Ukm, sizeof(gostKuznechikKExp15Ukm) };
/* Механизм импорта и экспорта ключа по алгоритму KExp15 на двойственном ключе Кузнечик */
CK_MECHANISM gostMagmaKExp15Mech = { CKM_MAGMA_KEXP_15_WRAP, &gostMagmaKExp15Ukm, sizeof(gostMagmaKExp15Ukm) };


CK_MECHANISM_PTR gostKExp15Mech = &gostKuznechikKExp15Mech;
//CK_MECHANISM gostKExp15Mech = gostMagmaKExp15Mech;

/* DEMO-метка для сессионного ключа */
CK_UTF8CHAR sessionKeyLabel[] = { "GOST 28147-89 key to wrap" };
CK_UTF8CHAR sessionKuznechikKeyLabel[] = { "Kuznechik key to wrap" };
CK_UTF8CHAR sessionMagmaKeyLabel[] = { "Magma key to wrap" };
CK_OBJECT_CLASS secretKeyObject = CKO_SECRET_KEY;
CK_KEY_TYPE keyTypeGost28147 = CKK_GOST28147;
CK_KEY_TYPE keyTypeKuznechik = CKK_KUZNECHIK;
CK_KEY_TYPE keyTypeMagma = CKK_MAGMA;
CK_BBOOL attributeTrue = CK_TRUE;
CK_BBOOL attributeFalse = CK_FALSE;

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

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

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


/*************************************************************************
* Шаблон демаскированного сессионного ключа типа Кузнечик                *
*************************************************************************/
CK_ATTRIBUTE unwrapSessionKeyTemplate[] =
{
	{ CKA_LABEL, &sessionKuznechikKeyLabel, sizeof(sessionKuznechikKeyLabel) - 1 },	// Метка ключа
	{ CKA_CLASS, &secretKeyObject, sizeof(secretKeyObject) },						// Класс - секретный ключ
	{ CKA_KEY_TYPE, &keyTypeKuznechik, sizeof(keyTypeKuznechik)},					// Тип ключа - Кузнечик
	{ 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 sessionKeyTemplate[] =
//{
//	{ CKA_LABEL, &sessionMagmaKeyLabel, sizeof(sessionMagmaKeyLabel) - 1 },// Метка ключа
//	{ CKA_CLASS, &secretKeyObject, sizeof(secretKeyObject) },              // Класс - секретный ключ
//	{ CKA_KEY_TYPE, &keyTypeMagma, sizeof(keyTypeMagma)},				   // Тип ключа - Магма
//	{ 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)}              // Ключ может быть извлечен в открытом виде
//};

/*************************************************************************
* Шаблон демаскированного сессионного ключа типа ГОСТ 28147-89           *
*************************************************************************/
//CK_ATTRIBUTE sessionKeyTemplate[] =
//{
// 	{ CKA_LABEL, &sessionKeyLabel, sizeof(sessionKeyLabel) - 1 },          // Метка ключа
// 	{ CKA_CLASS, &secretKeyObject, sizeof(secretKeyObject) },              // Класс - секретный ключ
// 	{ CKA_KEY_TYPE, &keyTypeGost28147, sizeof(keyTypeGost28147)},          // Тип ключа - ГОСТ 28147-89
// 	{ 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 для хранения значения атрибута CKA_VALUE */
CK_ATTRIBUTE attrValue = { CKA_VALUE, NULL_PTR, 0 };

CK_OBJECT_HANDLE hDerivedTwinKey;           		 // Хэндл выработанного двйоственного ключа
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;                // Хэндл ключа, который будет маскироваться/демаскироваться

...

/* Заполнить шаблон сессионного ключа случайными данными */
GenerateRandomData(GOST_28147_KEY_SIZE, &pbtSessionKey);
for (int i = 0; i < arraysize(sessionKeyTemplate); i++)
	if (sessionKeyTemplate[i].type == CKA_VALUE)
	{
		sessionKeyTemplate[i].pValue = pbtSessionKey;
		sessionKeyTemplate[i].ulValueLen = GOST_KUZNECHIK_KEY_SIZE;
		break;
	}

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

/* Создать ключ, который будет маскирован */
printf("Creating the GOST 28147-89 key to wrap");
rv = pFunctionList->C_CreateObject(hSession,	// Хэндл сессии, открытой с правами Пользователя
	sessionKeyTemplate,					// Шаблон создаваемого ключа
	arraysize(sessionKeyTemplate),		// Размер шаблона
	&hTempKey);							// Хэндл созданного ключа
if (rv != CKR_OK)
{
	printf(" -> Failed\n");
	goto wrap_exit;
}
printf(" -> OK\n");

/* Получить размер буфера, содержащего значение маскированного ключа */
printf("Defining wrapping key size");
rv = pFunctionList->C_WrapKey(hSession,					// Хэндл сессии, открытой с правами Пользователя		
	gostKExp15Mech,			// Механизм маскирования
	hDerivedTwinKey,		// Хэндл ключа, которым будет маскироваться ключ
	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_PTR)
{
	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,					// Хэндл сессии, открытой с правами Пользователя		
	gostKExp15Mech,			// Механизм маскирования
	hDerivedTwinKey,		// Хэндл ключа, которым будет маскироваться ключ
	hTempKey,				// Хэндл ключа, который будет маскирован
	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,								// Хэндл сессии, открытой с правами Пользователя	
	gostKExp15Mech,							// Механизм маскирования
	hDerivedTwinKey,						// Хэндл ключа, которым был маскирован ключ
	pbtWrappedKey,							// Указатель на буфер с маскированным ключом
	ulWrappedKeySize,						// Размер буфера с маскированным ключом
	unwrapSessionKeyTemplate,				// Указатель на шаблон для демаскированного ключа
	arraysize(unwrapSessionKeyTemplate),	// Размер шаблона для демаскированного ключа
	&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_PTR)
{
	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_KUZNECHIK_KEY_SIZE)
	|| (memcmp(pbtSessionKey,
		attrValue.pValue,
		GOST_KUZNECHIK_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 совместным механизмом хеширования и подписи

...

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

...