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

前端 未结 18 2739
盖世英雄少女心
盖世英雄少女心 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:54

    I tried everything in this post, but for me the solution was:

    1. Import the original .p12 file into my local machine
    2. Export it as a .pfx file checking the "Export all extended properties" and "Include all the certificates in the certification path if its possible" options
    3. Read the new certificate using this flag options from this post solution:

      var certificate = new X509Certificate2(certKeyFilePath, passCode,
      X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet |       
      X509KeyStorageFlags.PersistKeySet );
      
    0 讨论(0)
  • 2020-11-29 22:54

    It seems on Windows 10, if I run my program without administrative privileges (whether I use the PrivateKey property or the GetRSAPrivateKey() extension method), I will see this exception (see the title of this discussion thread for the exception). If I run my program with administrative privileges and use the PrivateKey property, I will also see this exception. Only if I run my program with administrative privileges and use the GetRSAPrivateKey() extension method, I will not see this exception.

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

    The link to Alejandro's blog is key.

    I believe this is because the certificate is stored on your machine with the CNG ("Crypto Next-Generation") API. The old .NET API is not compatible with it, so it doesn't work.

    You can use the Security.Cryptography wrapper for this API (available on Codeplex). This adds extension methods to X509Certificate/X509Certificate2, so your code will look something like:

    using Security.Cryptography.X509Certificates; // Get extension methods
    
    X509Certificate cert; // Populate from somewhere else...
    if (cert.HasCngKey())
    {
        var privateKey = cert.GetCngPrivateKey();
    }
    else
    {
        var privateKey = cert.PrivateKey;
    }
    

    Unfortunately the object model for CNG private keys is quite a bit different. I'm not sure if you can export them to XML like in your original code sample...in my case I just needed to sign some data with the private key.

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

    Powershell version of the answer from @berend-engelbrecht, assuming openssl installed via chocolatey

    function Fix-Certificates($certPasswordPlain)
    {
        $certs = Get-ChildItem -path "*.pfx" -Exclude "*.converted.pfx"
        $certs | ForEach-Object{
            $certFile = $_
    
            $shortName = [io.path]::GetFileNameWithoutExtension($certFile.Name)
            Write-Host "Importing $shortName"
            $finalPfx = "$shortName.converted.pfx"
    
    
            Set-Alias openssl "C:\Program Files\OpenSSL\bin\openssl.exe"
    
            # Extract public key
            OpenSSL pkcs12 -in $certFile.Fullname -nokeys -out "$shortName.cer" -passin "pass:$certPasswordPlain"
    
            # Extract private key
            OpenSSL pkcs12 -in $certFile.Fullname -nocerts -out "$shortName.pem" -passin "pass:$certPasswordPlain" -passout "pass:$certPasswordPlain"
    
            # Convert private key to RSA format
            OpenSSL rsa -inform PEM -in "$shortName.pem" -out "$shortName.rsa" -passin "pass:$certPasswordPlain" -passout "pass:$certPasswordPlain" 2>$null
    
            # Merge public keys with RSA private key to new PFX
            OpenSSL pkcs12 -export -in "$shortName.cer" -inkey "$shortName.rsa" -out $finalPfx -passin "pass:$certPasswordPlain" -passout "pass:$certPasswordPlain"
    
            # Clean up
            Remove-Item "$shortName.pem"
            Remove-Item "$shortName.cer"
            Remove-Item "$shortName.rsa"
    
            Write-Host "$finalPfx created"
        }
    }
    
    # Execute in cert folder
    Fix-Certificates password
    
    0 讨论(0)
  • 2020-11-29 22:57

    For a .net 4.8 WCF service I was getting this error because i hadn't (also) set the httpRuntime version.

    Without the httpRuntime set i was getting the error whenever a secured .net tcp binding was present.

    <system.web>
        <compilation targetFramework="4.8" />
        <httpRuntime targetFramework="4.8" />
        <!--<customErrors mode="Off" />-->
    </system.web>
    

    I had already setup the required permissions in mmc.exe -> add snap-in -> certificates -> personal -> all tasks -> manage private keys -> add [computer name]\IIS_IUSRS (all my application pools are ApplicationPoolIdentity [default] - which is covered by IIS_IUSRS)

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

    the PrivateKey and PublicKey properties are outdated beginning with NET 4.6. Please use:

    • cert.GetRSAPrivateKey() or GetECDsaPrivateKey()
    • cert.GetRSAPublicKey() or GetECDsaPublicKey()

    Regards

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