...
- kdf – идентификатор механизма диверсификации. Может быть использован один из двух механизмов:
- CKD_NULL - нет диверсификации
- CKD_CPDIVERSIFY_KDF
- pPublicData – открытый ключ получателя
- pUKM – имитовставкасинхропосылка
VKO GOST R 34.10-2012 (256 бит и 512 бит)
...
- pPublicData – открытый ключ получателя
- pUKM – имитовставкасинхропосылка.
Пример выработки общего ключа парной связи по алгоритму VKO GOST R 34.10-2012
...
Для получения сеансового ключ (CEK), зашифрованного на KEK с имитовставкой синхропосылкой CEK, необходимо после получения ключа функцией C_DeriveKey() использовать функцию маскирования C_WrapKey().
Для выработки сеансового ключ (CEK) в оперативной памяти токена, зашифрованного на KEK с имитовставкой CEKсинхропосылкой CEK, необходимо использовать функцию расширения C_EX_WrapKey().
...
Code Block | ||||
---|---|---|---|---|
| ||||
/* ИмитовставкаСинхропосылка для механизма импорта и экспорта ключа алгоритма 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 отдельными механизмами хеширования и подписи
...