06.03.2007 9:41:16Public key Ответов: 11
Андрей Горячев
Доброго времени суток,
Возникла следующая проблема.

Импортирую открытый ключ в BYTE* (в C++ используя CryptoAPI), получаю последовательность байтов размером 100. Далее мне нужно сравнить этот открытый ключ с открытым ключом сертификата, при этом для сравнения я вытаскиваю открытый ключ из сертификата уже в программе на C# .NET, используя X509Certificate2 класс. ТАк вот, при получении открытого ключа сертификата в .NET я получаю последовательность байтов размером 65-66 байт (у каждого сертификата по разному почему то). И так получается что эти 65-66 байтов совпадают с последними 66-65ю байтами ранее импортированного открытогоключа (размером 100 байт) начиная со второго байта.
В чём подвох? Как сравнить открытые ключи полученные из .NET и из CryptoAPI (C++)?
 
Ответы:
06.03.2007 10:05:48Kirill Sobolev
66 байт - это закодированный ОК, который лежит в CERT_INFO::SubjectPublicKeyInfo.PublicKey.pbData, его и надо сравнивать. Еще, конечно, помимо значения надо сравнивать алгоритм.
06.03.2007 10:47:33Андрей Горячев
Дело в том, что у меня есть только импортированный открытый ключ в файле. А почему он туда размером 100 байт записался тогда?
06.03.2007 10:55:37Kirill Sobolev
Туда еще попадает инфа об алгоритме и параметрах.
struct CRYPT_PUBLICKEYBLOB {
CRYPT_PUBKEY_INFO_HEADER tPublicKeyParam;
BYTE bASN1GostR3410_94_PublicKeyParameters [1];
BYTE bPublicKey [1];
};
Вам нужен собственно только bPublicKey.
06.03.2007 11:18:44Андрей Горячев
Ясно.
А вот у меня в результате имеется 100 байт с открытым ключём и некой информацией. Теперь мне отсюда нужно вытащить именно сам открытый ключ (нет сертификата в наличии, открытый ключ передаётся для проверки ЭЦП). Это возможно?
06.03.2007 11:56:27Kirill Sobolev
Конечно.
Собственно обратная процедура -
CryptImportKey, получается хендл ОК.
Затем CryptExportPublicKeyInfoEx в структуру CERT_PUBLIC_KEY_INFO, там уже отдельно лежат сам ОК и его алгоритм/параметры.
06.03.2007 12:59:42Андрей Горячев
CryptExportPublicKeyInfo - тут вот вторым параметром идёт keySpec, а у меня его нет. Его можно как то получить из провайдера? Если до этого провайдер был проинициализирован так: CryptAcquireContext(&hProv, NULL, NULL, 75, CRYPT_VERIFYCONTEXT)
06.03.2007 15:15:54Kirill Sobolev
Я ошибся, CryptExportPublicKeyInfo вообще похоже без секретного ключа не работает :(
06.03.2007 15:27:30Андрей Горячев
То есть без секретного ключа получается что я не могу из 100 байтов в результате получить открытый ключик?
06.03.2007 17:40:15Василий
Если есть блоб ОК ГОСТа 2001-го года (100 байт) и он не зашифрован, то значение ОК имеется в нём в открытом виде (последние 64 байта). Если делаем CryptImportKey - получаем хендл ОК, который можно использовать для операций, не требующих закрытого ключа, например, при проверке подписи.
06.03.2007 17:43:16Андрей Горячев
А оставшиеся 2 байта (до 66), которые я получаю когда импортирую открытый ключ из X509Certificate2 (.NET) в byte[], это что?
Всмысле мне сранивать последние 64 байта из 100 и последние 64 из 66?
06.03.2007 18:20:36Василий
2 байта перед ключом (ГОСТ.. 2001) - заголовок ASN.1, означающий - тип содержимого (OCTET STRING) и длину содержимого (64 байта).