How to protect data protection key files with a certificate on Asp.Net Core 2 on debian / linux

I am trying to configure data protection and use a certificate to protect key files. Here is the MS documentation Configuring Data Protection

Here is what I am trying to do:

services .AddDataProtection() .SetApplicationName("test server") .PersistKeysToFileSystem("/home/www-data/config") .ProtectKeysWithCertificate( new X509Certificate2("/home/www-data/config/"keyprotection.pfx); 

When I launch the application, I get the following error on startup:

 info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58] Creating key {71e2c23f-448b-49c9-984f-3c8d7227c904} with creation date 2017-08-29 18:53:51Z, activation date 2017-08-29 18:53:51Z, and expiration date 2017-11-27 18:53:51Z. info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39] Writing data to file '/home/www-data/config/key-71e2c23f-448b-49c9-984f-3c8d7227c904.xml'. fail: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[24] An exception occurred while processing the key element '<key id="71e2c23f-448b-49c9-984f-3c8d7227c904" version="1" />'. System.Security.Cryptography.CryptographicException: Unable to retrieve the decryption key. at System.Security.Cryptography.Xml.EncryptedXml.GetDecryptionKey(EncryptedData encryptedData, String symmetricAlgorithmUri) at System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument() at Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(XElement encryptedElement) at Microsoft.AspNetCore.DataProtection.XmlEncryption.XmlEncryptionExtensions.DecryptElement(XElement element, IActivator activator) at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement) warn: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[12] Key {71e2c23f-448b-49c9-984f-3c8d7227c904} is ineligible to be the default key because its CreateEncryptor method failed. System.Security.Cryptography.CryptographicException: Unable to retrieve the decryption key. at System.Security.Cryptography.Xml.EncryptedXml.GetDecryptionKey(EncryptedData encryptedData, String symmetricAlgorithmUri) at System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument() at Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(XElement encryptedElement) at Microsoft.AspNetCore.DataProtection.XmlEncryption.XmlEncryptionExtensions.DecryptElement(XElement element, IActivator activator) at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement) at Microsoft.AspNetCore.DataProtection.KeyManagement.DeferredKey.<>c__DisplayClass1_0.<GetLazyDescriptorDelegate>b__0() at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy`1.CreateValue() at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyBase.get_Descriptor() at Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CreateEncryptorInstance(IKey key) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyBase.CreateEncryptor() at Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver.CanCreateAuthenticatedEncryptor(IKey key) warn: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[12] Key {71e2c23f-448b-49c9-984f-3c8d7227c904} is ineligible to be the default key because its CreateEncryptor method failed. System.Security.Cryptography.CryptographicException: Unable to retrieve the decryption key. at System.Security.Cryptography.Xml.EncryptedXml.GetDecryptionKey(EncryptedData encryptedData, String symmetricAlgorithmUri) at System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument() at Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(XElement encryptedElement) at Microsoft.AspNetCore.DataProtection.XmlEncryption.XmlEncryptionExtensions.DecryptElement(XElement element, IActivator activator) at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement) at Microsoft.AspNetCore.DataProtection.KeyManagement.DeferredKey.<>c__DisplayClass1_0.<GetLazyDescriptorDelegate>b__0() at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode) --- End of stack trace from previous location where exception was thrown --- 

Thus, the key is created and well encrypted. But it seems that somehow he does not know how to decrypt it, since he is talking about an error:

 System.Security.Cryptography.CryptographicException: Unable to retrieve the decryption key. 

If I understand correctly, it uses the certificate that I provided to encrypt the key. But it seems that for some reason it is not using the same certificate for decryption (it seems he is trying to return it from another location [store?]).

What is going wrong?

I also tried putting the certificate in the CA store as described here: Create a self-signed certificate and trust it on Ubuntu Linux

Then I tried to find them from the code as follows:

 var cert = new CertificateResolver().ResolveCertificate(CertThumbprint); 

But this did not work (he cannot find it).

I also tried to find them using the following approach:

 var store = new X509Store(StoreName.CertificateAuthority, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); var collection = store.Certificates.Find( X509FindType.FindByThumbprint, CertThumbprint, false); store.Close(); var x509Cert = collection.Count > 0 ? collection[0] : null; 

But that didn't work either.

So what is the right way?

+5
source share
1 answer

For reasons known only to Microsoft, ProtectKeysWithCertificate overrides that accept valid certificates (PFX files or X509Certificate2 objects) can only encrypt DPAPI data. Decryption only works if the same certificate is stored in the machine's certificate store, which makes these overrides relatively meaningless.

Why? Who knows. This is not particularly useful information, but it is vaguely rejected here as a “limitation of the basic structure”.

In this related discussion (which was simply closed without any help or involvement from Microsoft at all), the user shares custom persistence classes, which aren that influenced this cryptic “limitation”. GitHub repo linked below, I know this is an old question, but maybe this will help someone else.

https://github.com/tillig/DataProtection

Update: this will be fixed in the upcoming version of Core 2.1.0: https://github.com/aspnet/Home/issues/2759#issuecomment-367157751

+2
source

Source: https://habr.com/ru/post/1271350/


All Articles