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

标签 c# digital-signature x509certificate smartcard-reader

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

下面是一些示例代码:

    // 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 keystore 中的智能卡相匹配)?

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

最佳答案

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

当您从商店选择证书时,X509Certificate你得到的对象实际上拥有它需要的一切,比如 HasPrivateKeyPrivateKey (一个 RSACryptoServiceProvider 对象,不是实际的私钥),Windows 知道从哪里获得 PrivateKey使用这些信息...包括验证读卡器中的智能卡是否有正确的智能卡。

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

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

enter image description here

为了解决这个问题,我仔细检查读卡器中的智能卡的初衷是确保签名操作确实是使用正确的智能卡完成的(我在 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"));

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

关于c# - 如何检查智能卡读卡器中的匹配证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46899187/

相关文章:

ios - 使用命令行(openssl)验证iTunes iOS应用内收据(购买信息和签名)

ssl - 将主题名称转换为 x509_name 格式

c# - MongoDB 连接导致 System.Net.Sockets.SocketException

c# - 保存 OpenXML 文档时操作共享字符串表

c# - Newtonsoft.JSON 序列化产生一个具有对象类型的唯一字符串

node.js 加密签名和 openssl 签名不匹配

java - 从 .wsdl for java 生成 Web 服务客户端安全策略

c# - 如何将ConfigureServices(IServiceCollection 服务)从.Net 5 迁移到.Net 6?

c# - X509 找不到请求的对象

java - 将 X509 证书转换为 PEM 或 ASN.1/DER