Я использую функцию CryptAcquireContext от Crypto API (https://docs.microsoft.com/en-us/windows/desktop/api/Wincrypt/nf-wincrypt-cryptacquirecontexta), чтобы получить доступ к моему хранилищу сертификатов, содержащемуся в моем USB-токене, и это работает как чудо!
Однако функция CryptAcquireContext устарела, и документация Crypto API рекомендует использовать CNG для достижения тех же результатов. Теперь вся моя проблема в том, как использовать CNG для получения контекста сертификата из моего USB-токена, и для этого я использую следующий код:
var
Provider: NCRYPT_PROV_HANDLE;
Reader: PByte;
ReaderSize: DWORD;
MemorySize: DWORD;
begin
// Get a handle to the smartcard reader specific provider
Status := NCryptOpenStorageProvider(@Provider
,'SafeSign Standard RSA and AES Cryptographic Service Provider'
,0); // returns ERROR_SUCCESS
// Convert the name of the reader to a PByte
UnicodeStringToBinary('Giesecke & Devrient GmbH StarSign CUT 0',Reader,ReaderSize);
// Inform the name of the reader to the CNG
Status := NCryptSetProperty(Provider
,NCRYPT_READER_PROPERTY
,Reader
,ReaderSize
,0); // returns ERROR_SUCCESS
MemorySize := SizeOf(HCERTSTORE);
// Try to get the size needed to a variable of type HCERTSTORE.
// This is the first step before get the certificate store
Status := NCryptGetProperty(Provider
,NCRYPT_USER_CERTSTORE_PROPERTY
,nil
,0
,@MemorySize
,0); //Returns 0x80090029 (NTE_NOT_SUPPORTED)
end;
Как видите, функция NCryptGetProperty
завершается ошибкой с кодом ошибки 0x80090029
, что означает NTE_NOT_SUPPORTED
. Что я делаю не так? Я нашел пример (C ++), выполняющий то же самое, что и я, так что, я думаю, все в порядке с моей реализацией, но ...
Моя цель - перечислить все сертификаты на моей смарт-карте (на самом деле USB-токен). Я могу сделать это с помощью Crypto API, но функция CryptAcquireContext
устарела, поэтому мне нужно использовать другую. Используя CAPI, я получаю хранилище сертификатов и могу перечислять его с помощью диалогового окна сертификатов по умолчанию, поэтому мне нужно, используя CNG, заставить хранилище сертификатов делать то же самое, но то, что я делаю сейчас, кажется неправильным.
Ну, некоторые наблюдения:
- Я не проверяю возвраты здесь (переменная состояния), чтобы упростить этот пример кода
- Функция UnicodeStringToBinary строго верна. Возвращенный буфер (PByte) имеет удвоенный размер исходной строки, и все байты равны "nn 00 nn 00 nn 00", поэтому переменная Reader содержит строку Unicode, как того требует свойство NCRYPT_READER_PROPERTY. Я могу опубликовать код по запросу.
- Моя подпись NCryptOpenStorageProvider более близка к версии Windows API, поэтому ее первый аргумент - указатель на NCRYPT_PROV_HANDLE