Page tree

Versions Compared

Key

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

...

Code Block
languagecpp
titleПолучение списка токенов
CK_SLOT_ID_PTR aSlots = NULL_PTR;           // Указатель на массив идентификаторов слотов
CK_ULONG ulSlotCount = 0;                   // Количество идентификаторов слотов в массиве
 
while(TRUE)
{
...
	/* Получить количество слотов c подключенными токенами */
	printf(" Getting number of connected slots");
	rv = pFunctionList->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
	if (rv != CKR_OK)
	{
		printf(" -> Failed\n");
		break;
	}
	printf(" -> OK\n");
 
	aSlots = (CK_SLOT_ID*)malloc(ulSlotCount * sizeof(CK_SLOT_ID));
	if (aSlots == NULL)
	{
		printf("Memory allocation for aSlots failed! \n");
		break;
	}
	memset(aSlots, 0, (ulSlotCount * sizeof(CK_SLOT_ID)));


	/* Получить список слотов c подключенными токенами */
	printf(" Getting list of connected slots");
	rv = pFunctionList->C_GetSlotList(CK_TRUE,	aSlots, &ulSlotCount);
	if (rv != CKR_OK)
	{
		printf(" -> Failed %X\n", (int)rv);
		break;
	}
	printf(" -> OK\n");

	printf(" Slots available: 0x%8.8X\n", (int)ulSlotCount);
	...
	break;
}
 
if (aSlots)
{
	free(aSlots);
	aSlots = NULL_PTR;
}

...

Code Block
languagecpp
titleОпределение класса токена
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;
	}
	/* Определить класс токена */
	ifswitch (tokenInfoEx.ulTokenClass == TOKEN_CLASS_S)
	{
		bIsRutokenPINPad = FALSE;
case TOKEN_CLASS_S: 
			printf(": Rutoken / Rutoken S\n");
	}
	else if (tokenInfoEx.ulTokenClass == case TOKEN_CLASS_ECP):
	{
		bIsRutokenPINPad = FALSE;
		printf(": Rutoken ECP\n");
	}
	else if (tokenInfoEx.ulTokenClass == case TOKEN_CLASS_LITE):
	{
		bIsRutokenPINPad = FALSE;
		printf(": Rutoken Lite\n");
	}
	else if (tokenInfoEx.ulTokenClass ==case  TOKEN_CLASS_WEB):
	{
		bIsRutokenPINPad = FALSE;
		printf(": printf(": Rutoken WEB\n");
	}
	else if (tokenInfoEx.ulTokenClass == case TOKEN_TYPE_RUTOKEN_PINPAD_FAMILY):
	{
		bIsRutokenPINPad = TRUE;
			printf(": Rutoken PINPad\n");
	}
	else
	{
		bIsRutokenPINPad = FALSE;
	default:
			printf(": undefined\n");
	}

	break;
}

...

Code Block
languagecpp
titleХеширование данных по алгоритму ГОСТ Р 34.11-94
/* Данные для хеширования в виде двоичной строки */
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);
	if (pbtHash == NULL)
	{
		printf("Memory allocation for pbtHash failed! \n");
		break;
	}
	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-байтовый блок сформированной цифровой подписи размером 64 байта для механизмов CKM_GOSTR3410_WITH_GOSTR3411  и CKM_GOSTR3410_WITH_GOSTR3411_12_256 и 128 байтдля механизма CKM_GOSTR3410_WITH_GOSTR3411_12_512

Если пользователь отклоняет операцию подписи, функция C_Sign() немедленно возвращает управление и код ошибки. Никаких вычислений хеша или цифровой подписи не производится.

Подпись на Рутокен PINPad отдельными механизмами хеширования и подписи

При использовании отдельных механизмов хеширования и подписи сначала в функцию C_Digest() с механизмом хеширования (например, CKM_GOSTR3411) передается текст в специальном формате для отображения его на экране Рутокен PINPad.

При вызове функция C_Digest() вычисляет хеш и возвращает управление вместе с значением хеша. Исходное сообщение и значение хеша запоминаются внутри Рутокен PINPad.

