We have two servers running the same ASP.NET MVC application under IIS. Server A is running IIS 7.5 on Windows Server 2008 R2 Standard v 6.1 build 7601 SP1. Server B is running IIS 8.5 on Windows Server 2012 R2 v 6.3 build 9600.
The app pools run under the same windows user.
The webapp uses ProtectedData.Protect and Unprotect with DataProtectionScope CurrentUser, and stores the encrypted values to separate databases (there is no interaction at all between the two servers)
Server A has been running for over a year and on two or three occasions has been unable to decrypt (with the error Failed to decrypt: Key not valid for use in specified state). We didn't understand the reason for this, and simply re-encrypted the values via the application. Since it was a rare occurrence, we decided we could live with it.
Server B has been running for about 3 weeks and in that time the same issue has occurred five times. We cannot live with this, hence me asking this question.
The Load User Profile settings in IIS advanced settings are true on both servers and have been throughout.
Our initial thought was that something might be changing in the app pool identity's user. But we have ruled this out since both apps are running under the same user and when server B breaks, server A continues to work, even after IISRESET and rebooting.
As far as we're aware the settings on the two servers are the same (to the extent possible, since they are different operating systems and IIS versions)
Can anyone think of a reason this might be happening? Thanks in advance.
Make sure you set the "Load User Profile" to true in iis application pool advance setting.
Edit:
Only the local operating system has access to this machine key which is unique for every installation. Windows supports the DPAPI for protecting data with this key. You don’t have direct access to the key when using this API. You can ask the system to encrypt or decrypt something with the machine’s key. In this way, your application could encrypt the key used by it through the DPAPI and .NET Framework supports the class System.Security.Cryptography.ProtectedData.
You should add a reference to the System.Security.dll assembly and import the System.Security.Cryptography namespace when you want to use the ProtectedData class for protecting sensitive information. Possible scopes are LocalMachine and CurrentUser.
You can select the LocalMachine when you want to use the machine key.
You can select the CurrentUser when you want to use a key generated for the currently logged-on user’s profile. In the case of Active Directory roaming profiles that allow reusing a Windows user profile on several Windows machines within an Active Directory domain, this key is machine-independent.
The administrator of the machine can decrypt the data by writing a program that calls the previous function.
If the user is not the administrator and has no permission to use the DPAPI, he/she cannot decrypt data encrypted with the machine key.
You should not use DPAPI to encrypt information in your database, because encrypted data is bound to the machine if you use the DataProtectionScope.LocalMachine setting. If the machine crashes and you have to restore your data on another machine, you will lose all the encrypted information.
You should have a backup of the key in another secure place, if you use the DPAPI for encrypting the key as described previously.
You have to run your application under a domain user account and use the key created for the user’s profile (DataProtectionScope.CurrentUser) if you want to use the DPAPI in web farm scenarios. You should create a separate domain for your web farm so that you don’t have to use a domain user of your company’s internal domain network.
Reference links:
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata?view=dotnet-plat-ext-3.1
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata.unprotect?view=dotnet-plat-ext-3.1
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata.protect?view=dotnet-plat-ext-3.1