Page tree

Versions Compared

Key

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

...

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;
	}
	/* Определить класс токена */
	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
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 };

 
 
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
languagecpp
titleПодпись данных по алгоритму ГОСТ Р 34.10-2001
/* Механизм подписи/проверки подписи по алгоритму ГОСТ Р 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");
}

...