Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data protection in ASP.NET Core 2.1 only works on one machine

I'm using the ASP.NET Core Data Protection system to encrypt data with Application A and decrypt it with Application B.

Encryption and decryption both work when run on the development machine, but when Application B is moved to the production machine it's no longer able to decrypt because the IDataProtector.Unprotect method throws an exception:

System.InvalidOperationException: The key ring does not contain a valid default protection key. The data protection system cannot create a new key because auto-generation of keys is disabled.

Here's the code I'm using to configure decryption in Application B:

sKeysPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Keys");

services.AddDataProtection()
    .SetApplicationName("My Application") // Application A sets this same name
    .PersistKeysToFileSystem(new DirectoryInfo(sKeysPath))
    .ProtectKeysWithCertificate("634D3F23...")
    //.ProtectKeysWithCertificate(x509Certificate2) // I've tried using an X509 certificate parameter but it gives the same result as providing the thumbprint of the one in the certificate store
    .DisableAutomaticKeyGeneration(); // Application A is the master key generator so do not generate keys

The production machine does contain the same Keys folder (with .pfx and .xml files) and same keys installed in the Windows certificate store.

As I understand it, by providing the certificate file to the Data Protection system, it should work on any machine and not be binded to a specific machine or Windows user. Is that assumption incorrect or is there an issue with the way I'm performing decryption?

Here are some more detailed logging messages:

2018-06-13 16:32:32.6750 | TRACE | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector | 5 | Performing unprotect operation to key {846541...} with purposes ('My Application', 'My Purpose').

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository | 37 | Reading data from file 'C:\inetpub\wwwroot\My Website\Keys\key-846541....xml'.

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager | 18 | Found key {846541...}.

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 13 | Considering key {846541...} with expiration date 2038-01-18 20:54:13Z as default key.

2018-06-13 16:32:32.6750 | DEBUG | Microsoft.AspNetCore.DataProtection.TypeForwardingActivator | Forwarded activator type request from Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor, Microsoft.AspNetCore.DataProtection, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60

2018-06-13 16:32:32.7051 | ERROR | Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager | 24 | An exception occurred while processing the key element '<key id="846541..." version="1" />'. Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist

2018-06-13 16:32:32.7051 | TRACE | Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager | 25 | An exception occurred while processing the key element '<key id="846541..." version="1" />...

2018-06-13 16:32:32.7051 | WARN | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 12 | Key {846541...} is ineligible to be the default key because its CreateEncryptor method failed. Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist

2018-06-13 16:32:32.7051 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 14 | Key {846541...} is no longer under consideration as default key because it is expired, revoked, or cannot be deciphered.

2018-06-13 16:32:32.7051 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver | 53 | Repository contains no viable default key. Caller should generate a key with immediate activation.

2018-06-13 16:32:32.7051 | DEBUG | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider | 57 | Policy resolution states that a new key should be added to the key ring.

2018-06-13 16:32:32.7051 | ERROR | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider | 49 | The key ring does not contain a valid default key, and the key manager is configured with auto-generation of keys disabled.

2018-06-13 16:32:32.7051 | ERROR | Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider | 48 | An error occurred while reading the key ring. System.InvalidOperationException: The key ring does not contain a valid default protection key. The data protection system cannot create a new key because auto-generation of keys is disabled.

like image 375
Coder6841 Avatar asked Jun 13 '18 18:06

Coder6841


People also ask

What is data protection in ASP.NET Core?

The ASP.NET Core data protection provides a cryptographic API to protect data, including key management and rotation. Web applications often need to store security-sensitive data. Windows provides a data protection API, DPAPI, but Windows DPAPI isn't intended for use in web applications.

Is an interface that can provide data protection services in dotnet core?

Encrypting and Decrypting Data with IDataProtector IDataProtector is an interface that provides data protection services. To be able to use its features, we have to add those data protection services to the specified IServiceCollection and then inject it using dependency injection.

Which class interface provide data protection services?

IDataProtector Interface (Microsoft. AspNetCore. DataProtection) An interface that can provide data protection services.


2 Answers

Thanks to Joe Audette's suggestion I checked out the detailed logging and found a more specific error which pointed me to this answer which had the solution.

The problem was that the permissions for the certificate in the Windows certificate store did not have the IIS_IUSRS group set to allow read access (Right click certificate → All Tasks → Manage Private Keys…). This issue didn't appear on the development machine because there it was running under Visual Studio's user context instead.

like image 146
Coder6841 Avatar answered Sep 21 '22 10:09

Coder6841


I had a similar issue, however it was between two different ASP.NET Core applications that were trying to share the same cookie. A minor version mismatch in Microsoft.AspNetCore.Authentication.Cookies (2.1.2 vs 2.2.0) was causing one of the applications to not be able to find the keys created by the other version.

Adding this answer here (even though it doesn't answer the above question), as the error messages match exactly, and hopefully it saves someone a few hours.

like image 23
tejas Avatar answered Sep 19 '22 10:09

tejas