aspnet/DataProtection

ProtectKeysWithDpapiNG fails with error "The specified data could not be decrypted"

patnolan opened this issue · 2 comments

I'm using ASPNetCore and want to use ProtectKeysWithDpapiNG to encrypt a password but I'm getting the following exception when executing "protector.Protect("password");" (see stack trace below)
System.Security.Cryptography.CryptographicException: 'The specified data could not be decrypted.'

I'm using a .pfx file which has been installed for the Current User. To create the .pfx file I used makecert and pvk2pfx.

Am I doing something wrong? Should this work?

My Code...

AddDataProtection in ConfigureServices(IServiceCollection services) code

using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
     store.Open(OpenFlags.ReadOnly);
     var protection = services.AddDataProtection();
     protection.ProtectKeysWithDpapiNG($"CERTIFICATE=HashId:{<thumbprint>}", flags: 
     DpapiNGProtectionDescriptorFlags.None);

     protection.PersistKeysToFileSystem(new DirectoryInfo(<location>));
     protection.SetApplicationName("e5AnywhereApi");
}

CreateProtector code

var protection = app.ApplicationServices.GetDataProtectionProvider();
var protector = protection.CreateProtector("<protector>");
var test = protector.Protect("password");

StackTrace

at Microsoft.AspNetCore.DataProtection.Cng.DpapiSecretSerializerHelper.UnprotectWithDpapiNGCore(Byte* pbData, UInt32 cbData)\r\n   
at Microsoft.AspNetCore.DataProtection.Cng.DpapiSecretSerializerHelper.UnprotectWithDpapiNG(Byte[] protectedData)\r\n   
at Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor.Decrypt(XElement encryptedElement)\r\n  
 at Microsoft.AspNetCore.DataProtection.XmlEncryption.XmlEncryptionExtensions.DecryptElement(XElement element, IActivator activator)\r\n   
at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement)\r\n   
at Microsoft.AspNetCore.DataProtection.KeyManagement.DeferredKey.<>c__DisplayClass1_0.<GetLazyEncryptorDelegate>b__0()\r\n   
at System.Lazy`1.CreateValue()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   
at System.Lazy`1.get_Value()\r\n  
 at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRing.KeyHolder.GetEncryptorInstance(Boolean& isRevoked)\r\n   
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRing.get_DefaultAuthenticatedEncryptor()\r\n   
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext)\r\n   
at Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Protect(IDataProtector protector, String plaintext)

Looks similar to #176.

You said "I'm using a .pfx file which has been installed for the Current User.", yet your code uses StoreLocation.LocalMachine. Did you mean to use StoreLocation.CurrentUser instead?

Sorry I just updated the sample code to use CurrentUser. I had left LocalMachine in from a previous test.

However you are right it does look similar to #176. I will close this issue and move my comment there.