Затем вызывается функция C_Sign() с механизмом подписи (например, CKM_GOSTR3410) и произвольным значением хеша. Рутокен PINPad подставляет (question) сохраненное значение хеша вместо переданного  Рутокен PINPad сверяет сохраненное значение хеша с переданным функцией C_Sign() значения и в случае совпадения отображает на экране текст исходного сообщения. Функция C_Sign() ожидает нажатия пользователем кнопки подтверждения или отказа от операции на экране Рутокен PINPad.  Если значения не совпадают, функция C_Sign() возвращает ошибку без вывода на экране текста сообщения.

Если пользователь подтверждает выполнение операции, то сохраненное значение хеша в Рутокен PINPad подписывается, и функция C_Sign() возвращает управление и 64-байтовый блок сформированной цифровой подписи размером 64 байта для механизма CKM_GOSTR3410 и 128 байт для механизма CKM_GOSTR3410_512

Если пользователь отклоняет операцию подписи, функция C_Sign() немедленно возвращает управление и код ошибки. Вычисления цифровой подписи не производится.

Пример подписи данных по алгоритму ГОСТ Р 34.10-2001

Code Block
languagecpp
titleПодпись данных по алгоритму ГОСТ Р 34.10-2001
/* Механизм подписи/проверки подписи по алгоритму ГОСТ Р 34.10-2001 */
CK_MECHANISM    SigVerMech = {CKM_GOSTR3410, NULL_PTR, 0};
 
/* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-1994 */
CK_BYTE     GOST3411params[]  = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01 };
 
/*  Механизм подписи/проверки подписи по алгоритму ГОСТ Р 34.10-2001 с хешированием по алгоритму ГОСТ Р 34.11-94*/
CK_MECHANISM    HashSigVerMech = {CKM_GOSTR3410_WITH_GOSTR3411, GOST3411params, sizeof(GOST3411params)};

CK_BYTE_PTR pbtSignature = NULL_PTR;                 // Указатель на буфер, содержащий подпись для исходных данных
CK_ULONG ulSignatureSize = 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,			// Хэндл сессии
								pbtHash,			// Буфер с данными для подписи
								ulHashSize,			// Длина подписываемых данных
								pbtSignature,		// Буфер с подписью
								&ulSignatureSize);	// Длина подписи
	if (rv != CKR_OK)
	{
		printf(" -> Failed\n");
		break;
	}
	printf(" -> OK\n");

	pbtSignature = (CK_BYTE*)malloc(ulSignatureSize);\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_Sign step 2");
	rv = pFunctionList->C_Sign( hSession,			// Хэндл сессии
								pbHash,				// Буфер с данными для подписи
								ulHashSize,			// Длина подписываемых данных
								pbtSignature,		// Буфер с подписью
								&ulSignatureSize);	// Длина подписи
	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");
	}
	
	break;
}

...

