title: X509Certificate2 on Azure App Services (Azure Websites) since mid-2017?
body: <p>I have a .NET Framework 4.7 application that allows users to upload X.509 certificates in PFX or PKCS#12 format (think: "SSL certificates" with the private key included), it then loads the certificate into a <code>System.Security.Cryptography.X509Certificates.X509Certificate2</code> instance. As my application code also needs to re-export the certificate I specify the <code>X509KeyStorageFlags.Exportable</code> option.</p>
  
  <p>When running under IIS on my production web-server, the Windows user-profile for the identity that <code>w3wp.exe</code> runs under is not loaded, so I do not specify the <code>UserKeySet</code> flag.</p>
  
  <pre><code>String filePassword = ...
  Byte[] userProvidedCertificateFile = ...
  
  using( X509Certificate2 cert = new X509Certificate2( rawData: userProvidedCertificateFile, password: filePassword, keyStorageFlags: X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet )
  {
      ...
  }
  </code></pre>
  
  <p>In early 2017 I deployed this code to an Azure App Service (aka Azure Website) instance and it worked okay - after initially failing because I did have the <code>UserKeySet</code> flag set (as Azure App Services do not load a user-profile certificate store.</p>
  
  <p>However, since mid-2017 (possibly around May or June) my application has stopped working - I assume the Azure App Service was moved to an updated system (though Kudu reports my application is running on Windows Server 2012 (<code>NT 6.2.9200.0</code>).</p>
  
  <p>It currently fails with two error messages that varied depending on input:</p>
  
  <ul>
  <li><code>CryptographicException</code> "The system cannot find the file specified."</li>
  <li><code>CryptographicException</code> "Access denied."</li>
  </ul>
  
  <p>I wrote an extensive test-case that tries different combinations of <code>X509Certificate2</code> constructor arguments, as well as with and without the <code>WEBSITE_LOAD_CERTIFICATES</code> Azure application setting.</p>
  
  <p>Here are my findings when working with an uploaded PFX/PKCS#12 certificate file that contains a private key and does not have password-protection:</p>
  
  <ul>
  <li>Running under IIS Express on my development box:
  
  <ul>
  <li>Loading the certificate file always succeeds, regardless of <code>X509KeyStorageFlags</code> value.</li>
  <li>Exporting the certificate file requires at least <code>X509KeyStorageFlags.Exportable</code>.</li>
  </ul></li>
  <li>Running under IIS on a production server (not an Azure App Service) where the <code>w3wp.exe</code> user-profile is not loaded:
  
  <ul>
  <li>Loading the certificate file requires that <code>X509KeyStorageFlags.UserKeySet</code> is <strong>not</strong> set, but otherwise always succeeds.</li>
  <li>Exporting the certificate file requires at least <code>X509KeyStorageFlags.Exportable</code>, but otherwise always succeeds, otherwise it fails with "Key not valid for use in specified state."</li>
  </ul></li>
  <li>Running under Azure App Service, without <code>WEBSITE_LOAD_CERTIFICATES</code> defined:
  
  <ul>
  <li>Loading the certificate with <code>MachineKeySet</code> set and <code>UserKeySet</code> is <strong>not</strong> set fails with a <code>CryptographicException</code>: "Access denied."</li>
  <li>Loading the certificate with any other <code>keyStorageFlags</code> value, including values like <code>UserKeySet | MachineKeySet | Exportable</code> or just <code>DefaultKeySet</code> fails with a <code>CryptographicException</code>: "The system cannot find the file specified."</li>
  <li>As I was not able to load the certificate at all I could not test exporting certificates.</li>
  </ul></li>
  <li>Running under Azure App Service, with <code>WEBSITE_LOAD_CERTIFICATES</code> defined as the thumbprint of the certificate that was uploaded:
  
  <ul>
  <li>Loading the certificate with <code>MachineKeySet</code> <strong>and</strong> <code>UserKeySet</code> is <strong>not</strong> set, fails with <code>CryptographicException</code>: "Access denied." .
  
  <ul>
  <li>So values like <code>UserKeySet</code> and <code>UserKeySet | MachineKeySet</code> and <code>Exportable</code> will work.</li>
  </ul></li>
  <li>Exporting certificates requires <code>X509KeyStorageFlags.Exportable</code> - same as all other environments.</li>
  </ul></li>
  </ul>
  
  <p>So it seems that <code>WEBSITE_LOAD_CERTIFICATES</code> seems to work - but only if the certificate being loaded into an <code>X509Certificate2</code> instance has the same thumbprint as specified in <code>WEBSITE_LOAD_CERTIFICATES</code>.</p>
  
  <p>Is there any way around this?</p>