Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 虽然设置了PrivateKey,但密钥集不存在_C#_Cryptography_Certificate_Rsa_X509certificate - Fatal编程技术网

C# 虽然设置了PrivateKey,但密钥集不存在

C# 虽然设置了PrivateKey,但密钥集不存在,c#,cryptography,certificate,rsa,x509certificate,C#,Cryptography,Certificate,Rsa,X509certificate,我正在尝试使用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")); RSAC

我正在尝试使用
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;
}
证书没有密钥(
HasPrivateKey
false
),因此我使用使用OpenSSL生成的正确密钥设置它:

openssl req -new -sha256 -x509 -days 7300 -out ca.crt -keyout ca.key.pem -nodes
我将ca.key.pem转换为XML

但是当调用
ComputeSignature
时,会引发此异常:

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

堆栈跟踪:

在 System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner 签名者,布尔静默,安全密码(安全句柄和hProv)位于 System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, 布尔沉默)在 系统。安全。加密。Pkcs。签名CMS。计算签名(CmsSigner 签名者,布尔沉默)在 系统。安全。加密。Pkcs。签名CMS。计算签名(CmsSigner 签名者)在控制台测试472.程序签名(X509Certificate2 证书,字符串(XML)中的 D:\me\Projects\ConsoleTest472\ConsoleTest472\Program.cs:at的第56行 控制台测试472.Program.Main(字符串[]args)位于 D:\me\Projects\ConsoleTest472\ConsoleTest472\Program.cs:第63行


我使用的代码有什么问题?设置私钥时是否设置了密钥集?

私钥必须是:

  • 在执行代码的用户的
    MY
    密钥存储中
  • 在机器的
    MY
    密钥存储中,授予用户权限
  • 与证书一起存储在PFX/PKCS#12文件中,并作为X509Certificate2加载,密码保护它
我使用的代码有什么问题

没什么意义。您正在获取私钥,然后忽略它,尝试替换它,然后处理它

更好的版本是

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;

它完成将私钥绑定到证书副本的工作(而不是进行变异),并执行任何必要的操作(在这种情况下,它将最终用RSACng密钥替换RSACNcryptoServiceProvider密钥,因为平台只支持仅用于内存(临时)密钥的CNG).

我知道我的代码没有意义,但当PrivateKey设置为
RSACryptServiceProvider
对象且HasPrivateKey为
true
时,为什么它找不到密钥集?它可能意味着“这是一个仅存储的密钥,但我需要一个命名密钥”或“此密钥只有公钥信息,但我需要私钥”,或“嗯,这个密钥本应存储在一个文件中,但该文件丢失了”。在您的情况下,我想它说“我是一个名为NULL的持久化密钥”,然后加载返回为“我找不到一个没有名称的密钥…”。您不应该使用PrivateKey setter,应该避免使用它的getter。
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;