2

我得到以下例外之一,而試圖從X509Certificate2證書私鑰:入門異常「無效的提供程序類型指定」或「項不存在」,而從X509Certificate2獲得私鑰偶爾

System.Security.Cryptography.CryptographicException:指定了無效的提供程序類型。

OR

System.Security.Cryptography.CryptographicException:鍵不會在下面的代碼行存在:的RSACryptoServiceProvider rsaKey =(的RSACryptoServiceProvider)digiSignCert.PrivateKey;

堆棧跟蹤:

System.Security.Cryptography.CryptographicException:鍵不存在。在System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType關鍵字類型,CspParameters參數,布爾randomKeyContainer,的Int32 dwKeySize,SafeProvHandle & safeProvHandle,SafeKeyHandle & safeKeyHandle)在System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()在System.Security.Cryptography。 RSACryptoServiceProvider..ctor(的Int32 dwKeySize,CspParameters參數,布爾useDefaultKeySize)在System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()在Api.CertificateUtil.GetSignedXml(字符串XML,X509Certificate2 privateCert)

代碼:

public static RSACryptoServiceProvider rsaKey = null; 
public X509Certificate2 _PrivateCert; 

public APISearch() 
{ 
    byte[] privateCert = null;//We get the actual certificate file data here 
    GetPrivateCerificate(privateCert, "[email protected]"); 
    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;

,有時私鑰被成功從證書文件中取得。截至目前,我們一直無法跟蹤這個問題的模式。

回答

5

RSACryptoServiceProvider是一種通過Window Cryptographic API(CAPI)庫執行RSA的類型。當.NET第一次創建時,CAPI是新的,並且始終是正確的答案(在Windows上)。從Windows Vista開始,有一個新庫:加密:下一代(CNG)。爲了兼容性,CNG瞭解如何與CAPI合作。但CAPI不能「做CAPI」和「瞭解CNG」。您看到的例外情況是,PFX表示應通過CNG存儲私鑰(或者店內證書表明其私鑰通過CNG存儲)。

當.NET Framework添加RSACng時,已經決定有太多人已經寫了(RSACryptoServiceProvider)cert.PrivateKey這一行,這樣屬性就永遠無法返回RSACng實例。相反,在.NET 4.6中創建了新的(擴展)方法:cert.GetRSAPublicKey()cert.GetRSAPrivateKey(),它們返回RSA而不是AsymmetricAlgorithm。同樣在.NET 4.6中,RSA基類已得到增強,使Sign/Verify和Encrypt/Decrypt操作向下移動(儘管簽名不同,因爲自從CAPI寫入以來RSA已獲得新選項)。

預期結果:(RSACryptoServiceProvider)privateCert.PrivateKey應始終生成一個私鑰。

實際的真相是cert.PrivateKey(和cert.PublicKey.Key)被軟棄用。你不應該再打電話給他/他們了。 RSA(4.6),ECDSA(4.6.1)和DSA(4.6.2)都有Get [Algorithm] {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)上返回一個不可播放的對象。

相關問題