尽管设置了私钥,但密钥集不存在

问题描述

我正在尝试使用CmsSigner并附加X509证书签名邮件

public static byte[] Sign(X509Certificate2 certificate,string keyXml)
{
    ContentInfo contentInfo = new ContentInfo(new Oid("1.2.840.113549.1.7.1"),Encoding.ASCII.GetBytes("hello"));

    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    rsa.FromXmlString(keyXml);

    using (certificate.GetRSAPrivateKey())
    {
        certificate.PrivateKey = rsa;
    }
    var signer = new CmsSigner(certificate);

    signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
    signer.SignedAttributes.Add(new Pkcs9SigningTime());

    var signedCms = new SignedCms(contentInfo,false);
    signedCms.ComputeSignature(signer);
    var encodeByteBlock = signedCms.Encode();
    return encodeByteBlock;
}

证书没有密钥(HasPrivateKeyfalse),因此我使用通过OpenSSL生成的正确密钥进行设置:

openssl req -new -sha256 -x509 -days 7300 -out ca.crt -keyout ca.key.pem -nodes

@H_502_19@我将ca.key.pem转换为XML。

但是当调用ComputeSignature时,会抛出此异常:

System.Security.Cryptography.CryptographicException:'密钥集不 存在'

堆栈跟踪:

在 System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner 签署者,布尔值无声,SafeCryptProvHandle&hProv) System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner签名者, 布尔无声) System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner 签署者,布尔值无声)位于 System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner 签名者)在ConsoleTest472.Program.Sign(X509Certificate2 证书,字符串keyXml)中 D:\ me \ Projects \ ConsoleTest472 \ ConsoleTest472 \ Program.cs:第56行位于 ConsoleTest472.Program.Main(String [] args)在 D:\ me \ Projects \ ConsoleTest472 \ ConsoleTest472 \ Program.cs:第63行

我使用的代码有什么问题?设置私钥时没有设置@H_502_19@ keyset ?

解决方法

我使用的代码有什么问题?

using (certificate.GetRSAPrivateKey())
{
    certificate.PrivateKey = rsa;
}

没有太大意义。您正在获取私钥,然后忽略它,尝试替换它,然后处置它。

一个更好的版本是

var signedCms = new SignedCms(contentInfo,false);

using (X509Certificate2 certWithKey = certificate.CopyWithPrivateKey(rsa))
{
    var signer = new CmsSigner(certWithKey);

    signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
    signer.SignedAttributes.Add(new Pkcs9SigningTime());

    signedCms.ComputeSignature(signer);
}

var encodeByteBlock = signedCms.Encode();
return encodeByteBlock;

将私钥绑定到证书副本的工作(而不是进行突变),并且进行了必要的工作(在这种情况下,最终将RSACryptoServiceProvider密钥替换为RSACng密钥,因为该平台仅支持CNG用于仅内存(临时)密钥。

,

私钥必须为:

  • 执行代码的用户的MY密钥库中
  • 在计算机的MY密钥库中,已授予用户权限
  • 与证书一起存储在PFX / PKCS#12文件中,并使用保护它的密码作为X509Certificate2加载。