【问题标题】:Decrypting FormsAuthentication.Encrypt in dotnet core在 dotnet 核心中解密 FormsAuthentication.Encrypt
【发布时间】:2020-10-03 01:53:45
【问题描述】:

我有使用 FormsAuthentication.Encrypt 由 .NET Framework 4.5.1 代码加密的数据,我需要能够使用 dotnet core 3.1 在代码中对其进行解密。

基于this documentation,我相信我应该能够通过在 .NET Framework 端使用 Microsoft.AspNetCore.DataProtection.SystemWeb 并在 dotnet 核心端配置数据保护来完成这项工作。但是,我收到以下错误:

CryptographicException: The payload was invalid.

在 .NET Framework 方面,我按照文档配置数据保护:

public class DataProtector : DataProtectionStartup
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddDataProtection()
            .SetApplicationName("myapp")
            .PersistKeysToFileSystem(new System.IO.DirectoryInfo("C:\\PathToKeys\\"));
    }
}

加密后的值是 FormsAuthentication.Encrypt(ticket); 的直接输出。我已经确认它使用了新机制:它将密钥保存在文件系统中,生成的密文以预期的 09F0C9F0 标头开头,并且 dotnet 核心代码既可以识别它,也能够识别它具有相关的密钥.但是,它实际上并没有取消保护。

dotnet 核心代码将其用作以下代码中“密文”的值:

static void Main(string[] args)
{
    var provider = DataProtectionProvider.Create(new DirectoryInfo("/pathToKeys"));
    var protector = provider.CreateProtector("myapp");//("FormsAuthentication.Ticket");
    byte[] b = HexToBinary(ciphertext);
    protector.Unprotect(b); // Error thrown here
}

根据我对相关代码的阅读,我尝试使用一些替代用途,例如“FormsAuthentication.Ticket”,但没有任何运气。是否有我在这里遗漏的步骤,或者我需要指定我不知道的目的?

按照建议添加 HexToBinary 代码。这是直接取自Microsoft.

        public static byte[] HexToBinary(string data)
    {
        if (data == null || data.Length % 2 != 0)
        {
            // input string length is not evenly divisible by 2
            return null;
        }

        byte[] binary = new byte[data.Length / 2];

        for (int i = 0; i < binary.Length; i++)
        {
            int highNibble = HexToInt(data[2 * i]);
            int lowNibble = HexToInt(data[2 * i + 1]);

            if (highNibble == -1 || lowNibble == -1)
            {
                return null; // bad hex data
            }
            binary[i] = (byte)((highNibble << 4) | lowNibble);
        }

        return binary;
    }
    public static int HexToInt(char h)
    {
        return (h >= '0' && h <= '9') ? h - '0' :
        (h >= 'a' && h <= 'f') ? h - 'a' + 10 :
        (h >= 'A' && h <= 'F') ? h - 'A' + 10 :
        -1;
    }

【问题讨论】:

  • 也许你可以参考this,看看Chris Pratt怎么说。
  • 谢谢,但这基本上是我在这里使用 Microsoft.AspNetCore.DataProtection.SystemWeb 所做的,以替换机器密钥机制。

标签: c# asp.net asp.net-core


【解决方案1】:

我能够解决这个问题。上面的代码在将 FormsAuthentication.Ticket 指定为 subPurpose 值时有效:

static void Main(string[] args)
{
    var provider = DataProtectionProvider.Create(new DirectoryInfo("/pathToKeys"));
    var protector = provider.CreateProtector("myapp", new string[] {"FormsAuthentication.Ticket"});
    byte[] b = HexToBinary(ciphertext);
    protector.Unprotect(b);
}

请注意,这在其他一些情况下会有所不同。例如,在 Web 服务中使用时,我需要添加数据保护,例如

WebHost.CreateDefaultBuilder(args)
.ConfigureServices(configureServices => {
    configureServices.AddDataProtection()
    .SetApplicationName("myapp")
    .PersistKeysToFileSystem(new DirectoryInfo(keyPath));
})
.UseStartup<Startup>()
.Build();

在此之后,后续调用可以创建相关的保护器,如下所示:

public Foo(IDataProtectionProvider provider)
{
    var protector = provider.CreateProtector("FormsAuthentication.Ticket");
    protector.Unprotect(ciphertext);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    相关资源
    最近更新 更多