Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Подпись на Рутокен 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_Encrypt(), или по частям, вызывая  C_EncryptUpdate() для каждого непоследнего блока и  C_EncryptFinal() для завершающего блока. Если в C_EncryptFinal() передать пустой блок данных, то функция вернет суммарный размер всех блоков зашифрованных данных.

Пример шифрования данных по алгоритму ГОСТ 28147-89 

Code Block
languagecpp
titleШифрование данных по алгоритму ГОСТ 28147-89 в режиме простой замены
/* Данные для шифрования */
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 };
 
/* Механизм шифрования/расшифрования по алгоритму ГОСТ 28147-89 в режиме простой замены */
CK_MECHANISM	EncDecMech    		= {CKM_GOST28147_ECB, NULL_PTR, 0};

 
CK_BYTE_PTR 	pbtEncryptedData 	= NULL_PTR;              // Указатель на буфер, содержащий зашифрованные данные
CK_ULONG 		ulEncryptedDataSize = 0;                     // Размер буфера с зашифрованными данными, в байтах 
 
while(TRUE)
{
	...
	/* Инициализировать операцию шифрования */
	printf("C_EncryptInit");
	rv = pFunctionList->C_EncryptInit(hSession,		// Хэндл сессии
			                          &EncDecMech,	// Механизм шифрования
			                          hSecKey);		// Хэндл секретного ключа
	if (rv != CKR_OK)
	{
		printf(" -> Failed\n");
		break;
	}
	printf(" -> OK\n");

	/* Получить размер зашифрованного текста */
	printf("Getting encrypted data size");
	rv = pFunctionList->C_Encrypt(hSession,					// Хэндл сессии 
			                      pbtData,					// Буфер с открытыми данными для шифрования
			                      arraysize(pbtData),		// Длина буфера с открытыми данными, в байтах
			                      NULL,						// Буфер с зашифрованными данными
			                      &ulEncryptedDataSize);	// Длина буфера с зашифрованными данными
	if (rv != CKR_OK)
	{
		printf(" -> Failed\n");
		break;
	}
	printf(" -> OK\n");

	pbtEncryptedData = (CK_BYTE*)malloc(ulEncryptedDataSize);
	memset(pbtEncryptedData,
		   0,
		   (ulEncryptedDataSize * sizeof(CK_BYTE)));
	
	/* Зашифровать открытый текст */
	printf("C_Encrypt");
	rv = pFunctionList->C_Encrypt(hSession,					// Хэндл сессии 
			                      pbtData,					// Буфер с открытыми данными для шифрования
			                      arraysize(pbtData),		// Длина буфера с открытыми данными, в байтах
			                      pbtEncryptedData,			// Буфер с зашифрованными данными
			                      &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;
}
 

...

Далее расшифрование выполняется вызовом функции C_Decrypt() с передачей в нее зашифрованные данные. Размер расшифрованных данных можно узнать, вызвав C_Decrypt()  с пустым указателем вместо указателя на буфера для расшифрованных данных.

Примеры расшифрования данных по алгоритму ГОСТ 28147-89 

Code Block
languagecpp
titleРасшифрование данных по алгоритму ГОСТ 28147-89
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;
}