问题描述
我正在尝试使用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
@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加载。