无法从 .net x509certificate2 对象获取私钥到 bouncycastle AsymmetricCipherKeyPair
Unable to fetch private key from .net x509certificate2 object to bouncycastle AsymmetricCipherKeyPair
我试图从这段代码中获取 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 格式
这是因为 BouncyCastle 尝试从 .NET 对象获取原始密钥 material(字面意思是导出),而实际密钥未标记为可导出。在 Windows 系统中,密钥存储在控制所有密钥操作的加密服务提供商中。当您需要执行特定的加密操作时,您是在要求 CSP 完成一项工作,而无需向您公开密钥 material。如果密钥在 CSP 中是 imported/generated 作为可导出的,您可以要求 CSP 导出密钥 material。如果没有设置这个标志,CSP 不会给你密钥。
我不知道 BouncyCastle 是如何工作的,但如果它需要原始密钥 material,那么您的证书中需要可导出的私钥。
要回答基本问题,"How do I make a PKCS#7 SignedData message signed with RSA+SHA-2-256?"
https://github.com/Microsoft/dotnet/blob/master/releases/net471/dotnet471-changes.md#bcl 表示 SHA-2-256 不仅适用于 4.7.1,而且现在是默认值:
Updated SignedXML and SignedCMS to use SHA256 as a default over SHA1. SHA1 may still be used by selected as a default by enabling a context switch. [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。
我试图从这段代码中获取 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 格式
这是因为 BouncyCastle 尝试从 .NET 对象获取原始密钥 material(字面意思是导出),而实际密钥未标记为可导出。在 Windows 系统中,密钥存储在控制所有密钥操作的加密服务提供商中。当您需要执行特定的加密操作时,您是在要求 CSP 完成一项工作,而无需向您公开密钥 material。如果密钥在 CSP 中是 imported/generated 作为可导出的,您可以要求 CSP 导出密钥 material。如果没有设置这个标志,CSP 不会给你密钥。
我不知道 BouncyCastle 是如何工作的,但如果它需要原始密钥 material,那么您的证书中需要可导出的私钥。
要回答基本问题,"How do I make a PKCS#7 SignedData message signed with RSA+SHA-2-256?"
https://github.com/Microsoft/dotnet/blob/master/releases/net471/dotnet471-changes.md#bcl 表示 SHA-2-256 不仅适用于 4.7.1,而且现在是默认值:
Updated SignedXML and SignedCMS to use SHA256 as a default over SHA1. SHA1 may still be used by selected as a default by enabling a context switch. [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。