• ASP.NET Core 6框架揭秘实例演示[20]:“数据保护”框架基于文件的密钥存储


    数据加解密与哈希》演示了“数据保护”框架如何用来对数据进行加解密,而“数据保护”框架的核心是“密钥管理”。数据保护框架以XML的形式来存储密钥,默认的IKeyManager实现类型为XmlKeyManager。接下来我们通过模拟代码和实例演示的形式来介绍一下XmlKeyManager对象针对密钥的创建、撤销和回收的实现原理。(本篇提供的实例已经汇总到《ASP.NET Core 6框架揭秘-实例演示版》)

    [S1308]基于本地文件系统的密钥管理(密钥创建)(源代码
    [S1309]基于本地文件系统的密钥管理(密钥撤销)(源代码

    [S1308]基于本地文件系统的密钥管理(密钥创建)

    接下来我们通过如下这个简单的演示实例来看看创建出来的密钥对应的XML具有怎样的结构。如代码片段所示,我们通过依赖注入容器得到IKeyManager对象,并用它创建了三个密钥。在调用AddDataProtection扩展方法后,我们调用返回IDataProtectionBuilder对象的PersistKeysToFileSystem扩展方法,其目的是利用FileSystemXmlRepository对象将代表创建密钥和密钥撤销操作的XML存储在指定的目录(“c:\keys”)下。

    复制代码
    using Microsoft.AspNetCore.DataProtection;
    using Microsoft.AspNetCore.DataProtection.KeyManagement;
    using Microsoft.Extensions.DependencyInjection;
    
    var directory = "c:\\keys";
    var services = new ServiceCollection();
    services
        .AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(directory));
    var keyManager = services
        .BuildServiceProvider()
        .GetRequiredService<IKeyManager>();
    
    var key1 = keyManager.CreateNewKey(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(1));
    var key2 = keyManager.CreateNewKey(DateTimeOffset.Now ,DateTimeOffset.Now.AddDays(2));
    var key3 = keyManager.CreateNewKey(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3));
    
    Console.WriteLine(key1.KeyId);
    Console.WriteLine(key2.KeyId);
    Console.WriteLine(key3.KeyId);
    
    复制代码

    演示程序运行后会将创建的三个密钥的ID以如图1的形式输出到控制台上。与此同时,目录“c:\keys\”下会出现三个对应的XML文件。从图中可以看出,表示密钥文件的名称正是调用IXmlRepository对象的StoreElement方法时指定的名称。

    image
    图1 以XML文件存储的密钥

    如下所示的是其中一个密钥对应的XML文件的内容。通过IAuthenticatedEncryptorDescriptor对象导出的XML体现在<key>/<descriptor>节点上。可以看出当前环境下默认采用的加密和哈希算法分别是AES_256_CBC和HMACSHA256,AuthenticatedEncryptorDescriptorDeserializer为采用的反序列化器类型。

    复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <key id="3f8769f0-78c8-42f2-9f13-102d83bb298c" version="1">
      <creationDate>2022-03-12T09:47:38.4677311Z</creationDate>
      <activationDate>2022-03-12T17:47:38.4630578+08:00</activationDate>
      <expirationDate>2022-03-13T17:47:38.4674829+08:00</expirationDate>
      <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=6.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>oFjUpRP4cKwp0QQctjibDN8QK3m76uQAlkGZ1V4E5sb9l9Yn4zzgjHyxpoJ7qENqBGwdD0A11U90YzGRb53p+g==</value>
          </masterKey>
        </descriptor>
      </descriptor>
    </key>
    复制代码

    [S1309]基于本地文件系统的密钥管理(密钥撤销)

    我们接着来看看密钥的撤销。如果是针对单个密钥的撤销,该密钥的ID会通过名为“key”的子元素保存下来。如果需要撤销现有的所有密钥,这个key元素的值会设置为“*”。两者采用的文件名称也不相同,格式分别为“revocation-{KeyId}”和“revocation-{RevocationDate}”。我们接下来演示针对密钥的撤销。如下面的代码片段所示,在得到IKeyManager对象之后,我们调用其GetAllKeys方法得到所有密钥。在调用RevokeKey方法撤销第一个得到密钥之后,我们调用RevokeAllKeys方法将现有密钥全部撤销掉。

    复制代码
    using Microsoft.AspNetCore.DataProtection;
    using Microsoft.AspNetCore.DataProtection.KeyManagement;
    using Microsoft.Extensions.DependencyInjection;
    
    var directory = "c:\\keys";
    var services = new ServiceCollection();
    services
        .AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(directory));
    var keyManager = services
        .BuildServiceProvider()
        .GetRequiredService<IKeyManager>();
    
    var key = keyManager.GetAllKeys().First();
    keyManager.RevokeKey(key.KeyId);
    keyManager.RevokeAllKeys(DateTimeOffset.Now, "Revocation Test");
    
    复制代码

    演示程序执行后会在密钥存储目录(c:\keys\)下生成两个名称前缀为“revocation-”的XML文件。与上面的代码进行比较,我们会发现XML文件的名称依然是调用IXmlRepository对象的StoreElement方法指定的名称。

    image
    图2 描述密钥撤销的XML文件

    如下所示的是这两个描述密钥撤销的XML文件的内容,可以看出XML结构与前面提供的RevokeKey和RevokeAllKeys方法的定义是匹配的。

    revocation-184d9274-78f1-4352-bbed-1d0d6803ddad.xml

    <?xml version="1.0" encoding="utf-8"?>
    <revocation version="1">
      <revocationDate>2022-03-12T09:54:48.1157691Z</revocationDate>
      <key id="184d9274-78f1-4352-bbed-1d0d6803ddad" />
      <reason />
    </revocation>

    revocation-20220312T0954481194781Z.xml

    复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <revocation version="1">
      <revocationDate>2022-03-12T17:54:48.1194781+08:00</revocationDate>
      <!-- All keys created before the revocation date are revoked. -->
      <key id="*" />
      <reason>Revocation Test</reason>
    </revocation>
    复制代码
  • 相关阅读:
    【数据结构功法】第4话 · 手把手拉着你入门单链表
    Django学习日志08
    智慧城市物联网建设:提升城市管理效率与居民生活品质
    【HTML实战】把爱心代码放在自己的网站上是一种什么体验?
    springboot项目打包上线
    为了带你搞懂 RPC,我们手写了一个 RPC 框架
    html入门综合练习
    解决常见的电脑故障
    企业微信知识库:从了解到搭建的全流程
    卡码网语言基础课 | 平均绩点
  • 原文地址:https://www.cnblogs.com/artech/p/inside-asp-net-core-6-20.html