ASP.NET Core 中的对字符串进行加密和解密

a60bc37a7c0aaaa4ffbd01c00a2eb1a7.jpeg

1. 引言

ASP.NET Core 数据保护提供加密 API,用于使用包括密钥管理、密钥轮换等在内的目的密钥对字符串进行加密和解密。可以通过使用 Windows DPAPI 加密或以纯文本形式安全地存储密钥,但它不适用于 Web 应用程序,因为它依赖于使用 DPAPI 来加密或解密它。我们将在这篇博文中更详细地讨论,敬请期待!

2. 什么是数据保护?

数据保护提供了我们简介中提到的加密 API,用于使用安全目的密钥加密和解密用户数据。那里有两种类型的密钥:

A. 主密钥
B. 目的

2.1. 主密钥

主密钥存在于密钥环中,用于保护和取消保护有效负载。密钥由数据保护提供商生成,并存储在配置的位置,即项目目录、共享位置、Azure 等内部。您可以选择使用 Windows DPAPI 加密主密钥,但它只能在 Windows 计算机上运行,而在 Linux 等非 Windows 环境中不起作用。

2.2 目的

目的是对数据进行加密,并使用相同的数据来解密数据。如果没有目的,解密的数据就无法反转为原始字符串。

3. 在 ASP.NET Core 应用中使用数据保护的两种方式

3.1 使用 DI(依赖注入)

在启动类中注册 DataProtection 服务,该启动类在控制器类或任何类的构造函数中注入 DataProtectionProvider 接口,并使用它来创建保护程序以保护或取消保护字符串。

3.2 无 DI(依赖注入)

使用 DataProtectionProvider 具体类创建数据保护,并在控制器中使用它来创建保护程序以保护或取消保护字符串。

4. 使用 DI 进行数据保护

4.1 启动类

使用目录信息注册数据保护服务,以将密钥存储在给定位置的密钥环中。此外,还有一个构建器服务选项,用于设置应用程序名称以区分应用程序之间的密钥,以便每个应用程序都有单独的密钥;否则,其他应用将共享相同的密钥。

public void ConfigureServices(IServiceCollection services)  
{  
  // Data protection service for crptography  
  services.AddDataProtection()  
          .SetApplicationName("MyAppName")  
          .PersistKeysToFileSystem(new DirectoryInfo(@"wwwroot/DataProtectionKeys"));  
}

4.2 数据保护自定义类

public class DataProtection {

  private IDataProtectionProvider _dataProtectionProvider;
  private IDataProtector _protector;

  // Data Protection class constructor 
  public DataProtection(IConfiguration configuration, IDataProtectionProvider dataProtectionProvider)
  {
      // Create the data protector from data protection provider with the purpose key
      _protector = dataProtectionProvider.CreateProtector("MyPurpose");
  }

  // Encrypt the user data
  public string Encrypt(string data)
  {
      return _protector.Protect(data);
  }

  // Decrypt the protected data
  public string? Decrypt(string data)
  {
      try
      {
          return _protector.Unprotect(data);
      }
      catch (CryptographicException ex)
      {
          return null;
      }
  }
}

5. 无 DI 的数据保护

5.1 启动类

无需在启动类中注册数据保护服务,因为某些项目具有不同的要求,并且不想使用依赖项注入。还有另一种方法可以在启动类中注册数据保护,并在自定义类中创建数据保护器,这使您在项目初始加载时创建一次数据保护提供程序。如果您想了解方法 3,请在下方发表评论以分享方法 3。

5.2 数据保护自定义类

public class DataProtection {

  private IDataProtectionProvider _dataProtectionProvider;
  private IDataProtector _protector;

  // Data Protection class constructor 
  public DataProtection(IConfiguration configuration)
  {
    // Creates the data protection provider and stores the generated key & other optional configurations
    _dataProtectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@configuration.GetSection("DataProtection:KeyPath").Value), (builder) => { builder.SetApplicationName("MyApplicationName"); });

    _protector = _dataProtectionProvider.CreateProtector("MyPurpose");
  }

  public string Encrypt(string data)
  {
      return _protector.Protect(data);
  }

  public string? Decrypt(string data)
  {
      try
      {
          return _protector.Unprotect(data);
      }
      catch (CryptographicException ex)
      {
          return null;
      }
  }
}

6. 使用 Windows DPAPI 注册数据保护以加密主密钥

6.1 启动类

使用 DPAPI 保护密钥环中的密钥。

public void ConfigureServices(IServiceCollection services)  
{  
  // Data protection service for crptography  
  services.AddDataProtection()  
          .SetApplicationName("MyAppName")  
          .PersistKeysToFileSystem(new DirectoryInfo(@"wwwroot/DataProtectionKeys"))  
          .ProtectKeysWithDpapi();  
}

7. 加密和解密字符串

public class UserController : ControllerBase
{
    IConfiguration _configuration;
    private IDataProtectionProvider _dataProtectionProvider;

    public PermissionController(IConfiguration configuration, IDataProtectionProvider dataProtectionProvider) {
        _configuration = configuration;
        _dataProtectionProvider = dataProtectionProvider;
    }

    /// <summary>
    /// Encrypt the string using the data protection class
    /// </summary>
    /// <param name="data"></param>
    /// <param name="purpose"></param>
    /// <returns></returns>
    [HttpGet]
    public ActionResult<string> Encrypt(string data, string purpose)
    {
        if(purpose != Constants.DataProtection.Purpose)
        {
            return BadRequest();
        }

        DataProtection dataProtection = new DataProtection(_configuration, _dataProtectionProvider);
        return dataProtection.Encrypt(data);
    }

    /// <summary>
    /// Decrypt the encrypted string using the data protection class
    /// </summary>
    /// <param name="data"></param>
    /// <param name="purpose"></param>
    /// <returns></returns>
    [HttpGet]
    public ActionResult<string> Decrypt(string data, string purpose)
    {
        if (purpose != Constants.DataProtection.Purpose)
        {
            return BadRequest();
        }

        DataProtection dataProtection = new DataProtection(_configuration, _dataProtectionProvider);
        var decryptedString = dataProtection.Decrypt(data);
        if(decryptedString == null)
        {
            return BadRequest();
        }
        return decryptedString;
    }
}

7.1 使用自定义数据保护类的控制器方法

7.2 输出

7.2.1 Postman 加密结果

0b988ebfc9d9b01a0aade0914db61901.png

7.2.2 Postman 解密结果

65ba739310ba6b0859b15287be955f7c.png

_注意:_DataProtectionProvider 具体类型的实例的创建成本很高。如果应用维护多个此类实例,并且它们都使用相同的密钥存储目录,则应用性能可能会降低。

如果你喜欢我的文章,请给我一个赞!谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值