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

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

    In my case, the following code worked fine in localhost (both NET 3.5 and NET 4.7):

     var certificate = new X509Certificate2(certificateBytes, password);
    
     string xml = "....";
     XmlDocument xmlDocument = new XmlDocument();
     xmlDocument.PreserveWhitespace = true;
     xmlDocument.LoadXml(xml);
    
     SignedXml signedXml = new SignedXml(xmlDocument);
     signedXml.SigningKey = certificate.PrivateKey;
    
     //etc...
    

    But it failed when deployed to an Azure Web App, at certificate.PrivateKey

    It worked by changing the code as follows:

     var certificate = new X509Certificate2(certificateBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
                                                                       //^ Here
     string xml = "....";
     XmlDocument xmlDocument = new XmlDocument();
     xmlDocument.PreserveWhitespace = true;
     xmlDocument.LoadXml(xml);
    
     SignedXml signedXml = new SignedXml(xmlDocument);
     signedXml.SigningKey = certificate.GetRSAPrivateKey();
                                          // ^ Here too
    
     //etc...
    

    A whole day of work lost thanks to Microsoft Azure, once again in my life.

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

    In my case, I was trying to use a self-signed certificate with PowerShell's New-SelfSignedCertificate command. By default, it will generate a certificate using the CNG (Crypto-Next Generation) API instead of the older/classic crypto CAPI. Some older pieces of code will have trouble with this; in my case it was an older version of the IdentityServer STS provider.

    By adding this at the end of my New-SelfSignedCertificate command, I got past the issue:

    -KeySpec KeyExchange

    Reference on the switch for the powershell command:

    https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps

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

    After following the accepted answer (specifying KeySpec), the exception changed to System.Security.Cryptography.CryptographicException: Invalid provider type specified.. I resolved that exception by giving my web application access to the private key (IIS_IUSRS). I discovered that this would also fix the problem with my original certificate. So before generating and deploying new certificates, check the private key's permissions as well.

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

    Using Visual Studio 2019 and IISExpress, I was able to correct this problem by removing the following flag when loading the .pfx|.p12 file:

    X509KeyStorageFlags.MachineKeySet
    

    Before:

    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable
    

    After:

    X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable
    

    Normally, I'll load the cert this way:

    var myCert = new X509Certificate2("mykey.pfx", "mypassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
    

    This does NOT raise an Exception, instead the Exception is raised when attempting to use the certificate (or in my case, when trying to obtain the .PrivateKey). I've found this issue can be caused when the invoking user has insufficient permissions.

    Since I rely on the MachineKeySet flag for some environments, my current solution is to swallow the Exception, change the flags, try again. :/

    A more organic solution would be to test the permissions level and set this flag dynamically, however I'm not aware of a simple way to do this, hence the fallback.

    NOTE: The .pfx file I'm using was created from a website that uses a JavaScript library (digitalbazaar/forge) which does NOT use CNG (Cryptography Next Generation) Key Storage Providers. here are many common causes for this same error (the most common fixes related to CNG extensions, which have -- unfortunately even changed namespaces in .NET versions), which throw the same error. Microsoft should ultimately be more verbose when throwing these types of errors.

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

    I also had this issue and after attempting the suggestions in this post without success. I was able to resolve my issue by reloading the certificate with the Digicert certificate utility https://www.digicert.com/util/. This allows one to select the provider to load the certificate into. In my case loading the certificate into the Microsoft RSA Schannel Cryptographic Provider provider where I had expected it to be in the first place resolved the issue.

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

    I faced the same problem in our IIS app:

     System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent)
        System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent)
        System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
    

    Regenerating certs as mentioned here didnt help. I also noticed that test console app works fine under pool user.

    Problem disappeared after clearing "Enable 32-bit Applications" setting for IIS app pool.

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