偶尔从X509证书2获取私钥时,获取异常或指定的提供程序类型无效。密钥不存在。 [英] Getting Exception "Invalid Provider type specified" or "Key does not exist" while getting Private key from X509Certificate2 Occasionally

查看:27
本文介绍了偶尔从X509证书2获取私钥时,获取异常或指定的提供程序类型无效。密钥不存在。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试从X509证书2获取私钥时遇到以下异常之一:

System.Security.Cryptography.CryptographicException:指定的提供程序类型无效。

以下代码行中不存在

System.Security.Cryptography.CryptographicException:密钥:RSACryptoServiceProvider rsaKey=(RSACryptoServiceProvider)digiSignCert.PrivateKey;

堆栈跟踪:

System.Security.Cryptography.CryptographicException:密钥不存在。在System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType的密钥类型、Csp参数参数、布尔随机密钥容器、Int32dwKeySize、SafeProvHandle和SafeProvHandle、SafeKeyHandle和SafeKeyHandle)在System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()的System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32的密钥大小、Csp参数参数、布尔的用法默认密钥大小)在System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()的Api.cerficateUtil.GetSignedXML(字符串xml,X509证书2 PriateCert)

编码:

public static RSACryptoServiceProvider rsaKey = null;
public X509Certificate2 _PrivateCert;

public APISearch()
{
    byte[] privateCert = null;//We get the actual certificate file data here
    GetPrivateCerificate(privateCert, "abc@123");
    GetSignedXml(_PrivateCert);
}

public void GetPrivateCerificate(byte[] privateCert, string pwd)
{
    _PrivateCert = new X509Certificate2(privateCert, pwd, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
}

public void GetSignedXml(X509Certificate2 privateCert)
{
    rsaKey = (RSACryptoServiceProvider)privateCert.PrivateKey; //Occassional Exception
}
预期结果:(RSACryptoServiceProvider)privateCert.PrivateKey应始终生成私钥。

实际结果:有时会在该行抛出上述异常:

rsaKey = (RSACryptoServiceProvider)privateCert.PrivateKey;

并且有时可以成功地从证书文件中获取私钥。到目前为止,我们无法跟踪此问题的模式。

推荐答案

RSACryptoServiceProvider是一种通过Windows加密API(CAPI)库执行的类型。当.NET第一次被创建时,CAPI是新的,并且总是正确的答案(在Windows上)。从Windows Vista开始,有一个新的库:密码学:下一代(CNG)。出于兼容性考虑,CNG了解如何使用CAPI。但CAPI不能"做CAPI",不能"懂CNG"。您看到的例外情况是,当PFX指示私钥应该通过CNG存储时(或者店内证书指示其私钥通过CNG存储)。

当.NET框架添加RSACng时,确定已经有太多人编写了(RSACryptoServiceProvider)cert.PrivateKey行,因此该属性永远不能返回RSACng实例。相反,在.NET 4.6中创建了新的(扩展)方法:cert.GetRSAPublicKey()cert.GetRSAPrivateKey(),它们返回RSA而不是AsymmetricAlgorithm。在.NET 4.6中,RSA基类也得到了增强,可以将签名/验证和加密/解密操作向下移动(尽管使用了不同的签名,因为自编写CAPI以来RSA获得了新的选项)。

预期结果:(RSACryptoServiceProvider)privateCert.PrivateKey应始终生成私钥。

实际情况是cert.PrivateKey(和cert.PublicKey.Key)是被软否决的。你不应该再叫它/他们了。RSA(4.6)、ECDSA(4.6.1)和DSA(4.6.2)都有GET[算法]{Public|Private}密钥方法。

  • (RSACryptoServiceProvider)cert.PrivateKey=>cert.GetRSAPrivateKey()
  • rsaCSP.Encrypt(data, false)=>rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1)
  • rsaCSP.Encrypt(data, true)=>rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA1)
  • rsaCSP.SignData(data, "SHA256")=>rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)

DecryptSignHashVerifyDataVerifyHash相似;ECDsaDSA相似。

最后,请不要硬转换这些方法的返回值,它会随着需要而更改...在Windows上,它可以返回RSACng或RSACryptoServiceProvider;在Linux(.NET Core)上,它当前返回RSAOpenSsl;在MacOS(.NET Core)上,它返回不可转换的对象。

这篇关于偶尔从X509证书2获取私钥时,获取异常或指定的提供程序类型无效。密钥不存在。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