...
Code Block | ||||
---|---|---|---|---|
| ||||
CK_C_EX_GetFunctionListExtended pfGetFunctionListEx = NULL_PTR; // Указатель на функцию C_EX_GetFunctionListExtended CK_FUNCTION_LIST_EXTENDED_PTR pFunctionListEx = NULL_PTR; // Указатель на список функций расширения PKCS#11, хранящийся в структуре CK_FUNCTION_LIST_EXTENDED CK_TOKEN_INFO_EXTENDED tokenInfoEx; // Структура данных типа CK_TOKEN_INFO_EXTENDED с информацией о токене while(TRUE) { ... printf("Determining token type"); /* Получить адрес функции запроса структуры с указателями на функции расширения */ pfGetFunctionListEx = (CK_C_EX_GetFunctionListExtended)GetProcAddress(hModule, "C_EX_GetFunctionListExtended"); if (pfGetFunctionListEx == NULL_PTR) { printf(" -> Failed\n"); break; } /* Получить структуру с указателями на функции расширения */ rv = pfGetFunctionListEx(&pFunctionListEx); if (rv != CKR_OK) { printf(" -> Failed\n"); break; } memset(&tokenInfoEx, 0, sizeof(CK_TOKEN_INFO_EXTENDED)); tokenInfoEx.ulSizeofThisStructure = sizeof(CK_TOKEN_INFO_EXTENDED); /* Получить расширенную информацию о подключенном токене */ rv = pFunctionListEx->C_EX_GetTokenInfoExtended(aSlots[0], // Идентификатор слота, к которому подключен токен &tokenInfoEx); // Буфер для помещения информации о токене if (rv != CKR_OK) { printf(" -> Failed\n"); break; } /* Определить класс токена */ if (tokenInfoEx.ulTokenClass == TOKEN_CLASS_S) { bIsRutokenPINPad = FALSE; printf(": Rutoken / Rutoken S\n"); } else if (tokenInfoEx.ulTokenClass == TOKEN_CLASS_ECP) { bIsRutokenPINPad = FALSE; printf(": Rutoken ECP\n"); } else if (tokenInfoEx.ulTokenClass == TOKEN_CLASS_LITE) { bIsRutokenPINPad = FALSE; printf(": Rutoken Lite\n"); } else if (tokenInfoEx.ulTokenClass == TOKEN_CLASS_WEB) { bIsRutokenPINPad = FALSE; printf(": Rutoken WEB\n"); } else if (tokenInfoEx.ulTokenClass == TOKEN_TYPE_RUTOKEN_PINPAD_FAMILY) { bIsRutokenPINPad = TRUE; printf(": Rutoken PINPad\n"); } else { bIsRutokenPINPad = FALSE; printf(": undefined\n"); } break; } |
Открытие и закрытие сессии
...
CKM_MD2
для хеширования алгоритмом MD2,CKM_MD5
для хеширования алгоритмом MD5,CKM_SHA_1
для хеширования алгоритмом SHA-1,CKM_GOSTR3411
для хеширования алгоритмом ГОСТ Р 34.11.94,CKM_GOSTR3411_12_256
для хеширования алгоритмом ГОСТ Р 34.11.2012 с длиной значения 256 бит,CKM_GOSTR3411_12_512
для хеширования алгоритмом ГОСТ Р 34.11.2012 с длиной закрытого ключа 512 бит.
Подпись и проверка подписи
Поддерживаемые механизмы
Хеширование данных
Для хеширования данных служат функции C_DigestInit()
и C_Digest()
. Сначала операцию хеширования нужно инициализировать через C_DigestInit()
, передав в нее идентификатор сессии и ссылку на механизм хеширования. Затем размер буфера хешированных данных можно определить, вызвав
, и выполнить хеширование данных, вызвав C_Digest
()
второй раз.C_Digest
()
Code Block | ||||
---|---|---|---|---|
| ||||
/* Данные для подписи в виде двоичной строки */
CK_BYTE pbtData[] = { 0x3C, 0x21, 0x50, 0x49, 0x4E, 0x50, 0x41, 0x44, 0x46, 0x49, 0x4C, 0x45, 0x20, 0x52, 0x55, 0x3E,
0x3C, 0x21, 0x3E, 0xED, 0xE5, 0xE2, 0xE8, 0xE4, 0xE8, 0xEC, 0xFB, 0xE9, 0x20, 0xF2, 0xE5, 0xEA };
while(TRUE)
{
...
/* Инициализировать операцию хеширования */
printf("C_DigestInit");
rv = pFunctionList->C_DigestInit(hSession,
&HashMech);
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
/* Определить размер хешированных данных */
printf("C_Digest step 1");
rv = pFunctionList->C_Digest( hSession,
pbtData,
ulData,
pbtHash,
&ulHashSize);
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
pbtHash = (CK_BYTE*)malloc(ulHashSize);
memset(pbtHash,
0,
(ulHashSize * sizeof(CK_BYTE)));
/* Сформировать хеш от исходных данных */
printf("C_Digest step 2");
rv = pFunctionList->C_Digest(hSession,
pbtData,
ulData,
pbtHash,
&ulHashSize);
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
break;
}
|
Подпись и проверка подписи
Поддерживаемые механизмы
Устройства Рутокен поддерживают следующие Устройства Рутокен поддерживают следующие механизмы подписи:
CKM_GOSTR3410
подписи алгоритмом ГОСТ Р 34.10.2001,CKM_GOSTR3410_WITH_GOSTR3411
для совместного хеширования алгоритмомCKM_GOSTR3411
и подписи алгоритмом CKM_GOSTR3410,CKM_GOSTR3410_512
для подписи алгоритмом ГОСТ Р 34.10.2012 с длиной закрытого ключа 512 бит,CKM_GOSTR3410_WITH_GOSTR3411_12_256
для совместного хеширования алгоритмомCKM_GOSTR3411_12_256
и подписи на ключе длиной 256 бит,CKM_GOSTR3410_WITH_GOSTR3411_12_512
для совместного хеширования алгоритмомCKM_GOSTR3411_12_512
и подписи на ключе длиной 512 бит,CKM_RSA_PKCS
для подписи алгоритмом RSA.
...
Для подписи сырых данных служат функции C_SignInit()
и C_Sign()
. Сначала операцию подписи нужно инициализировать через Cчерез C_SignInit()
, передав в нее идентификатор сессии, механизма и закрытого ключа. Затем размер буфера подписанных данных можно определить, вызвав Cвызвав C_Sign()
, и подписать данные, вызвав C_Sign()
второй раз.
При использовании совместных алгоритмов хеширования и подписи (например, CKM_GOSTR3410_WITH_GOSTR3411)
в C_Sign() передается открытый текст для подписи, при использовании только алгоритма подписи (например, CKM_GOSTR3410
) -- уже прохешированные данные.
...
Code Block | ||||
---|---|---|---|---|
| ||||
/* Механизм подписи/проверки подписи по алгоритму ГОСТ Р 34.10-2001 */ CK_MECHANISM SigVerMech = {CKM_GOSTR3410, NULL_PTR, 0}; while(TRUE) { ... /* Инициализировать операцию подписи данных */ printf("C_SignInit"); rv = pFunctionList->C_SignInit( hSession, // Хэндл сессии &SigVerMech, // Механизм подписи hPrivateKey ); // Хэндл закрытого ключа if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Определить размер подписанных данных */ printf("C_Sign step 1"); rv = pFunctionList->C_Sign( hSession, // Хэндл сессии pbHash, // Буфер с данными для подписи ulHashSize, // Длина подписываемых данных pbtSignature, // Буфер с подписанными данными &ulSignatureSize); // Длина подписанных данных if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); pbtSignature = (CK_BYTE*)malloc(ulSignatureSize); memset( pbtSignature, 0, ulSignatureSize * sizeof(CK_BYTE)); /* Подписать исходные данные */ printf("C_Sign step 2"); rv = pFunctionList->C_Sign( hSession, // Хэндл сессии pbHash, // Буфер с данными для подписи ulHashSize, // Длина подписываемых данных pbtSignature, // Буфер с подписанными данными &ulSignatureSize); // Длина подписанных данных if (rv != CKR_OK) if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Распечатать буфер, содержащий подпись */ printf("Signature buffer is: \n"); for (i = 0; i < ulSignatureSize; i++) { printf("%02X ", pbtSignature[i]); if ((i + 1) % 8 == 0) printf("\n"); } |
...