将 machinekey.protect 加密从 .net 4.5 移植到 .net 7.0 (c#)

Porting machinekey.protect encryption from .net 4.5 to .net 7.0 (c#)

提问人:David 提问时间:11/14/2023 更新时间:11/15/2023 访问量:48

问:

我正在努力将解决方案从 .net 4.5.2 移植到 .net 7.0。在此解决方案中,有一个用于解密数据的类,该类在不同的设备上使用 MachineKey.Protect 进行编码(数据存储在数据库中)。在 .net 7.0 中,MachineKey.Protect 不再存在。

原代码如下:

    public class EncryptionHandler
    {
        public string Protect(byte[] data)
        {
            if (data == null || data.Length == 0) return null;
            var value = MachineKey.Protect(data);
            return Convert.ToBase64String(value);
        }

        public string Unprotect(string value)
        {
            if (value == "") return value;
            return Encoding.Unicode.GetString(MachineKey.Decode(value, MachineKeyProtection.Encryption));
        }

        internal void HackMachineKey() //This is used to insert the machinekey from the other device
        {
            var getter = typeof(MachineKeySection).GetMethod("GetApplicationConfig", BindingFlags.Static | BindingFlags.NonPublic);
            var config = (MachineKeySection)getter.Invoke(null, null);
            Console.WriteLine("Current Decryptionkey: " + config.DecryptionKey);
            var readOnlyField = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
            readOnlyField.SetValue(config, false);

            config.DecryptionKey = Properties.Settings.Default.MachineKeyDecryptionKey; 
            config.ValidationKey = Properties.Settings.Default.MachineKeyValidationKey;

            readOnlyField.SetValue(config, true);
        }
    }

在我移植到 .net 7 的端口中,我尝试插入键作为“目的”,但这显然不起作用:

    internal class NewEncryptionHandler
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();
        private IDataProtector _protector;
        //ToDo: move to external config
        private string _decryptionKey = "myMachineKey";
        private string _validationKey = "myValidationKey";

        internal NewEncryptionHandler(Config config)
        {
            var provider = DataProtectionProvider.Create("EzGetSettings");
            _protector = provider.CreateProtector(config.DecryptionKey, config.ValidationKey, "MachineKeyProtection.All");
        }

        internal string Unprotect(string? value)
        {
            byte[] protectedData = Encoding.UTF8.GetBytes( value);
            var unprotected= _protector.Unprotect(protectedData);
            return Convert.ToBase64String(unprotected);
        }
    }

我不确定如何正确创建或配置 DataProtectionProvider。任何帮助将不胜感激!

C# 加密 NET-7.0 MachineKey

评论


答:

1赞 Denis Micheal 11/14/2023 #1

按照文档中的此示例进行操作。

确保将其添加到 .Program.cs

builder.Services.AddDataProtection();

然后在你的类 Dependency 中,在构造函数中注入接口,如下所示:IDataProtectionProvider

public class NewEncryptionHandler
{
   IDataProtector _protector;

   public NewEncryptionHandler(IDataProtectionProvider provider)
   {
     _protector = provider.CreateProtector("purpose");
   }
}

然后在你的加密中:NewEncryptionHandler

var encrypted = _protector.Protect("TEST");

要解密:

var decrypted = _protector.Unprotect(encrypted);

编辑

使用 Console 并使用 main 方法的示例:

static void Main(string[] args)
{
    // add data protection services
    var serviceCollection = new ServiceCollection();
    serviceCollection.AddDataProtection();
    var serviceProvider = serviceCollection.BuildServiceProvider();


    // Create a data protector
    var dataProtector = serviceProvider.GetService<IDataProtectionProvider>();

    // Create an instance of NewEncryptionHandler
    var newEncryptionHandler = new NewEncryptionHandler(dataProtector);

    // Call encryption and decryption methods
    var plainText = "Hello, world!";
    var encryptedData = newEncryptionHandler.EncryptData(plainText);
    var decryptedText = newEncryptionHandler.DecryptData(encryptedData);


    Console.WriteLine($"Plain text: {plainText}");
    Console.WriteLine($"Encrypted data: {encryptedData}");
    Console.WriteLine($"Decrypted text: {decryptedText}");
}

班级:NewEncryptionHandler

public class NewEncryptionHandler
{
    private readonly IDataProtector _dataProtector;

    public NewEncryptionHandler(IDataProtectionProvider dataProtector)
    {
        _dataProtector = dataProtector.CreateProtector("purpose");
    }

    public string EncryptData(string plainText)
    {
        // Encrypt data using the data protector
        return _dataProtector.Protect(plainText);
    }

    public string DecryptData(string encryptedData)
    {
        // Decrypt data using the data protector
        return _dataProtector.Unprotect(encryptedData);
    }
}

评论

0赞 David 11/14/2023
对不起,我没有提到它,但它是一个控制台应用程序,而不是 .net 核心应用程序。所以没有建设者。我不确定如何以这种方式插入服务,或者这是否有必要。主要问题似乎是我错误地设置了 protectionprovider。我的错误消息是:“无法验证数据:System.Security.Cryptography.CryptographicException:无法解密提供的有效负载,因为它未受此保护提供程序的保护。
0赞 Denis Micheal 11/15/2023
还添加了有关如何在控制台上执行此操作的编辑,您也没有分享您是如何调用的,但我假设加密/解密的调用方法是不同的。Protect_protector
0赞 David 11/15/2023
感谢您的努力,但我不认为这解决了我的问题:数据在另一台机器上使用 .net 4.5 MachineKey.Protect(data) 加密;加密,这就是我只使用 Decrypt 的原因。我遇到的问题是我不知道如何在 IDataProtector 中插入 machinekey。我认为这应该使用 IXmlRepository 来完成,但我不知道如何完成。
0赞 Denis Micheal 11/15/2023
值得一读