【问题标题】:Update x509Certificate2 with correct Cryptographic Service Provider in Bouncy Castle在 Bouncy Castle 中使用正确的加密服务提供程序更新 x509Certificate2
【发布时间】:2017-12-18 11:10:34
【问题描述】:

我正在使用 Wiktor Zychla (http://www.wiktorzychla.com/2012/12/how-to-create-x509certificate2.html) 的这篇博文中的 CertificateGenerator.GenerateCertificate 创建 x509Certificate2

Bouncy Castle crypto library 用于生成证书文件。我需要使用更强的签名算法,所以我使用的是SHA256withRSA,而不是SHA1withRSA(示例中的一个)。

生成证书并成功导出到.pfx文件。稍后使用证书时出现错误Invalid algorithm specified。

运行 certutil -dump mycert.pfx 时,我看到设置了错误的加密服务提供程序 (CSP):Microsoft Base Cryptographic Provider v1.0

...

---------------- 结束嵌套级别 1 ----------------

Provider = Microsoft Base Cryptographic Provider v1.0

...

我如何告诉 Bouncy Castle API 使用不同的 CSP?Microsoft Enhanced RSA 和 AES Cryptographic Provider,实际上可以处理 SHA256withRSA。

Bouncy Castle 和C# 上的资源非常少,因此非常感谢任何指向一些文档或相关示例的链接。

CryptoAPI CSP 和算法列表,它们支持:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb931357(v=vs.85).aspx

【问题讨论】:

    标签: c# cryptography x509certificate bouncycastle x509certificate2


    【解决方案1】:

    最简单的方法是在导入生成的 pfx 时指定 CSP。你可以使用这个命令

    certutil -importPFX -csp "Microsoft Enhanced RSA and AES Cryptographic Provider" -v c:\yourpfx.pfx AT_KEYEXCHANGE,NoExport,NoProtect
    

    这会

    • 导入到 LocalMachine\My
    • 将 CSP 设置为 Microsoft 增强 RSA 和 AES 加密提供程序
    • 将私钥使用设置为 Exchange
    • 将私钥设置为不可导出
    • 设置没有额外(密码)保护的私钥

    CSP 是 PKCS#12 (PFX) 中的 windows 特定字段,除了 windows 没有人设置它。如果您使用文件 new X509Certificate2(filename) 中的 PFX,则必须更改私钥。将PrivateKey 属性转换为RSACryptoServiceProvider 并修改CspParameters(我现在没有sn-p)。然后将修改后的RSACryptoServiceProvider设置回PrivateKey属性。

    ------- 编辑

    这是从文件读取的 PFX 上更改 CSP 的示例代码

    // need to set exportable flag to be able to ... export private key
    X509Certificate2 cert = new X509Certificate2(@"d:\test.pfx", "a", X509KeyStorageFlags.Exportable);
    var privKey = cert.PrivateKey as RSACryptoServiceProvider;
    
    // will be needed later
    var exported = privKey.ToXmlString(true);
    
    // change CSP
    var cspParams = new CspParameters()
    {
        ProviderType = 24,
        ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider"
    };
    
    // create new PrivateKey from CspParameters and exported privkey
    var newPrivKey = new RSACryptoServiceProvider(cspParams);
    newPrivKey.FromXmlString(exported);
    
    // Assign edited private key back
    cert.PrivateKey = newPrivKey;
    
    // export as PKCS#12/PFX
    var bytes = cert.Export(X509ContentType.Pfx, "a");
    

    【讨论】:

    • 感谢您的回答。我在数据库中存储了“错误”的证书。不要对 LocalMachine 进行导入(这就是我们的应用程序使用证书的方式)。需要最好在 c# 中重新生成那些“错误”的证书并将它们存储回 DB,而不会破坏现有的集成。这甚至可以在 C# 中实现吗? :-)
    • 转换后的私钥var rsa = (RSACryptoServiceProvider) x509cert.PrivateKey。还有rsa.CspKeyContainerInfo,其中包含ProviderType和ProviderName。这些是只读属性,不能更改,这对私钥有意义:-) 你提到的那些CspParameters 吗?以及如何更新它们(如果可能)。
    • @mimo 我添加了应该更改 CSP 的示例代码。
    • 感谢代码。我在最后一行收到异常CryptographicExceptio: Keyset does not exist:cert.Export(X509ContentType.Pfx, "a")。我的 cert.pfx 位于c:\code\temp。已授予对 AppPool 的完全访问权限,在该 AppPool 下运行我的代码到 temp 以及 cert.pfx,但仍然获得 Keyset does not exist。
    • @mimo 这很奇怪。我没有尝试从 Web 应用程序运行代码。每次我看到这个异常时,它都与私钥的权限有关。您可以尝试在X509Certificate2 构造函数中使用X509KeyStorageFlags。也许会有所帮助。晚上我会试着调查一下。
    猜你喜欢
    • 2013-04-02
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2011-01-26
    • 2015-06-13
    • 2013-02-20
    • 1970-01-01
    • 2011-06-27
    相关资源
    最近更新 更多