...
В PKCS#11 доступны две роли: CKU_USER -- пользователь Рутокен, CKU_SO -- администратор Рутокен.
Предварительно должна быть открыта сессия.
Code Block | ||||
---|---|---|---|---|
| ||||
/* DEMO PIN-код Пользователя Рутокен */ CK_UTF8CHAR USER_PIN[] = {'1', '2', '3', '4', '5', '6', '7', '8'}; ... /* Выполнить аутентификацию Пользователя */ printf("Logging in"); rv = pFunctionList->C_Login(hSession, // Хэндл сессии CKU_USER, // Тип пользователя USER_PIN, // PIN-код пользователя sizeof(USER_PIN)); // Длина PIN-кода if (rv != CKR_OK) printf(" -> Failed\n"); else printf(" -> OK\n"); ... /*Сбросить права доступа */ printf("Logging out"); rv = pFunctionList->C_Logout(hSession); if ((rv == CKR_OK) || (rv == CKR_USER_NOT_LOGGED_IN)) printf(" -> OK\n"); else printf(" -> Failed\n"); |
...
CKM_GOSTR3410_KEY_PAIR_GEN
для генерации ключевой пары ГОСТ Р 34.10.2001,CKM_GOSTR3410_512_KEY_PAIR_GEN
для генерации ключевой пары ГОСТ Р 34.10.2012 с длиной ключа 512 бит,CKM_RSA_PKCS_KEY_PAIR_GEN
для генерации ключевой пары RSA.
...
Для генерации ключевой пары предназначена функция C_GenerateKeyPair()
, в которую передается механизм генерации и шаблоны ключевой пары.
Предварительно должна быть открыта сессия чтения/записи с авторизацией с правами пользователя Рутокен.
Code Block | ||||
---|---|---|---|---|
| ||||
/* Вычисление размера массива */ #define arraysize(a) (sizeof(a)/sizeof(a[0])) CK_MECHANISM KeyGenMech = {CKM_GOSTR3410_KEY_PAIR_GEN, NULL_PTR, 0}; // Генерация ключа ГОСТ Р 34.10-2001 CK_OBJECT_HANDLE hPublicKey = NULL_PTR; // Хэндл открытого ключа CK_OBJECT_HANDLE hPrivateKey = NULL_PTR; // Хэндл закрытого ключа ... printf("Generating key pair"); rv = pFunctionList->C_GenerateKeyPair(hSession, // Хэндл открытой сессии &KeyGenMech, // Используемый механизм генерации ключевой пары GOST34_10_2001PublicKey, // Шаблон открытого ключа arraysize(GOST34_10_2001PublicKey), // Размер шаблона открытого ключа GOST34_10_2001PrivateKey, // Шаблон закрытого ключа arraysize(GOST34_10_2001PrivateKey), // Размер шаблона закрытого ключа &hPublicKey, // Хэндл открытого ключа &hPrivateKey); // Хэндл закрытого ключа if (rv != CKR_OK) printf(" -> Failed\n"); else printf(" -> OK\n"); |
...
Для генерации секретного ключа предназначена функция C_GenerateKey()
, в которую передается механизм генерации и шаблон ключа.
Предварительно должна быть открыта сессия чтения/записи с авторизацией с правами Пользователя.
Code Block | ||||
---|---|---|---|---|
| ||||
/* Вычисление размера массива */ #define arraysize(a) (sizeof(a)/sizeof(a[0])) CK_MECHANISM KeyGenMech = {CKM_GOST28147_KEY_GEN, NULL_PTR, 0}; // Генерация ключа ГОСТ 28147-89 CK_OBJECT_HANDLE hSecKey = NULL_PTR; // Хэндл cекретного ключа ... printf("\n Generating key"); rv = pFunctionList->C_GenerateKey(hSession, // Хэндл открытой сессии &KeyGenMech, // Используемый механизм генерации ключа attrGOST28147_89SecKey, // Шаблон для создания секретного ключа arraysize(attrGOST28147_89SecKey), // Размер шаблона секретного ключа &hSecKey); // Хэндл секретного ключа if (rv != CKR_OK) printf(" -> Failed\n"); else printf(" -> OK\n"); |
...
Для хеширования данных служат функции 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 }; /* Механизм хеширования ГОСТ Р 34.11-94 */ CK_MECHANISM HashMech = {CKM_GOSTR3411, NULL_PTR, 0}; CK_BYTE_PTR pbtHash = NULL_PTR; // Указатель на буфер для хешированных данных CK_ULONG ulHashSize = 0; // Размер буфера в байтах 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, arraysize(pbtData), 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, arraysize(pbtData), pbtHash, &ulHashSize); if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); break; } |
...
Подпись на Рутокен PINPad совместным механизмом хеширования и подписи
При использовании совместного механизма хеширования и подписи в функцию C_Sign()
с совместным механизмом (например, CKM_GOSTR3410_WITH_GOSTR3411
) передается текст в специальным формате для отображения его на экране Рутокен PINPad.
При вызове функции C_Sign()
на экране Рутокен PINPad появится текст сообщения, а функция будет ожидать нажатия пользователем кнопки подтверждения или отказа от операции на экране Рутокен PINPad.
Если пользователь подтверждает выполнение операции, то сообщение сначала хешируется внутри Рутокен PINPad, а затем подписывается. Функция C_Sign()
возвращает управление и 64-байтовый блок сформированной цифровой подписи .
Если пользователь отклоняет операцию подписи, функция C_Sign()
немедленно возвращает управление и код ошибки. Никаких вычислений хеша или цифровой подписи не производится.
Подпись на Рутокен PINPad отдельными механизмами хеширования и подписи
При использовании отдельных механизмов хеширования и подписи сначала в функцию C_Digest()
с механизмом хеширования (например, CKM_GOSTR3411
) передается текст в специальном формате для отображения его на экране Рутокен PINPad.
При вызове функция C_Digest()
вычисляет хеш и возвращает управление вместе с значением хеша. Исходное сообщение и значение хеша запоминаются внутри Рутокен PINPad.
Затем вызывается функция C_Sign()
с механизмом подписи (например, CKM_GOSTR3410
) и произвольным значением хеша. Рутокен PINPad подставляет сохраненное значение хеша вместо переданного функцией C_Sign()
значения и отображает на экране текст исходного сообщения. Функция C_Sign()
ожидает нажатия пользователем кнопки подтверждения или отказа от операции на экране Рутокен PINPad.
Если пользователь подтверждает выполнение операции, то сохраненное значение хеша в Рутокен PINPad подписывается, и функция C_Sign()
возвращает управление и 64-байтовый блок сформированной цифровой подписи.
Если пользователь отклоняет операцию подписи, функция C_Sign()
немедленно возвращает управление и код ошибки. Вычисления цифровой подписи не производится.
Пример подписи данных по алгоритму ГОСТ Р 34.10-2001
...
Далее расшифрование выполняется вызовом функции C_Decrypt()
с передачей в нее зашифрованные данные. Размер расшифрованных данных можно узнать, вызвав C_Decrypt()
с пустым указателем вместо указателя на буфера для расшифрованных данных.
...
Пример расшифрования данных по алгоритму ГОСТ 28147-89
Code Block | ||||
---|---|---|---|---|
| ||||
while(TRUE) { ... /* Инициализировать операцию расшифрования */ printf("C_DecryptInit"); rv = pFunctionList->C_DecryptInit(hSession, // Хэндл сессии &EncDecStreamMech, // Механизм расшифрования hSecKey); // Хэндл секретного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Расшифровать шифротекст */ printf("Getting decrypted data size"); rv = pFunctionList->C_Decrypt(hSession, // Хэндл сессии pbtEncryptedData, // Буфер с зашифрованными данными ulEncryptedDataSize, // Размер зашифрованных данных NULL_PTR, // Буфер с расшифрованными данными &ulDecryptedDataSize); // Размер расшифрованных данных if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); pbtDecryptedData = (CK_BYTE*)malloc(ulDecryptedDataSize); memset(pbtDecryptedData, 0, (ulDecryptedDataSize * sizeof(CK_BYTE))); printf("C_Decrypt"); rv = pFunctionList->C_Decrypt(hSession, // Хэндл сессии pbtEncryptedData, // Буфер с зашифрованными данными ulEncryptedDataSize, // Размер зашифрованных данных pbtDecryptedData, // Буфер с расшифрованными данными &ulDecryptedDataSize); // Размер расшифрованных данных if (rv != CKR_OK) { printf(" -> Failed\n"); break; } printf(" -> OK\n"); /* Распечатать буфер, содержащий расшифрованный текст */ printf("Decrypted buffer is:\n"); for (i = 0; i < ulDecryptedDataSize; i++) { printf("%02X ", pbtDecryptedData[i]); if ((i + 1) % 8 == 0) printf("\n"); } break; } if (pbtEncryptedData) { free(pbtEncryptedData); pbtEncryptedData = NULL_PTR; } if (pbtDecryptedData) { free(pbtDecryptedData); pbtDecryptedData = NULL_PTR; } |