2

I am having the below piece of ASP.NET code to load a pfx file from a folder

var certificatePath = $"{HttpContext.Current.Server.MapPath("~")}{certFolderName}\\{certFileName}";
return new X509Certificate2(certificatePath, certPassword, X509KeyStorageFlags.MachineKeySet);

This code works fine in local IIS. However the same code when moved to our QA servers its throws Access Denied error as below.

enter image description here

I had gone through many forums and got to know that this is mostly a permission issue in accessing the folder C:\ProgramData\Microsoft\Crypto\RSA\MachineKey. I have verified the access for this folder in our server and its all fine. The 'Everyone' user has read & write access. So ideally there shouldn't be any access denied error. I even gave explicit Full Control access to the identity of App Pool, but still doesn't work. I am trying to understand what else could cause this access denied problem.

Ashok
  • 145
  • 2
  • 19
  • You can try to assign your user as the identity of the dedicated application pool, more information you can refer to this link: [Application Pool Identities](https://learn.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities). – samwu Jan 06 '22 at 03:15

1 Answers1

1

return new X509Certificate2(certificatePath, certPassword, X509KeyStorageFlags.MachineKeySet);

the problem is with last parameter. Your application (app pool identity) doesn't have permissions to access local machine store. You should either use Current User store (for persistent key storage) or ephemeral if the key must be accessed only in runtime.

Crypt32
  • 12,850
  • 2
  • 41
  • 70
  • I had given the necessary permission to access local machine key store (C:\ProgramData\Microsoft\Crypto\RSA\MachineKey). But still it doesn't work. – Ashok Jan 04 '22 at 11:05
  • What is the point to store the key in machine store? – Crypt32 Jan 04 '22 at 11:07
  • I am trying to load certificate from a pfx file in the file system and not from from certificate store. When we load the cert from file its supposed to store its private keys temporarily in C:\ProgramData\Microsoft\Crypto\RSA\MachineKey folder. That's why access was given to this folder. – Ashok Jan 04 '22 at 11:10
  • `its supposed to store its private keys temporarily` -- this is a very false assumption. Key storage depends on how and where it is used. Acquiring a private key inside the web application's runtime often suggests that the key must not be persisted at all, therefore storage flag should be `Ephemeral` which stores the key in memory while the handle is valid. – Crypt32 Jan 04 '22 at 12:21
  • Ephemeral is not supported in .NET Framework 4.6 that we currently use. Upgrading the framework is a big effort. So I am looking for options that the current framework version supports. Also, I cannot choose Current User Store option as we have restriction in setting the LoadUserProfile setting in IIS App Pool to true – Ashok Jan 04 '22 at 16:37
  • If you are on a lower version of framework, then simply try a constructor without any storage flags. – Crypt32 Jan 04 '22 at 16:59
  • I tried that as well. If I dont't give any storage flags its defaulting to the option similar to Current User store and gives path not found error. Path not found error happens when the User Profile folder is not found. To overcome that I need to enable LoadUserProfile setting in IIS App Pool for which I have a limitation. – Ashok Jan 04 '22 at 17:25