Code Block
languagecpp
titleПодпись запроса на сертификат в формате PKCS#10
/* Сформированный запрос на сертификат в виде двоичной строки */
CK_BYTE pbtReqCert[] = {0x30, 0x82, 0x02, 0x69, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x83, 0x31, 0x0b, 0x30, 0x09, 0x06,
						0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x52, 0x55, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04,
						0x08, 0x13, 0x06, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
						0x04, 0x07, 0x13, 0x03, 0x6d, 0x73, 0x6b, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x09,
						0x13, 0x06, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04,
						0x0a, 0x13, 0x05, 0x41, 0x6b, 0x74, 0x69, 0x76, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
						0x0b, 0x13, 0x02, 0x49, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x10, 0x13, 0x0e,
						0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x31, 0x1b,
						0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x0c, 0x1e, 0x12, 0x04, 0x34, 0x04, 0x3e, 0x04, 0x3b, 0x04,
						0x36, 0x04, 0x3d, 0x04, 0x3e, 0x04, 0x41, 0x04, 0x42, 0x04, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06,
						0x08, 0x2a, 0x85, 0x03, 0x03, 0x81, 0x03, 0x01, 0x01, 0x12, 0x0b, 0x31, 0x32, 0x33, 0x34, 0x35,
						0x36, 0x37, 0x38, 0x39, 0x38, 0x37, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x2a, 0x85, 0x03, 0x64,
						0x03, 0x12, 0x0b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x38, 0x37, 0x31, 0x16,
						0x30, 0x14, 0x06, 0x05, 0x2a, 0x85, 0x03, 0x64, 0x01, 0x12, 0x0b, 0x31, 0x32, 0x33, 0x34, 0x35,
						0x36, 0x37, 0x38, 0x39, 0x38, 0x37, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x2a, 0x85, 0x03, 0x64,
						0x05, 0x12, 0x0b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x38, 0x37, 0x31, 0x2f,
						0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x26, 0x04, 0x24, 0x04, 0x30, 0x04, 0x3c, 0x04,
						0x38, 0x04, 0x3b, 0x04, 0x38, 0x04, 0x4f, 0x00, 0x20, 0x04, 0x18, 0x04, 0x3c, 0x04, 0x4f, 0x00,
						0x20, 0x04, 0x1e, 0x04, 0x47, 0x04, 0x35, 0x04, 0x41, 0x04, 0x42, 0x04, 0x32, 0x04, 0x3e, 0x31,
						0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x41, 0x13, 0x09, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f,
						0x6e, 0x79, 0x6d, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x04, 0x13, 0x07, 0x73, 0x75,
						0x72, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x2a, 0x13, 0x0a,
						0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x6e, 0x61,	0x6d, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09,
						0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,	0x01, 0x16, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70,
						0x6c, 0x65, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70,	0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x63,
						0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02,	0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
						0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a,	0x85, 0x03, 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43,
						0x00, 0x04, 0x40, 0x26, 0x68, 0x22, 0x87, 0x6b,	0x3e, 0x60, 0xde, 0x6e, 0xcf, 0x7d, 0x9b, 0xc5,
						0x99, 0x49, 0x88, 0xe3, 0xce, 0x8d, 0x05, 0xb2,	0x0a, 0x3c, 0x3d, 0x2c, 0xb3, 0x7c, 0xc6, 0x9e,
						0x7e, 0x5a, 0xc6, 0x95, 0xde, 0x97, 0x86, 0x9a,	0x56, 0xe3, 0xc5, 0xf5, 0xc5, 0xca, 0x9a, 0x4a,
						0xd9, 0x11, 0xa0, 0x40, 0x08, 0xca, 0x70, 0x29,	0x13, 0x64, 0x7f, 0xa1, 0x6c, 0x5b, 0x5b, 0x25,
						0xc9, 0xa6, 0x0c, 0xa0, 0x78, 0x30, 0x76, 0x06,	0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
						0x09, 0x0e, 0x31, 0x69, 0x30, 0x67, 0x30, 0x0b,	0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
						0x02, 0x06, 0xc0, 0x30, 0x16, 0x06, 0x03, 0x55,	0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, 0x30,
						0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,	0x07, 0x03, 0x04, 0x30, 0x13, 0x06, 0x03, 0x55,
						0x1d, 0x20, 0x04, 0x0c, 0x30, 0x0a, 0x30, 0x08,	0x06, 0x06, 0x2a, 0x85, 0x03, 0x64, 0x71, 0x01,
						0x30, 0x2b, 0x06, 0x05, 0x2a, 0x85, 0x03, 0x64,	0x6f, 0x04, 0x22, 0x0c, 0x20, 0xd0, 0xa1, 0xd0,
						0x9a, 0xd0, 0x97, 0xd0, 0x98, 0x20, 0x22, 0xd0,	0xa0, 0xd0, 0xa3, 0xd0, 0xa2, 0xd0, 0x9e, 0xd0,
						0x9a, 0xd0, 0x95, 0xd0, 0x9d, 0x20, 0xd0, 0xad, 0xd0, 0xa6, 0xd0, 0x9f, 0x22
};
 
/*  Механизм хеширования ГОСТ Р 34.11-94 */
CK_MECHANISM 	HashMech 	= {CKM_GOSTR3411, NULL_PTR, 0}; 

