我试图从此代码获取 pkcs-7签名 X509Certificate2 对象的密钥对。
RSACryptoServiceProvider key = (RSACryptoServiceProvider)Cert.PrivateKey;
RSAParameters rsaparam = key.ExportParameters(true);
AsymmetricCipherKeyPair keypair = DotNetUtilities.GetRsaKeyPair(rsaparam);
如果 X509Certificate2对象是使用.pfx 这样的文件创建的,那么这很好用
X509Certificate2 cert = new X509Certificate2(".pfx file path", "password");
它工作正常。 但是当证书从证书商店列出时,就像这样
X509Certificate2 cert;
X509Store UserCertificateStore = new X509Store("My");
UserCertificateStore.Open(OpenFlags.ReadOnly);
var certificates = UserCertificateStore.Certificates;
foreach (var certificate in certificates)
{
if (certificate.Thumbprint==thumbprint)
{
cert=certificate;
break;
}
}
它会在邮件中引发异常 - 密钥无法在指定状态下使用。
在@ Crypt32回答尝试使用RSA方法签名哈希
之后RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey;
using (SHA256Managed sHA256 = new SHA256Managed())
{
byte[] hash = sHA256.ComputeHash(data);
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
}
但签名不是PKCS#7格式
答案 0 :(得分:0)
这是因为BouncyCastle尝试从.NET对象获取原始密钥材料(字面意思是导出),而实际密钥未标记为可导出。在Windows系统中,密钥存储在加密服务提供程序中,用于控制所有密钥操作。当您需要执行特定的加密操作时,您要求CSP完成一项工作,而无需向您公开密钥材料。如果密钥是在CSP中导出/生成为可导出的,则可以要求CSP导出密钥材料。如果未设置此标志,CSP将不会为您提供密钥。
我不知道BouncyCastle是如何工作的,但如果它需要原始密钥材料,那么您的证书中需要可导出的私钥。
答案 1 :(得分:0)
要回答基本问题,“如何使用RSA + SHA-2-256签署PKCS#7 SignedData消息?”
https://github.com/Microsoft/dotnet/blob/master/releases/net471/dotnet471-changes.md#bcl说SHA-2-256不仅适用于4.7.1,而且现在是默认值:
更新了SignedXML和SignedCMS,将SHA256用作SHA1的默认值。通过启用上下文切换,SHA1仍可被选中作为默认值使用。 [397307,System.Security.dll,Bug]
在较旧的框架上,可以通过:
ContentInfo content = new ContentInfo(data);
SignedCms cms = new SignedCms(content);
CmsSigner signer = new CmsSigner(cert);
signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
cms.ComputeSignature(signer);
return cms.Encode();
其中“2.16.840.1.101.3.4.2.1”是SHA-2-256的OID-ese。