title: "Invalid provider type specified" CryptographicException when trying to load private key of certificate
body: <p>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 to them over the wire. I'm doing so programmatically in C#, but I think this is a permissions or misconfiguration issue, so I'll focus on the facts which seem to be most relevant:</p>
  
  <ul>
  <li>I don't think this issue is code-related; my code works on other computers, and the issue affects sample code from Microsoft.</li>
  <li>The certificate was provided as a PFX file and is just for test purposes, so it also includes a dummy certification authority.</li>
  <li>Using MMC.exe, I can import the certificate into the personal store for the local machine, before granting permissions on the private key to all relevant accounts, and dragging and dropping the certification authority into the Trusted Root Certification Authorities.</li>
  <li>Using C#, I can load the certificate (identified by its thumbprint) and verify that it has a private key using <code>X509Certificate2.HasPrivateKey</code>. However, trying to read the key causes an error. In .NET a <code>CryptographicException</code> is thrown with the message "Invalid provider type specified" upon trying to access the property <code>X509Certificate2.PrivateKey</code>. In Win32, calling the method <code>CryptAcquireCertificatePrivateKey</code> returns the equivalent HRESULT, <code>NTE_BAD_PROV_TYPE</code>.</li>
  <li>This is the same exception which also occurs when using two of Microsoft's own code samples to read the private key of the certificate.</li>
  <li>Installing the same certificate in the equivalent store for the current user, instead of the local machine, allows the private key to be successfully loaded.</li>
  <li>I'm on Windows 8.1 with local administrator rights, and I've tried running my code in both normal and elevated modes. Colleagues on Windows 7 and Windows 8 have been able to load the key from the local machine store for the same certificate.</li>
  <li>I can successfully read the private key of the self-signed IIS test certificate, which is in the same store location.</li>
  <li>I am already targeting .NET 4.5 (this error has been reported with some older versions of the framework).</li>
  <li>I don't think this is a problem with certificate templates, because I would expect that to affect both the local machine and current-user stores equally?</li>
  </ul>
  
  <p>Unlike my colleagues, I have made multiple previous attempts to uninstall and re-install the certificate in various ways, including via IIS Manager and also including an older certificate from the same issuer. I can't see any traces of old or duplicate certificates in MMC. However, I do have many private key files of identical size which, based on the last-write time, must have been left behind after my various installation attempts. These are found at the following locations, for the local machine and current user stores respectively:</p>
  
  <p>c:\ProgramData\Microsoft\Crypto\RSA\MachineKeys</p>
  
  <p>c:\Users\\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-[rest of user ID]</p>
  
  <p>So, can anyone please advise whether:</p>
  
  <ul>
  <li>It's a good idea to uninstall the certificate using MMC, delete all those files which look like orphaned private keys, and then re-install the certificate and try again?</li>
  <li>There any other files which I should try to manually delete?</li>
  <li>There's anything else I should try?</li>
  </ul>
  
  <p>UPDATE - Added a code sample showing an attempt to read a private key:</p>
  
  <pre><code>static void Main()
  {
      // Exception occurs when trying to read the private key after loading certificate from here:
      X509Store store = new X509Store("MY", StoreLocation.LocalMachine);
      // Exception does not occur if certificate was installed to, and loaded from, here:
      //X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
  
      store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
  
      X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
      X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
      X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.MultiSelection);
      Console.WriteLine("Number of certificates: {0}{1}", scollection.Count, Environment.NewLine);
  
      foreach (X509Certificate2 x509 in scollection)
      {
          try
          {
              Console.WriteLine("Private Key: {0}", x509.HasPrivateKey ? x509.PrivateKey.ToXmlString(false) : "[N/A]");
              x509.Reset();
          }
          catch (CryptographicException ex)
          {
              Console.WriteLine(ex.Message);
          }
      }
      store.Close();
  
      Console.ReadLine();
  }
  </code></pre>