“Invalid provider type specified” CryptographicException when trying to load private key of certificate

前端 未结 18 2738
盖世英雄少女心
盖世英雄少女心 2020-11-29 22:04

I\'m trying to read the private key of a certificate which has been shared with me by a third-party service provider, so I can use it to encrypt some XML before sending it t

相关标签:
18条回答
  • 2020-11-29 22:45

    This error went away after i removed the certificate from the store and imported it again from the .pfx file, using the Certificate Import Wizard (double-click the .pfx file) and an extra import option.

    After checking the import option (same step where password is entered):

    "Mark this key as exportable. This will allow you to back up or transport your keys at a later time."

    The privatekey could now be accessed from code without any errors.

    I also explicitly select the "Personal" store on the 2nd to last step, but I don't think this matters.

    0 讨论(0)
  • 2020-11-29 22:46

    As many other answers have pointed out, this issue arises when the private key is a Windows Cryptography: Next Generation (CNG) key instead of a "classic" Windows Cryptographic API (CAPI) key.

    Beginning with .NET Framework 4.6 the private key (assuming it's an RSA key) can be accessed via an extension method on X509Certificate2: cert.GetRSAPrivateKey().

    When the private key is held by CNG the GetRSAPrivateKey extension method will return an RSACng object (new to the framework in 4.6). Because CNG has a pass-through to read older CAPI software keys, GetRSAPrivateKey will usually return an RSACng even for a CAPI key; but if CNG can't load it (e.g. it's an HSM key with no CNG driver) then GetRSAPrivateKey will return an RSACryptoServiceProvider.

    Note that the return type for GetRSAPrivateKey is RSA. Beginning with .NET Framework v4.6 you shouldn't need to cast beyond RSA for standard operations; the only reason to use RSACng or RSACryptoServiceProvider is when you need to interop with programs or libraries that use the NCRYPT_KEY_HANDLE or the key identifier (or opening a persisted key by name). (.NET Framework v4.6 had a lot of places that still cast the input object to RSACryptoServiceProvider, but those were all eliminated by 4.6.2 (of course, that's more than 2 years ago at this point)).

    ECDSA certificate support was added in 4.6.1 via a GetECDsaPrivateKey extension method, and DSA was upgraded in 4.6.2 via GetDSAPrivateKey.

    On .NET Core the return value from Get[Algorithm]PrivateKey changes depending on the OS. For RSA it's RSACng/RSACryptoServiceProvider on Windows, RSAOpenSsl on Linux (or any UNIX-like OS except macOS), and a non-public type on macOS (meaning you can't cast it beyond RSA).

    0 讨论(0)
  • 2020-11-29 22:48

    Here is another reason that this can happen, this was a weird issue and after struggling for a day I solved the issue. As an experiment I changed permission for "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" folder which holds private key data for certificates using Machine key store. When you change permission for this folder all privatekeys shows up as "Microsoft Software KSP provider" which is not the provider (in my case they are supposed to be " Microsoft RSA Schannel Cryptographic Provider").

    Solution: Reset permissions to Machinekeys folder

    Original permission for this folder can be found in here. In my case I have changed permission for "Everyone", gave read permissions where it removed "Special permissions" tick. So I checked with one of my team member (Right click folder> Properties > Security > Advanced > select "Everyone" > Edit > Click "Advanced settings" in permission check box list

    Hope this will save someone's day!

    Here is where I found the answer source, credit goes to him for documenting this.

    0 讨论(0)
  • 2020-11-29 22:49

    The problem is your code is not able to read the PFX file. convert the pfx file to RSA format by doing the below steps.

    Get the certificate and extract the pfx file from the certificate.

    use the password 123456 below to have a quick solution.

    rename your pfx to 'my.pfx' file to make it simple and put it in "C:\Certi" make sure you have open SSL installed already in the system. open cmd in windows system and type --> OpenSSL Stay cool and just run these ones by one --> copy paste. *Note

    -passin is your Pfx file password -passout is the new password for converted pfx.

    1. pkcs12 -in "C:\Certi\my.pfx" -nokeys -out "C:\Certi\MYCERT.cer" -passin "pass:123456"
    
    2. pkcs12 -in "C:\Certi\my.pfx" -nocerts –out “C:\Certi\MYCERT.pem" -passin "pass:123456" -passout "pass:123456"
    
    3. rsa -inform PEM -in "C:\Certi\MYCERT.pem" -out "C:\Certi\MYCERT.rsa" -passin "pass:123456" -passout "pass:123456"
    

    if you face issue in the 3rd command go here https://decoder.link/converter
    Click PKC#12 To PEM upload your pfx file and get it converted online. download the zip file. it contains 3 files. just copy ".key" file and rename it as my.key and put in "C:\Certi"

    4. rsa -in C:\Certi\my.key -out C:\Certi\domain-rsa.key
    
    5. pkcs12 -export -in "C:\Certi\MYCERT.cer" -inkey "C:\Certi\domain-rsa.key" -out "C:\Certi\CONVERTED.pfx" -passin "pass:123456" -passout "pass:123456"
    
    
    **Also, you can try below things if the issue still persists**
    
    • Given access to app pool or IIS user to folder "mandatory to do"

    Path --- > C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

    • Delete the old keys (clear up the mess)
      Path --- > C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
    0 讨论(0)
  • 2020-11-29 22:53

    I had the same problem on Windows 8 and Server 2012/2012 R2 with two new certificates I recently received. On Windows 10, the problem no longer occurs (but that does not help me, as the code manipulating the certificate is used on a server). While the solution of Joe Strommen in principle works, the different private key model would require massive change to the code using the certificates. I find that a better solution is to convert the private key from CNG to RSA, as explained by Remy Blok here.

    Remy uses OpenSSL and two older tools to accomplish the private key conversion, we wanted to automate it and developed an OpenSSL-only solution. Given MYCERT.pfx with private key password MYPWD in CNG format, these are the steps to get a new CONVERTED.pfx with private key in RSA format and same password:

    1. Extract public keys, full certificate chain:

    OpenSSL pkcs12 -in "MYCERT.pfx" -nokeys -out "MYCERT.cer" -passin "pass:MYPWD"

    1. Extract private key:

    OpenSSL pkcs12 -in "MYCERT.pfx" -nocerts –out “MYCERT.pem" -passin "pass:MYPWD" -passout "pass:MYPWD"

    1. Convert private key to RSA format:

    OpenSSL rsa -inform PEM -in "MYCERT.pem" -out "MYCERT.rsa" -passin "pass:MYPWD" -passout "pass:MYPWD"

    1. Merge public keys with RSA private key to new PFX:

    OpenSSL pkcs12 -export -in "MYCERT.cer" -inkey "MYCERT.rsa" -out "CONVERTED.pfx" -passin "pass:MYPWD" -passout "pass:MYPWD"

    If you load the converted pfx or import it in the Windows certificate store instead of the CNG format pfx, the problem goes away and the C# code does not need to change.

    One additional gotcha that I encountered when automating this: we use long generated passwords for the private key and the password may contain ". For the OpenSSL command line, " characters inside the password must be escaped as "".

    0 讨论(0)
  • 2020-11-29 22:54

    What worked for me: IIS / Application pool / Load User Profile = true

    0 讨论(0)
提交回复
热议问题