/* Механизм подписи/проверки подписи по алгоритму ГОСТ Р 34.10-2001 */
CK_MECHANISM    SigVerMech 	= {CKM_GOSTR3410, NULL_PTR, 0};
 
CK_BYTE_PTR 	pbtHash 		= NULL_PTR;    // Указатель на буфер для значения хеша данных
CK_ULONG 		ulHashSize 		= 0;           // Размер буфера в байтах
CK_BYTE_PTR 	pbtSignature 	= NULL_PTR;    // Указатель на буфер, содержащий подпись для исходных данных
CK_ULONG 		ulSignatureSize = 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,					// Хэндл сессии
								  pbtReqCert,				// Буфер с запросом на сертификат
								  arraysize(pbtReqCert),	// Размер буфера с запросом на сертификат
								  pbtHash,					// Буфер для значения хеша
								  &ulHashSize);				// Размер значения хеша
	if (rv != CKR_OK)
	{
		printf(" -> Failed\n");
		break;
	}
	printf(" -> OK\n");

	pbtHash = (CK_BYTE*)malloc(ulHashSize);
	if (pbtHash == NULL)
	{
		printf("Memory allocation for pbtHash failed! \n");
		break;
	}
	memset(pbtHash,
		   0,
		   (ulHashSize * sizeof(CK_BYTE)));

	/* Сформировать хеш от исходных данных */
	printf("C_Digest step 2");
	rv = pFunctionList->C_Digest(hSession,					// Хэндл сессии
								 pbtReqCert,				// Буфер с запросом на сертификат
								 arraysize(pbtReqCert),		// Размер буфера с запросом на сертификат
								 pbtHash,					// Буфер для значения хеша
								 &ulHashSize);				// Размер значения хеша
	if (rv != CKR_OK)
	{
		printf(" -> Failed\n");
		break;
	}
	printf(" -> OK\n");
 
	/* Инициализировать операцию подписи данных */
	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,			// Хэндл сессии
								pbtHash,			// Буфер с данными для подписи
								ulHashSize,			// Длина подписываемых данных
								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_Sign step 2");
	rv = pFunctionList->C_Sign( hSession,			// Хэндл сессии
								pbHash,				// Буфер с данными для подписи
								ulHashSize,			// Длина подписываемых данных
								pbtSignature,		// Буфер с подписью
								&ulSignatureSize);	// Длина подписи
	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");
	}
	
	break;
}
 

...

  • CKM_GOST28147_ECB для шифрования алгоритмом ГОСТ 28147-89 в режиме простой замены,
  • CKM_GOST28147 для шифрования алгоритмом ГОСТ 28147-89 в режиме гаммирования с обратной связью,
  • CKM_RSA_PKCS для шифрования алгоритмом RSAдля шифрования алгоритмом RSA.
Warning
titleВнимание!

Так как в режиме простой замены (механизм CKM_GOST28147_ECB) шифрование каждого блока данных осуществляется одним и тем же ключом, этот механизм должен применяться только для данных небольшого размера (например, ключей). В противном случае стойкость алгоритма.снижается.

Шифрование данных

Для шифрования данных одним блоком служат функции C_EncryptInit() и C_Encrypt(), для поточного – С_EncryptInit(), C_EncryptUpdate() и C_EncryptFinal(). 

...

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);
	if (pbtEncryptedData == NULL)
	{
		printf("Memory allocation for pbtEncryptedData failed! \n");
		break;
	}
	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;
}
 
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 };
 
CK_BYTE	 	IV[]  	 	= {1, 2, 3, 4, 5, 6, 7, 8};		// Значение вектора инициализации
CK_ULONG 	ulIVLen 	= 8;                           	// Длина вектора инициализации


/* Механизм шифрования/расшифрования по алгоритму ГОСТ 28147-89 в режиме гаммирования с обратной связью */
CK_MECHANISM	EncDecStreamMech   	= {CKM_GOST28147, IV, ulIVLen};

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;
}

...

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);
	if (pbtDecryptedData == NULL)
	{
		printf("Memory allocation for pbtDecryptedData failed! \n");
		break;
	}
	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;
}

...