如何使用CNG从智能卡(USB令牌)获取证书存储?

时间:2018-06-27 22:21:10

标签: delphi certificate cng

我正在使用Crypto API的CryptAcquireContext函数(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的指针

0 个答案:

没有答案