为什么需要数据保护

Web应用程序中经常需要存储一些敏感数据(如用户密码),Windows 系统为桌面程序提供了DPAPI用来使用,但是并不适用于Web系统。ASP.NET Core提供了一套简单易用的API用来保护数据

ASP.NET Core 中,数据保护主要是用来给服务端设计的,用来替换ASP.NET 1.x-4.x中的,machineKey主要是用来保证使用Form身份验证时Cookie数据的加密解密,以确保不会被修改。或者ViewState数据的加密解密不被篡改,以及对session状态标识进行验证

最简单的示例

  1. public class MyClass
  2. {
  3. readonly IDataProtector protector;
  4. public MyClass(IDataProtectionProvider provider)
  5. {
  6. protector = provider.CreateProtector(nameof(MyClass));
  7. }
  8. public void RunSample()
  9. {
  10. string testStr = "Hello World";
  11. // 加密
  12. string protectedPayload = protector.Protect(testStr);
  13. Console.WriteLine($"Protect returned: {protectedPayload}");
  14. Console.WriteLine("=========================================");
  15. // 解密
  16. string unprotectedPayload = protector.Unprotect(protectedPayload);
  17. Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
  18. }
  19. }
  1. [TestMethod()]
  2. public void Sample_01()
  3. {
  4. // 添加数据保护到服务中
  5. var serviceCollection = new ServiceCollection();
  6. serviceCollection.AddDataProtection();
  7. var services = serviceCollection.BuildServiceProvider();
  8. // 从DI中创建一个MyClass的实例
  9. var instance = ActivatorUtilities.CreateInstance<MyClass>(services);
  10. instance.RunSample();
  11. Assert.IsTrue(true);
  12. }

image.png

CreateProtector(nameof(MyClass))中,参数“nameof(MyClass)”可以理解为一个公钥或一个标识,指示当前Protector的用途。因为ASP.NET Core Data Protection 是非对称加密,所以系统中应该还有一个密钥,此处的密钥 ASP.NET Core 在系统内部帮你维护了,每一台机器都有一个自有的私钥

私钥存储

  • 如果程序寄宿在Microsoft Azure下,存储在“%HOME%\ASP.NET\DataProtection-Keys”文件夹
  • 如果程序寄宿在IIS下,它被保存在HKLM注册表的ACLed特殊注册表键,并且只有工作进程可以访问,它使用windowsDPAPI加密
  • 如果当前用户可用,即win10或者win7中,它存储在%LOCALAPPDATA%\ASP.NET\DataProtection-Keys”文件夹,同样使用的windowsDPAPI加密
  • 如果这些都不符合,那么也就是私钥是没有被持久化的,也就是说当进程关闭的时候,生成的私钥就丢失了

私钥文件示例

image.png

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <key id="bf2f4417-10fa-4d4d-ba61-b91c041029e0" version="1">
  3. <creationDate>2021-03-08T02:18:08.641323Z</creationDate>
  4. <activationDate>2021-03-09T09:07:57.9935838Z</activationDate>
  5. <expirationDate>2021-06-06T02:18:08.5176468Z</expirationDate>
  6. <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
  7. <descriptor>
  8. <encryption algorithm="AES_256_CBC" />
  9. <validation algorithm="HMACSHA256" />
  10. <encryptedSecret decryptorType="Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor, Microsoft.AspNetCore.DataProtection, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" xmlns="http://schemas.asp.net/2015/03/dataProtection">
  11. <encryptedKey xmlns="">
  12. <!-- This key is encrypted with Windows DPAPI. -->
  13. <value>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAdzyZbq38yUupe39PhMdBEAAAAAACAAAAAAAQZgAAAAEAACAAAACYrALB9ricGU/5Y6iOanIlQjSCb548eBxAWafTbwxtLAAAAAAOgAAAAAIAACAAAADd6x5zXIP/VC6r1Y5ZAf74uL/+lc68ilrliN7T8dGhYVABAAD0qlvH4LDPjhr3R9WTjP+mOJZrrtt8clI91ULbNPDN2bgwM7ibkICFOLVr9AkwMpRzP+etArhuXbIhH6jzdv9aoAjAcQsQtg37LSlWBI3TFmTtz53nHzIxmfgUuPS23sLjHc7KTBo9+DPHy5BT3qm21y8EDoQ8ehj6WqqwvaEkThRXcG5Kst5HzBbIgeRXSrSprjIeja0uhJpFJOAzOr5ngeoRG4tKfs6VMZMIU9IMbukbuGSC/JoUMR5yzavT/Yi+Cr9x9eeIewDOKzRIaq3wIkYIybhOJxZm5MMgV3A4j4nKSSN0jcW6hXee5ksdywsPKquK5E5fz/jY6bVc9Sj1DV+A6IN6MAjstQzYpZ6CIjFJwgwD7OpD9G/JmlwRNhB/TnNWKAW+4duXYEgKADWA4ZVg2riaYYphPbEmz5RXnphN+C6OEDozguAsW60Z2DJAAAAAPxkE7aqhWgiAk2Fxf8w1yZ6ZMkBSXe/b655jsvfLl6asBUStynk08vPaw5YsD61VyRNp/s8lRjrfwyHpTGrxOw==</value>
  14. </encryptedKey>
  15. </encryptedSecret>
  16. </descriptor>
  17. </descriptor>
  18. </key>

文件包含一个创建日期,一个过期日期。间隔为90天,当90天之后密钥就会失效,系统将自动生成一个新的密钥并设置新的密钥作为活动的密钥。只要已过期的密钥还存在于系统上,仍然可以解密任何受保护的数据