Skip to content
This repository has been archived by the owner on Oct 17, 2018. It is now read-only.

Cannot unprotect data after upgrading .NET Framework app to new DataProtection version #187

Closed
nphmuller opened this issue Nov 23, 2016 · 8 comments
Assignees

Comments

@nphmuller
Copy link

An exception is thrown when I try to unprotect data in release 1.1.0 which was protected with release 1.0.0. This only happens when I target the full .Net Framework stack (only tested net462). When I target netcoreapp everything runs smoothly.

Seems like there are some differences between .Net Full and .Net Core in the way library versions are bound. In issue #153 almost the same problem happens.

These are the exception details:

System.Security.Cryptography.CryptographicException was unhandled
  HResult=-2146233296
  Message=The provided payload could not be decrypted. Refer to the inner exception for more information.
  Source=Microsoft.AspNetCore.DataProtection
  StackTrace:
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked)
       at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)
       at Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(IDataProtector protector, String protectedData)
       at ConsoleApp2.Program.Main(String[] args) in c:\users\mulle\documents\visual studio 2015\Projects\ConsoleApp2\src\ConsoleApp2\Program.cs:line 20
  InnerException: 
       FileName=Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
       FusionLog==== Pre-bind state information ===
LOG: DisplayName = Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 (Fully-specified)
LOG: Appbase = file:///c:/users/mulle/documents/visual studio 2015/Projects/ConsoleApp2/src/ConsoleApp2/bin/Debug/net462/win7-x64/
LOG: Initial PrivatePath = NULL
Calling assembly : Microsoft.AspNetCore.DataProtection, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: c:\users\mulle\documents\visual studio 2015\Projects\ConsoleApp2\src\ConsoleApp2\bin\Debug\net462\win7-x64\ConsoleApp2.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
LOG: Attempting download of new URL file:///c:/users/mulle/documents/visual studio 2015/Projects/ConsoleApp2/src/ConsoleApp2/bin/Debug/net462/win7-x64/Microsoft.AspNetCore.DataProtection.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Minor Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

       HResult=-2146234304
       Message=Could not load file or assembly 'Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
       Source=mscorlib
       StackTrace:
            at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
            at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
            at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
            at System.Type.GetType(String typeName, Boolean throwOnError)
            at Microsoft.AspNetCore.DataProtection.SimpleActivator.CreateInstance(Type expectedBaseType, String implementationTypeName)
            at Microsoft.AspNetCore.DataProtection.ActivatorExtensions.CreateInstance[T](IActivator activator, String implementationTypeName)
            at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement)
            at Microsoft.AspNetCore.DataProtection.KeyManagement.DeferredKey.<>c__DisplayClass1_0.<GetLazyEncryptorDelegate>b__0()
            at System.Lazy`1.CreateValue()
            at System.Lazy`1.LazyInitValue()
            at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRing.KeyHolder.GetEncryptorInstance(Boolean& isRevoked)
            at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRing.GetAuthenticatedEncryptorByKeyId(Guid keyId, Boolean& isRevoked)
            at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)
       InnerException: 

I wrote a small app that demonstrates my problem:

project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.AspNetCore.DataProtection.Extensions": "1.1.0"
  },

  "frameworks": {
    "net462": {
      "dependencies": {
        "System.Reflection": "4.*",
        "System.Runtime": "4.*",
        "System.Runtime.Extensions": "4.*"
      }
    } 
  }
}

Program.cs:

using System;
using System.IO;
using Microsoft.AspNetCore.DataProtection;

namespace ConsoleApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var keysDir = new DirectoryInfo(Environment.ExpandEnvironmentVariables(@"%localappdata%\ASP.NET\DataProtection-Keys"));
            var protector = DataProtectionProvider.Create(keysDir).CreateProtector("Test");

            string protectedData;
            // The commented line was ran with "Microsoft.AspNetCore.DataProtection.Extensions" on version 1.0.0 in project.json.
            // This was used to create the protected data used in the line below it.
            //protectedData = protector.Protect("TestData");
            protectedData = "CfDJ8Hfj9GhtU4RDpuGkMJ0qEoKKKVc2uSFps_1jM0HoQKiXD8ii6UrKRFQ2YzMhm7pHLtFlKWk7XhJymmxCb1Ci7p2d34I-1VAn7xQgkMTAUKmi_Td11UXfN3FARidrfzL6IA";

            //The exception is thrown on this line:
            var unprotectedData = protector.Unprotect(protectedData);
        }
    }
}

And the key file (key-68f4e377-536d-4384-a6e1-a4309d2a1282.xml).
Place it in '%LocalAppData%\ASP.NET\DataProtection-Keys' (or change the line of code).
Don't worry, the key was created only for this issue ;)

<?xml version="1.0" encoding="utf-8"?>
<key id="68f4e377-536d-4384-a6e1-a4309d2a1282" version="1">
  <creationDate>2016-11-23T21:37:00.3045352Z</creationDate>
  <activationDate>2016-11-23T21:37:00.2025208Z</activationDate>
  <expirationDate>2017-02-21T21:37:00.2025208Z</expirationDate>
  <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
    <descriptor>
      <encryption algorithm="AES_256_CBC" />
      <validation algorithm="HMACSHA256" />
      <masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
        <!-- Warning: the key below is in an unencrypted form. -->
        <value>rA5uDx7kFHrx0Qt+owWotP0NQf/wBxL/breAbCh+AOVjrdGHca5hgIIuQIlyBFlXB/X1pXj6tL40JwQ6iUD43Q==</value>
      </masterKey>
    </descriptor>
  </descriptor>
</key>
@KLuuKer
Copy link

KLuuKer commented Nov 28, 2016

I have exactly the same issue, but since i have a custom dataprotectionrepository i just do this before loading the xml

  rawxmlstring = rawxmlstring.Replace(
                        "Microsoft.AspNetCore.DataProtection, Version=1.0.0.0,",
                        "Microsoft.AspNetCore.DataProtection, Version=1.1.0.0,");

it would be nice if i didn't have todo this tough, since this also won't create a new key that uses the new assembly version

@muratg
Copy link

muratg commented Nov 28, 2016

@pakrym thoughts?

@nphmuller
Copy link
Author

Any updates on this issue? Would hate to run into this problem again when the next version is released.

@snickler
Copy link

snickler commented Feb 6, 2017

@nphmuller , have you tried downgrading Kestrel to 1.0.2? I've had some similar weird issues in regards to using OpenId while having everything on 1.1.

@kevinchalet
Copy link

@muratg could that be fixed in the next milestone to make sure the same issue doesn't reproduce when moving from 1.x to 2.0?

@muratg muratg added this to the 2.0.0 milestone Mar 6, 2017
@muratg muratg assigned natemcmaster and unassigned pakrym Apr 13, 2017
@natemcmaster natemcmaster changed the title Cannot unprotect 1.0.0 data in 1.1.0 when targetting net46x Cannot unprotect data after upgrading to .NET Framework app to new DataProtection version Apr 25, 2017
@natemcmaster natemcmaster changed the title Cannot unprotect data after upgrading to .NET Framework app to new DataProtection version Cannot unprotect data after upgrading .NET Framework app to new DataProtection version Apr 25, 2017
@kspearrin
Copy link

@natemcmaster I just hit this error again when migrating DataProtection from 1.1.1 to 1.1.2. Is this expected until this fix goes live?

@snickler
Copy link

snickler commented May 20, 2017 via email

@natemcmaster
Copy link
Contributor

The fix is in 2.0.0-preview1. It wasn't included it in 1.1.2. I've opened #235 as a separate issue to consider/discuss backporting this fix to 1.x.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants