...
- флаг формата возвращаемого ключа (
CKD_NULL
илиCKD_CPDIVERSIFY_KD
), - значение открытого ключа второй стороны и его размер,
- вектор синхронизации и его длину.
Пример выработки общего ключа парной связи по алгоритму VKO GOST R 34.10-2001 и VKO GOST R 34.10-2012
Code Block | ||||
---|---|---|---|---|
| ||||
/* Значение синхропосылки */ CK_BYTE cbUKM[] = {A9 3C 16 46 18 F0 31 F3}; /* Параметры механизма выработки общего ключа VKO GOST R 34.10-2001 */ CK_GOSTR3410_DERIVE_PARAMS ckDeriveParams = { CKD_CPDIVERSIFY_KDF,// Формат выходных данных: CKD_CPDIVERSIFY_KD - диверсифицированный KEK (для VKO GOST R 34.10-2001), // CKD_NULL - не диверсифицированный KEK NULL_PTR, // Значение открытого ключа 0, // Длина открытого ключа в байтах cbUKM, // Вектор инициализации (синхропосылки) arraysize(cbUKM)}; // Длина синхропосылки в байтах (от 8 байт) /* Механизм выработки общего ключа */ CK_MECHANISM ckmDerivationMech2001 = {CKM_GOSTR3410_DERIVE, NULL_PTR, 0}; CK_MECHANISM ckmDerivationMech2012 = {CKM_GOSTR3410_12_DERIVE, NULL_PTR, 0}; /* Значение открытого ключа получателя */ CK_BYTE cbPubRecipientKey[] = { FF 8D AB 7F 1C 0B 74 A5 AD 7F 0B 5F 8D 5B 3C 44 58 37 98 C9 25 86 40 7E EC 6E AF 00 CB 44 65 A5 22 9A 53 56 32 97 35 80 99 CA 1E 17 21 3A 96 0E 21 FB C6 0F 25 5B 5D 99 4E C4 5C 42 08 7D 06 04 }; 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_OBJECT_HANDLE hDerivedKey_1 = NULL_PTR; // Хэндл выработанного на стороне отправителя общего ключа CK_OBJECT_HANDLE hObject, // Хэндл объекта while(TRUE) { ... /* Выделить необходимое количество памяти для значения атрибута */ ckDeriveParams.pPublicData = (CK_BYTE*)malloc(ckDeriveParams.ulPublicDataLen); if (ckDeriveParams.pPublicData == NULL) { printf("Memory allocation for aSlots failed! \n"); break; } memset(ckDeriveParams.pPublicData, 0, (ckDeriveParams.ulPublicDataLen * sizeof(CK_BYTE))) /* Поместить в структуру типа CK_GOSTR3410_DERIVE_PARAMS открытый ключ получателя */ ckDeriveParams.pPublicData = &cbPubRecipientKey; ckDeriveParams.ulPublicDataLen = arraysize(cbPubRecipientKey); /* Поместить в структуру типа CK_MECHANISM параметры, необходимые для выработки общего ключа */ ckmDerivationMech.pParameter = &ckDeriveParams; ckmDerivationMech.ulParameterLen = sizeof(ckDeriveParams); /* Выработать общий ключ ГОСТ 28147-89 на основании закрытого ключа отправителя и открытого ключа получателя */ printf("C_DeriveKey"); rv = pFunctionList->C_DeriveKey(hSession, // Хэндл открытой с правами Пользователя сессии &ckmDerivationMech2001, // Механизм ключевого обмена hPrivateKey, // Хэндл закрытого ключа отправителя attrGOST28147DerivedKey, // Шаблон создания общего ключа arraysize(attrGOST28147DerivedKey), // Размер шаблона &hDerivedKey_1); // Хэндл общего выработанного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Получить размер буфера для хранения значения атрибута CKA_VALUE*/ printf("Getting object value size"); rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл открытой с правами Пользователя сессии hDerivedKey_1, // Хэндл общего ключа &attrDerivedKeyValue, // Шаблон получения значения атрибута 1); // Количество атрибутов в шаблоне if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Выделить необходимое количество памяти для значения атрибута */ attrDerivedKeyValue.pValue = (CK_BYTE*)malloc(attrDerivedKeyValue.ulValueLen); if (attrDerivedKeyValue.pValue == NULL) { printf("Memory allocation for attrDerivedKeyValue failed! \n"); break; } memset(attrDerivedKeyValue.pValue, 0, (attrDerivedKeyValue.ulValueLen * sizeof(CK_BYTE))); /* Получить значение общего ключа ГОСТ 28147-89 */ printf("Getting object value"); rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл открытой с правами Пользователя сессии hDerivedKey_1, // Хэндл общего ключа &attrDerivedKeyValue, // Шаблон получения значения атрибута 1); // Количество атрибутов в шаблоне if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Распечатать буфер со значением общего ключа ГОСТ 28147-89 */ printf("Derived key data is:\n"); for (i = 0; i < attrDerivedKeyValue.ulValueLen; i++) { printf("%02X ", attrDerivedKeyValue.pValue[i]); if ((i + 1) % 8 == 0) printf("\n"); } break; } if (ckDeriveParams.pPublicData) { free(ckDeriveParams.pPublicData); ckDeriveParams.pPublicData = NULL_PTR; ckDeriveParams.ulPublicDataLen = 0; } if (attrDerivedKeyValue.pValue) { free(attrDerivedKeyValue.pValue); attrDerivedKeyValue.pValue = NULL_PTR; attrDerivedKeyValue.ulValueLen= 0; } if (rv != CKR_OK) { pFunctionList->C_DestroyObject(hSession, hDerivedKey_1); hDerivedKey_1 = NULL_PTR; } if (rv != CKR_OK) printf("\nDeriving failed!\n\n"); else printf("Deriving has been completed successfully.\n\n"); |
...
Особенности подписи данных на Рутокен PINPad
...
Подпись данных отдельными механизмами хеширования и подписи
...
При использовании отдельных механизмов хеширования и подписи сообщение сначала хешируется функциями C_DigestInit()
и C_Digest()
, а затем значение хеша подписывается функциями C_SignInit
()/
и C_EX_SignInvisibleInit()
C_Sign
()/
C_EX_SignInvisible().
В функцию C_DigestInit()
передается механизм хеширования (например, CKM_GOSTR3411
), а в функцию C_Digest()
– само сообщение. При вызове функция C_Digest()
вычисляет хеш сообщения и возвращает управление вместе со значением хеша. Исходное сообщение и значение хеша запоминаются в памяти Рутокен PINPad.
Затем вызывается функция инициализации подписи C_SignInit()/
C_EX_SignInvisibleInit()
, в которую передается механизм подписи (например, CKM_GOSTR3410
), и сама функция подписи C_Sign
()/
с переданным в нее значением хеша.C_EX_SignInvisible()
Если подпись выполняется ключевой парой с атрибутом CKA_VENDOR_KEY_CONFIRM_OP
равным true
, то при вызове функции C_EX_SignInvisible()
подпись выполняется в автоматическом режиме. Рутокен PINPad сверяет сохраненное значение хеша с переданным функцией C_EX_SignInvisible()
и в случае совпадения выполняет подпись хеша и возвращает блок сформированной подписи размером 64 байта для механизма CKM_GOSTR3410
и 128 байт для механизма CKM_GOSTR3410_512
. Если значения хешей не совпадают, функция C_EX_SignInvisible
()
возвращает ошибку.
Если подпись выполняется ключевой парой с атрибутом CKA_VENDOR_KEY_CONFIRM_OP
равным true
, то при вызове функции C_Sign
()
Рутокен PINPad сверяет сохраненное значение хеша с переданным функцией и в случае совпадения отображает на экране текст исходного сообщения. Функция C_Sign()
ожидает нажатия пользователем кнопки подтверждения или отказа от операции на экране Рутокен PINPad. Если значения хешей не совпадают, функция C_Sign()
возвращает ошибку без вывода на экране текста сообщения.
Если пользователь подтверждает выполнение операции, то сохраненное значение хеша в Рутокен PINPad подписывается, и функция C_Sign()
возвращает управление и блок сформированной цифровой подписи размером 64 байта для механизма CKM_GOSTR3410
и 128 байт для механизма CKM_GOSTR3410_512
.
Если пользователь отклоняет операцию подписи, функция C_Sign()
немедленно возвращает управление и код ошибки. Вычисления цифровой подписи не производится.
...
Пример подписи данных по алгоритму ГОСТ Р 34.10-2001 отдельными механизмами хеширования и подписи для всех устройств Рутокен
...
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 отдельными механизмами хеширования и подписи для всех устройств Рутокен
...
При использовании совместного механизма и хеширование, и подпись выполняются функцией C_Sign()
. Сначала в функцию C_SignInit()
передается совместный механизм (например, CKM_GOSTR3410_WITH_GOSTR3411
), а затем в функцию C_Sign()
– сообщение.
Пример подписи данных по алгоритму ГОСТ Р 34.10-2001 совместным механизмом хеширования и подписи (кроме Рутокен PINPad)
...
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 совместным механизмом хеширования и подписи (кроме Рутокен PINPad)
...
При использовании совместного механизма и хеширование, и подпись выполняются функцией
. Сначала в функцию C_EX_SignInvisible()
передается совместный механизм (например, C_EX_SignInvisibleInit()
CKM_GOSTR3410_WITH_GOSTR3411
), а затем в функцию
– сообщение.C_EX_SignInvisible()
При вызове функции C_EX_SignInvisible()
подпись будет выполнена в автоматическом режиме без отображения подписываемого сообщения на экране Рутокен PINPad.
Пример подписи данных по алгоритму ГОСТ Р 34.10-2001 совместным механизмом хеширования и подписи для Рутокен PINPad
...
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 совместным механизмом хеширования и подписи для Рутокен PINPad
...