...
Warning |
---|
Устройства Рутокен, сертифицированные ФСБ, не поддерживают создание (импорт) ключей функцией |
...
Warning |
---|
Устройства Рутокен, сертифицированные ФСБ, не поддерживают создание (импорт) ключей функцией |
...
CKK_GENERIC_SECRET
для абстрактных ключей произвольной длины,CKK_GOST28147
для ключей ГОСТ 28147-89,CKK_MAGMA
для использования в алгоритмах шифрования ГОСТ 34.12-2018 (ГОСТ Р 34.12-2015) с длиной блока 128 бит,CKK_KUZNECHIK
для использования в алгоритмах шифрования ГОСТ 34.12-2018 (ГОСТ Р 34.12-2015) с длиной блока 64 бит,CKK_MAGMA_TWIN_KEY
для использования в алгоритме экспорта и импорта ключей ГОСТ Р 1323565.1.017-2018, построенном на основании блочного шифра «Магма»,CKK_KUZNECHIK_TWIN_KEY
для использования в алгоритме экспорта и импорта ключей ГОСТ Р 1323565.1.017-2018, построенном на основании блочного шифра «Кузнечик»,
...
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 };
/* Механизм выработки имитовставки ГОСТ 28147-89 */
CK_MECHANISM gost28147MacMech = {CKM_GOST28147_MAC, NULL_PTR, 0};
/* Механизм выработки имитовставки ГОСТ Р 34.12-2015 */
CK_MECHANISM kuznechikMacMech = { CKM_KUZNECHIK_MAC, NULL_PTR, 0 };
CK_MECHANISM magmaMacMech = { CKM_MAGMA_MAC, NULL_PTR, 0 };
CK_BYTE_PTR pbtMac = NULL_PTR; // Указатель на буфер для значения MAC
CK_ULONG ulMacSize = 0; // Размер буфера в байтах
while(TRUE)
{
...
/* Инициализировать операцию взятия MAC*/
printf("C_SignInit");
rv = functionList->C_SignInit(hSession, // Хэндл сессии
&kuznechikMacMech, // Механизм взятия MAC
hSecretKey); // Хендл секретного ключа, на котором вычисляем MAC
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
/* Определить размер значения MAC */
printf("C_Sign step 1");
rv = pFunctionList->C_Sign( hSession, // Хэндл сессии
pbtData, // Буфер с данными для хеширования
arraysize(pbtData), // Размер данных для хеширования
pbtMac, // Буфер для вычисленного значения хеша
&ulMacSize); // Размер значения хеша
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
pbtMac = (CK_BYTE*)malloc(ulMacSize);
if (pbtHash == NULL)
{
printf("Memory allocation for pbtMac failed! \n");
break;
}
memset(pbtMac,
0,
(ulMacSize * sizeof(CK_BYTE)));
/* Вычислить MAC от исходных данных */
printf("C_Sign step 2");
rv = pFunctionList->C_Sign( hSession, // Хэндл сессии
pbtData, // Буфер с данными для хеширования
arraysize(pbtData), // Размер данных для хеширования
pbtMac, // Буфер для вычисленного значения хеша
&ulMacSize); // Размер значения хеша
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
break;
}
|
...
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 };
/* Механизм выработки MAC ГОСТ Р 34.12-2015 */
CK_MECHANISM kuznechikMacMech = { CKM_KUZNECHIK_MAC, NULL_PTR, 0 };
CK_MECHANISM magmaMacMech = { CKM_MAGMA_MAC, NULL_PTR, 0 };
while(TRUE)
{
...
/* Инициализировать операцию проверки MAC*/
printf("C_VerifyInit");
rv = functionList->C_VerifyInit(hSession, // Хэндл сессии
&kuznechikMacMech, // Механизм взятия MAC
hSecretKey); // Хендл секретного ключа, на котором вычисляем MAC
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
/* Проверка MAC */
printf("C_Verify");
rv = pFunctionList->C_Verify( hSession, // Хэндл сессии
pbtData, // Буфер с данными для хеширования
arraysize(pbtData), // Размер данных для хеширования
pbtMac, // Буфер для вычисленного значения хеша
&ulMacSize); // Размер значения хеша
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
break;
}
|
...
Устройства Рутокен поддерживают следующие механизмы подписи:
CKM_GOSTR3410
подписи алгоритмом ГОСТ Р 34.10.2001 и ГОСТ Р 34.10.2012 с длиной закрытого ключа 256 бит,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.CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS
для алгоритма взятия хеша с последующим взятием подписи по алгоритму RSACKM_ECDSA
для подписи алгоритмом ECDSA.
...
Подпись данных отдельными механизмами хеширования и подписи
...
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 отдельными механизмами хеширования и подписи для всех устройств Рутокен
...
При использовании совместного механизма и хеширование, и подпись выполняются функцией C_Sign()
. Сначала в функцию C_SignInit()
передается совместный механизм (например, CKM_GOSTR3410_WITH_GOSTR3411
), а затем в функцию C_Sign()
– сообщение.
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 совместным механизмом хеширования и подписи
...
Пример подписи данных по алгоритму ECDSA отдельными механизмами хеширования и подписи
...
Code Block | ||||
---|---|---|---|---|
| ||||
while(TRUE) { ... /* Инициализировать операцию проверки подписи */ printf(" C_VerifyInit"); rv = pFunctionList->C_VerifyInit(hSession, // Хэндл сессии &SigVerMech, // Механизм подписи hPublicKey); // Хэндл открытого ключа if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Проверить подпись для исходных данных */ printf(" C_Verify"); rv = pFunctionList->C_Verify(hSession, // Хэндл сессии pbHash, // Буфер с значением хеша исходногосообщения ulHashSize, // Длина буфера pbtSignature, // Буфер с подписью ulSignatureSize); // Длина подписи if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); break; } ... if (pbtSignature) { free(pbtSignature); pbtSignature = NULL_PTR; } if (pbHash) { free(pbHash); pbHash= NULL_PTR; } |
...
Поточная подпись и
...
проверка подписи
При работе с большим количеством данных бывает удобно отправлять данные токену частями. При таком режиме работе с токеном необходимо использовать функции C_SignInit/C_VerifyInit
, C_SignUpdate/C_VerifyUpdate
и C_SignFinal/C_VerifyFinal
.
Code Block | ||||
---|---|---|---|---|
| ||||
/* Инициализировать операцию подписи данных */
printf("C_SignInit");
rv = pFunctionList->C_SignInit( hSession, // Хэндл сессии
&SigVerMech256, // Механизм подписи (SigVerMech256 или SigVerMech512)
hPrivateKey ); // Хэндл закрытого ключа
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
for (size_t i=0; i < dataLen; i+=blockLen)
{
size_t len = (dataLen-i) < blockLen? (dataLen-i) : blockLen;
// подпись отдельных блоков данных
rv = pFunctionList->C_SignUpdate( hSession, // Хэндл сессии
pData + i, // Буфер с данными для подписи
len); // Длина подписываемых данных
if (rv != CKR_OK)
break;
}
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
/* Определить размер подписи*/
printf("C_SignFinal step 1");
rv = pFunctionList->C_SignFinal(hSession, // Хэндл сессии
pbtSignature, // Буфер с подписью
&ulSignatureSize); // Длина подписи
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n");
pbtSignature = (CK_BYTE*)malloc(ulSignatureSize);
if (pbtSignature == NULL)
{
printf("Memory allocation for pbtSignature failed! \n");
break;
}
memset( pbtSignature,
0,
ulSignatureSize * sizeof(CK_BYTE));
/* Подписать исходные данные */
printf("C_SignFinal step 2");
rv = pFunctionList->C_SignFinal(hSession, // Хэндл сессии
pbtSignature, // Буфер с подписью
&ulSignatureSize); // Длина подписи
if (rv != CKR_OK)
{
printf(" -> Failed\n");
break;
}
printf(" -> OK\n"); |
Шифрование и расшифрование
Поддерживаемые механизмы
Устройства Рутокен поддерживают следующие механизмы шифрования:
CKM_GOST28147_ECB
для шифрования алгоритмом ГОСТ 28147-89 в режиме простой замены,CKM_GOST28147
для шифрования алгоритмом ГОСТ 28147-89 в режиме гаммирования с обратной связью (программное и аппаратное),CKM_KUZNECHIK_ECB
для шифрования алгоритмом Кузнечик в режиме простой замены (ГОСТ 34.13-2018),CKM_KUZNECHIK_CTR_ACPKM
для шифрования алгоритмом Кузнечик в режиме гаммирования CTR с мешингом ACPKM (Р 1323565.1.017-2018),CKM_MAGMA_ECB
для шифрования алгоритмом Магма в режиме простой замены (ГОСТ 34.13-2018),CKM_MAGMA_CTR_ACPKM
для шифрования алгоритмом Магма в режиме гаммирования CTR с мешингом ACPKM (Р 1323565.1.017-2018),CKM_RSA_PKCS
для шифрования алгоритмом RSA.
Warning | ||
---|---|---|
| ||
Так как в режиме простой замены (механизм |
Поддерживаемые механизмы
Устройства Рутокен поддерживают следующие механизмы шифрования:
CKM_GOST28147_ECB
для шифрования алгоритмом ГОСТ 28147-89 в режиме простой замены,CKM_GOST28147
для шифрования алгоритмом ГОСТ 28147-89 в режиме гаммирования с обратной связью (программное и аппаратное),CKM_KUZNECHIK_ECB
для шифрования алгоритмом Кузнечик в режиме простой замены (ГОСТ 34.13-2018),CKM_KUZNECHIK_CTR_ACPKM
для шифрования алгоритмом Кузнечик в режиме гаммирования CTR с мешингом ACPKM (ГОСТ 34.13-2018),CKM_MAGMA_ECB
для шифрования алгоритмом Магма в режиме простой замены (ГОСТ 34.13-2018),CKM_MAGMA_CTR_ACPKM
для шифрования алгоритмом Магма в режиме гаммирования CTR с мешингом ACPKM (ГОСТ 34.13-2018),CKM_RSA_PKCS
для шифрования алгоритмом RSA.
Warning | ||
---|---|---|
| ||
Так как в режиме простой замены (механизм |
...
Сначала операцию шифрования нужно инициализировать вызовом функции C_EncryptInit()
, передав в нее идентификатор сессии, механизма и секретного ключа. В параметрах механизмов для ГОСТ 28147-89 и ГОСТ Р 34.12-2015 можно задать вектор инициализации и его длину.
...
Code Block | ||||
---|---|---|---|---|
| ||||
/* Данные для шифрования */ CK_BYTE pbtData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00 }; CK_BYTE IV[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; // Значение вектора инициализации для алгоритма ГОСТ 28147-89 // Механизмы CKM_KUZNECHIK_CTR_ACPKM и CKM_MAGMA_CTR_ACPKM используют два параметра: // период смены ключа и синхропосылку, длина которой равна половине длины блока. // Параметры задаются в виде последовательно записанного периода смены ключа 32-битного целого, // представленного в BigEndian формате и синхропосылки в виде байтового массива. // Если период смены ключа установлен в нуль, ключ по алгоритму ACPKM не меняется и механизм совпадает с режимом CTR, описанном в ГОСТ Р 34.13-2018. CK_BYTE kuznechikEncMechParams[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; // Параметры алгоритма Кузнечик ГОСТ Р 34.12-2015 CK_BYTE magmaEncMechParams[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; // Параметры алгоритма Магма ГОСТ Р 34.12-2015 /* Механизм шифрования/расшифрования */ CK_MECHANISM EncDecStreamMech = {CKM_GOST28147, IV, sizeof(IV)}; // по алгоритму ГОСТ 28147-89 в режиме гаммирования с обратной связью // { CKM_KUZNECHIK_CTR_ACPKM, &kuznechikEncMechParams, sizeof(kuznechikEncMechParams) }; // по алгоритму Кузнечик ГОСТ Р 34.12-2015 в режиме гаммирования CTR с мешингом ACPKM // { CKM_MAGMA_CTR_ACPKM, &magmaEncMechParams, sizeof(magmaEncMechParams) }; // по алгоритму Магма ГОСТ Р 34.12-2015 в режиме гаммирования CTR с мешингом ACPKM CK_BYTE_PTR pbtEncryptedData = NULL_PTR; // Указатель на буфер, содержащий зашифрованные данные CK_ULONG ulEncryptedDataSize = 0; // Размер буфера с зашифрованными данными, в байтах CK_ULONG ulBlockSize = 32; // Размер блока данных, в байтах CK_ULONG ulCurrentPosition = 0; // Текущее начало блока CK_ULONG ulRestLen = 0; // Размер оставшегося буфера, в байтах while(TRUE) { ... /* Инициализировать операцию шифрования */ printf("C_EncryptInit"); rv = pFunctionList->C_EncryptInit(hSession, // Хэндл сессии &EncDecStreamMech, // Механизм шифрования hSecKey); // Хэндл секретного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Зашифровать открытый текст */ ulEncryptedDataSize = arraysize(pbtData); ulRestLen = arraysize(pbtData); pbtEncryptedData = (CK_BYTE*)malloc(ulEncryptedDataSize); if (pbtEncryptedData == NULL) { printf("Memory allocation for pbtEncryptedData failed! \n"); break; } memset( pbtEncryptedData, 0, (ulEncryptedDataSize * sizeof(CK_BYTE))); while (ulRestLen) { if (ulBlockSize > ulRestLen) ulBlockSize = ulRestLen; printf("Block size: %u B (Total: %u of %u) ", ulBlockSize, ulCurrentPosition + ulBlockSize, ulEncryptedDataSize); rv = pFunctionList->C_EncryptUpdate(hSession, // Хэндл сессии pbtData + ulCurrentPosition, // Буфер с блоком данных для шифрования ulBlockSize, // Размер блока, в байтах pbtEncryptedData + ulCurrentPosition, // Буфер с блоком зашифрованных данных &ulBlockSize); // Размер блока, в байтах if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); ulCurrentPosition += ulBlockSize; ulRestLen -= ulBlockSize; } if (rv != CKR_OK) break; printf("Finalizing encryption"); rv = pFunctionList->C_EncryptFinal( hSession, // Хэндл сессии NULL_PTR, // Буфер с последним блоком данных &ulEncryptedDataSize); // Длина буфера if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Распечатать буфер, содержащий зашифрованные данные*/ printf("Encrypted buffer is:\n"); for (i = 0; i < ulEncryptedDataSize; i++) { printf("%02X ", pbtEncryptedData[i]); if ((i + 1) % 8 == 0) printf("\n"); } break; } |
...