如何在智能卡读卡器中检查匹配的证书?

Posted

技术标签:

【中文标题】如何在智能卡读卡器中检查匹配的证书?【英文标题】:How to check for matching Certificate in SmartCard reader? 【发布时间】:2017-10-23 21:59:04 【问题描述】:

假设我从 Windows 的密钥库中选择了一个证书,并且在签名时,我需要确定插入读卡器的 SmartCard 是否是正确的......

这里是一些示例代码:

    // finding the certificate
    X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, true);

    // by thumbprint, there is only one
    certs = certs.Find(X509FindType.FindByThumbprint, "123456BLAHBLAHAE3C", true); 
    X509Certificate2 cert = certs[0];

    RSACryptoServiceProvider key;
    if (cert.HasPrivateKey)
    
        // software cert
        key = cert.PrivateKey as RSACryptoServiceProvider;
    
    else
    
        // certificate from smartcard
        CspParameters csp = new CspParameters(1, "Microsoft Base Smart Card Crypto Provider");
        csp.Flags = CspProviderFlags.UseDefaultKeyContainer;
        key = new RSACryptoServiceProvider(csp);
    

现在,当我想对数据进行签名时,我如何知道当前插入的智能卡是否真的是我正在寻找的智能卡(与 Windows 密钥库中的智能卡匹配)?

我在问这个问题,因为现在当我签署数据时,我会收到输入智能卡 PIN 的提示,但我插入的卡甚至不是我选择的凭据......而且无论如何它只是签署了数据......

【问题讨论】:

【参考方案1】:

经过一整天的故障排除和互联网挖掘。事实证明,我根本不需要这样做。事实上,这是我自己犯的一个错误。

当您从 Store 中选择证书时,您获得的 X509Certificate 对象实际上拥有它所需的一切,例如 HasPrivateKeyPrivateKey(一个 RSACryptoServiceProvider 对象,不是实际的 PrivateKey ),并且 Windows 知道使用这些信息从哪里获取PrivateKey...包括验证阅读器中的智能卡是否具有正确的智能卡。

我的问题是,在某些时候我使用cert.GetRawCertData() 来获取原始字节来执行我自己的证书验证,最后我从原始字节中重新创建了一个X509Certificate 对象......我认为它会给我回到原来的X509Certificate 对象,但是哦,我错了HasPrivateKeyPrivateKey 都不见了。

现在,我不确定这是否是 Windows 10 中的新功能。但正如您在下面看到的,我实际上根本不需要检查读卡器中的内容......

为了解决这个问题,我在读卡器中仔细检查智能卡的初衷是确保签名操作确实是使用正确的智能卡完成的(我在 Java 中遇到了问题,您可以在其中弹出另一张卡并输入错误卡的 PIN 码,它仍然会为您签名)。但是,更好的方法实际上是使用PublicKey 并验证数据。

// so after you finished signing the data...
// make a new RSACryptoServiceProvider and verify it like this:
RSACryptoServiceProvider rsa = cert.PublicKey.Key as RSACryptoServiceProvider;
Debug.WriteLine("     Verify data >> " + (rsa.VerifyData(data, alg, signature) ? "OK" : "FAILED"));
Debug.WriteLine("Verify signature >> " + (rsa.VerifyHash(hash, alg, signature) ? "OK" : "FAILED"));

注意:不要在RSACryptoServiceProvider 上使用using 进行验证,如果这样做,您将关闭PublicKey.Key 上的静态句柄,如果您再次尝试验证(无论出于何种原因),您将得到一个Safe Handle has been closed 异常。

【讨论】:

【参考方案2】:

看看这个帖子,它或多或少是相同的问题和答案 - find certificate on smartcard currently on reader

【讨论】:

我不确定示例或帖子是否太旧,运行示例代码时,除了Access Denied,我什么也得不到。这是经过数小时尝试不同参数并浏览了多个 MSDN 文档后的结果。也许现在 Windows 10 的行为有所不同……呃。

以上是关于如何在智能卡读卡器中检查匹配的证书?的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 从 PKI 智能卡读取证书

在当前阅读器上的智能卡上查找证书

黑莓智能卡读卡器示例

如何在 C++ 中监听智能卡插入和删除事件?

NFC 读卡器和卡上匹配 (MOC) 兼容性

基于证书的登录