Как получить хранилище сертификатов со смарт-карты (USB Token) с помощью CNG?
Я использую функцию CryptAcquireContext API Crypto ( 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
1 ответ
Я не работаю с delphi ... но имя читателя должно оканчиваться нулем.
Я получил это, работая в .NET с
Microsoft Smart Card Key Storage Provider
и звонок:
NCrypt.NCryptSetProperty(
provider,
NCrypt.KeyStoragePropertyIdentifiers.NCRYPT_READER_PROPERTY,
Encoding.Unicode.GetBytes(smartCardReader + '\0')
);