Статус: Участник
Группы: Участники
Зарегистрирован: 25.10.2013(UTC) Сообщений: 12 Сказал(а) «Спасибо»: 4 раз
|
Задача: сформировать (временный) ключ подписи и экспортировать его (в зашифрованном виде). На принимающей стороне расшифровать. Две стороны: "генератор ключей" (Generator), "приёмник ключей" (Recipient) На стороне "генератора ключей": Код:
// Создание временного контейнера с экспортируемым ключом
CryptAcquireContext(&hGenProv, "\\\.\\REGISTRY\\TEMPKEY"..);
CryptGenKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hGenKey ) ;
CryptExportKey(hGenKey, ... PUBLICKEYBLOB, pbGenKeyPUB... );
// Создание эфемерного ключа для ключевого обмена
CryptGenKey(hGenProv, CALG_DH_GR3410_12_256_EPHEM, CRYPT_PREGEN|CRYPT_EXPORTABLE, &hEphem);
CryptSetKeyParam(hEphem, KP_X, NULL, 0);
CryptExportKey(hEphem, ... PUBLICKEYBLOB, pbEphemPub... );
CryptSetKeyParam(hKEK, KP_ALGID, CALG_PRO12_EXPORT)
// Импорт публичного ключа приёмника и вывод ключа обмена KEK
CryptImportKey(hGenProv, pbRecipientPublicKeyBlob, hEphemKey, &hKEK);
// На ключе обмена KEK зашифровать ключ из временного контейнера
CryptExportKey(hGenKey, hKEK, PRIVATEKEYBLOB, pbEncryptedBlob, ..);
На стороне приёмника: Код:
// Открытие личного ключа приёмника для расшифровки ключей
CryptAcquireContext(&hRecipientProv, "mykey",...);
CryptGetUserKey(hRecipientProv, AT_KEYEXCHANGE, &hRecipientKey);
// Импорт публичной части эфемерного ключа от генератора
CryptImportKey(hRecipientProv, pbEphemPub, hRecipientKey, &hKEK);
CryptSetKeyParam(hKEK, KP_ALGID, CALG_PRO12_EXPORT);
// CryptImportKey( hRecipientProv, pbEncryptedBlob, hKEK, &hGenKey);
// этот путь работает в том смысле что на стороне приёмника
// Задача - расшифровать pbEncryptedBlob
Из pbEncryptedBlob достал ASN.1 структуру Код:
Offset| Len |LenByte|
======+======+=======+======================================================================
0| 99| 1| SEQUENCE :
2| 91| 1| SEQUENCE :
4| 8| 1| OCTET STRING :
| | | 4BB2D25DB1B86406 // UKM
14| 40| 1| SEQUENCE :
16| 32| 1| OCTET STRING :
| | | A942F8052AA3A528DBE631B80A3FEA4034EFE92EEDA92088044DA6B9F6E2C160 // зашифрованное значение ключа
50| 4| 1| OCTET STRING : '7D54464E' // контрольная сумма ключа
56| 37| 1| CONTEXT SPECIFIC (0) :
58| 2| 1| BIT STRING UnusedBits:7 :
| | | 80
62| 31| 1| CONTEXT SPECIFIC (0) :
64| 8| 1| OBJECT IDENTIFIER : [1.2.643.7.1.1.1.1]
74| 19| 1| SEQUENCE :
76| 7| 1| OBJECT IDENTIFIER : GostR3410_2001_CryptoPro_A_ParamSet [1.2.643.2.2.35.1]
85| 8| 1| OBJECT IDENTIFIER : [1.2.643.7.1.1.2.2]
95| 4| 1| OCTET STRING : '58DCE44C'
Пробовал как-то так Код:
CryptSetKeyParam(hKEK, KP_ALGID, CALG_G28147);
// Сформировать CRYPT_DIVERSBLOB (https://cpdn.cryptopro.ru/content/csp39/html/group___pro_c_s_p_key_1g22d0afd866885ab6779eabc9dab4a6b8.html)
...
divblob.DiversBlobHeader.aiDiversAlgId = CryptoAPI.CALG_PRO12_DIVERS;
divblob.DiversBlobHeader.cbDiversData = 8;
memcpy(divblob.pbData, EncryptedBlob->UKM;
// Вывести ключ импорта
CryptImportKey(... &divblob, hKEK, &hDivKEK);
CryptSetKeyParam(hDivKEK, KP_MODE, CRYPT_MODE_ECB)
CryptDecrypt(hDivKEK, NULL, FALSE, EncryptedBlob->EncryptedKey+ 0, &enclen);
CryptDecrypt(hDivKEK, NULL, FALSE, EncryptedBlob->EncryptedKey+ 8, &enclen);
CryptDecrypt(hDivKEK, NULL, FALSE, EncryptedBlob->EncryptedKey+16, &enclen);
CryptDecrypt(hDivKEK, NULL, FALSE, EncryptedBlob->EncryptedKey+24, &enclen);
В результате расшифровывается мусор, контрольная сумма под ключом не сходится, публичный ключ к расшифрованному значению не подходит. Я правильно понимаю, что CALG_PRO_DIVERS соответствует "rfc4357, CryptoPro KEK Diversification Algorithm" ? CALG_PRO12_DIVERS - аналогично для ключей 34.10-2012 ? Если нет, то можно ли диверсифицировать ключ алгоритмом CryptoPro KEK Diversification Algorithm из rfc4357 средствами CryptoAPI ?
|