无法从.net x509certificate2对象中获取私钥以用于bouncycastle AsymmetricCipherKeyPair

3

我正在尝试从这段代码中获取X509Certificate2对象的pkcs-7签名密钥对。

RSACryptoServiceProvider key = (RSACryptoServiceProvider)Cert.PrivateKey;
RSAParameters rsaparam = key.ExportParameters(true);
AsymmetricCipherKeyPair keypair = DotNetUtilities.GetRsaKeyPair(rsaparam);

如果使用.pfx文件创建X509Certificate2对象,则这将正常工作。

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格式

2个回答

2
这是因为BouncyCastle试图从.NET对象中获取原始密钥材料(即导出),而实际密钥未标记为可导出。在Windows系统中,密钥存储在加密服务提供程序中,控制所有密钥操作。当您需要执行特定的加密操作时,您会请求CSP执行任务,并且它会在不必暴露密钥材料给您的情况下执行。如果密钥被导入/生成为可导出,则可以请求CSP导出密钥材料。如果未设置此标志,则CSP将不会向您提供密钥。
我不知道BouncyCastle如何工作,但如果它期望原始密钥材料,则需要在证书中具有可导出的私钥。

谢谢,有没有什么解决方法可以实现这个?我必须使用 Windows 密钥库和 CSP 硬件中的证书签署 SHA256 哈希。 - Prashanth
你需要调用Windows代码(.NET对象中的方法)来对数据进行签名。例如,可以使用RSA.SignData方法中的任何适当重载。RSA是一个基类,RSACryptoServiceProvider从中派生。例如:https://msdn.microsoft.com/en-us/library/mt132675.aspx - Crypt32
RSA会创建分离的PKCS7签名吗? - Prashanth
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey;使用SHA256Managed进行哈希计算:using (SHA256Managed sHA256 = new SHA256Managed()) { byte[] hash = sHA256.ComputeHash(data); return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256")); }但是,我尝试了这个方法,得到的签名不是PKCS#7格式 - Prashanth
要创建PKCS#7消息,您需要使用“SignedCms”类,该类可以从您的数据构造PKCS#7消息,并使用签名证书计算签名。 - Crypt32
但是 System.Security.Cryptography.Pkcs.CmsSigner 不支持使用 sha256 哈希值进行签名。 - Prashanth

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" 是 OID 语言中 SHA-2-256 的代号。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接