首页 > 解决方案 > 无法使用智能卡上的私钥创建 CmsSigner

问题描述

当我尝试创建 CmsSigner 来签署我的消息时遇到了错误。

基本上,我的个人证书存储中有多个证书具有相同的电子邮件地址(主题),当我使用 ApplicationPkcs7Mime.Sign() 方法时,它使用了错误的证书来签署我的消息。

因此,为了找到正确的证书,我基本上实现了搜索并初始化正确的 CmsSigner 以用于签名。但是,我遇到了一个错误,我怀疑这是因为相应证书的私钥在我的智能卡内是不可导出的。这是我编写的代码和我得到的错误。

   X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, userEmail, true);
        MimeKit.Cryptography.CmsSigner signer = null;

        foreach (X509Certificate2 cert in collection)
        {             
            if (cert.Issuer.Contains("My_Trusted_CA") && cert.HasPrivateKey)
            {

                foreach (X509Extension ext in cert.Extensions)
                {
                    if (ext.Oid.FriendlyName == "Key Usage")
                    {

                        X509KeyUsageExtension keyUsage = (X509KeyUsageExtension)ext;
                        System.Security.Cryptography.X509Certificates.X509KeyUsageFlags keyUsageFlags = keyUsage.KeyUsages;
                        if (keyUsageFlags.HasFlag(System.Security.Cryptography.X509Certificates.X509KeyUsageFlags.DigitalSignature))
                        {
                            Log("Certificate Found: " + cert.SerialNumber);
                            try
                            {
                                signer = new MimeKit.Cryptography.CmsSigner(cert);
                            } catch (Exception ex)
                            {
                                ThrowErrorMessage("Error creating CMS Signer: " + ex.Message + "\n" + ex.StackTrace);
                            }
                            break;
                        }
                    }
                }
            }
        }

这是抛出的异常:

Error creating CMS Signer: Invalid type specified.
   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.Utils._ExportKey(SafeKeyHandle hKey, Int32 blobType, Object cspObject)
   at System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters)
   at MimeKit.Cryptography.AsymmetricAlgorithmExtensions.GetAsymmetricKeyParameters(RSACryptoServiceProvider rsa, Boolean publicOnly, AsymmetricKeyParameter& pub, AsymmetricKeyParameter& key)
   at MimeKit.Cryptography.AsymmetricAlgorithmExtensions.GetAsymmetricKeyParameter(RSACryptoServiceProvider rsa)
   at MimeKit.Cryptography.CmsSigner..ctor(X509Certificate2 certificate)

谢谢。

标签: mimekit

解决方案


您使用的是哪个版本的 .NET?

检查MimeKit.Cryptography.WIndowsSecureMimeContext您是否可以使用(只要您net45在 packages.config 中引用 MimeKit 的目标,它就应该适用于 >= .NET v4.5)。

假设您可以使用,我建议继承WindowsSecureMimeContext并覆盖GetCmsSigner方法。

一旦你这样做了,你将能够或多或少地复制和粘贴你当前的逻辑,以便将正确的 CmsSigner 放入其中,结果如下:

protected override System.Security.Cryptography.Pkcs.CmsSigner GetCmsSigner (MailboxAddress mailbox, DigestAlgorithm digestAlgo)
{
    var store = new X509Store (StoreName.My, StoreLocation.CurrentUser);
    store.Open (OpenFlags.ReadOnly);

    var collection = store.Certificates.Find (X509FindType.FindBySubjectName, userEmail, true);
    System.Security.Cryptography.Pkcs.CmsSigner signer = null;

    foreach (X509Certificate2 cert in collection)
    {             
        if (cert.Issuer.Contains("My_Trusted_CA") && cert.HasPrivateKey)
        {
            foreach (X509Extension ext in cert.Extensions)
            {
                if (ext.Oid.FriendlyName == "Key Usage")
                {
                    var keyUsage = (X509KeyUsageExtension)ext;
                    var keyUsageFlags = keyUsage.KeyUsages;

                    if (keyUsageFlags.HasFlag (System.Security.Cryptography.X509Certificates.X509KeyUsageFlags.DigitalSignature))
                    {
                        Log("Certificate Found: " + cert.SerialNumber);
                        try
                        {
                            signer = new System.Security.Cryptography.Pkcs.CmsSigner(cert);
                        } catch (Exception ex)
                        {
                            ThrowErrorMessage("Error creating CMS Signer: " + ex.Message + "\n" + ex.StackTrace);
                        }
                        break;
                    }
                }
            }
        }
    }
}

推荐阅读