Как получить хранилище сертификатов со смарт-карты (USB Token) с помощью CNG? - PullRequest
0 голосов
/ 28 июня 2018

Я использую функцию 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, заставить хранилище сертификатов делать то же самое, но то, что я делаю сейчас, кажется неправильным.

Ну, некоторые наблюдения:

  1. Я не проверяю возвраты здесь (переменная состояния), чтобы упростить этот пример кода
  2. Функция UnicodeStringToBinary строго верна. Возвращенный буфер (PByte) имеет удвоенный размер исходной строки, и все байты равны "nn 00 nn 00 nn 00", поэтому переменная Reader содержит строку Unicode, как того требует свойство NCRYPT_READER_PROPERTY. Я могу опубликовать код по запросу.
  3. Моя подпись NCryptOpenStorageProvider более близка к версии Windows API, поэтому ее первый аргумент - указатель на NCRYPT_PROV_HANDLE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...