ASP.NET Core 的密钥管理可扩展性Key management extensibility in ASP.NET Core

阅读本部分之前,请阅读部分,因为它说明了这些 api 背后的一些基本概念。

警告

实现以下接口的任何类型应该是线程安全的多个调用方。

接口是 cryptosystem 中密钥的基本表示形式。在抽象意义上,"加密密钥材料"字面意义上不在此处使用术语该键。一个键具有以下属性:

  • 激活、 创建和过期日期

  • 吊销状态

  • 密钥标识符 (GUID)

此外,IKey 公开了可用于创建绑定到此密钥的IAuthenticatedEncryptor实例的 CreateEncryptor 方法。

此外,IKey 公开了可用于创建绑定到此密钥的实例的 CreateEncryptorInstance 方法。

备注

没有用于从 IKey 实例检索原始加密材料的 API。

IKeyManagerIKeyManager

IKeyManager 接口表示负责常规密钥存储、检索和操作的对象。它公开三个高级操作:

  • 创建新的密钥,并将其保存到存储。

  • 撤消一个或多个密钥并保存到存储吊销信息。

警告

编写 IKeyManager 是一种非常高级的任务,大多数开发人员都不应尝试。相反,大多数开发人员应充分利用类提供的功能。

XmlKeyManager 类型是 IKeyManager的内置具体实现。它提供了几个有用的功能,包括密钥托管和静态密钥加密。此系统中的键表示为 XML 元素(特别是system.xml.linq.xelement>)。

XmlKeyManager 依赖于完成其任务的过程中的多个其他组件:

  • AlgorithmConfiguration,用于指示新密钥使用的算法。

  • IXmlEncryptor [可选],这允许静态加密密钥。

  • IKeyEscrowSink [可选],它提供密钥委托服务。

  • IXmlRepository,控制在存储中保留密钥的位置。

  • IXmlEncryptor [可选],这允许静态加密密钥。

  • IKeyEscrowSink [可选],它提供密钥委托服务。

下面是高级关系图,这些关系图指示如何在 XmlKeyManager中将这些组件连接在一起。

密钥创建/CreateNewKey

CreateNewKey的实现中,AlgorithmConfiguration 组件用于创建唯一 IAuthenticatedEncryptorDescriptor,然后将其序列化为 XML。如果存在密钥托管接收器,则原始 (未加密) 的 XML 提供到接收器进行长期存储。然后,将通过 IXmlEncryptor (如果需要)运行未加密的 XML,以生成加密的 XML 文档。此加密文档通过 IXmlRepository持久保存到长期存储。(如果未配置任何 IXmlEncryptor,则会将未加密的文档保留在 IXmlRepository中。)

密钥检索

密钥创建/CreateNewKey

CreateNewKey的实现中, 组件用于创建唯一 IAuthenticatedEncryptorDescriptor,然后将其序列化为 XML。如果存在密钥托管接收器,则原始 (未加密) 的 XML 提供到接收器进行长期存储。然后,将通过 IXmlEncryptor (如果需要)运行未加密的 XML,以生成加密的 XML 文档。此加密文档通过 IXmlRepository持久保存到长期存储。(如果未配置任何 IXmlEncryptor,则会将未加密的文档保留在 IXmlRepository中。)

密钥检索

密钥检索/GetAllKeys

GetAllKeys的实现中,将从基础 IXmlRepository读取表示键和吊销的 XML 文档。如果这些文档进行加密,系统将自动解密机密。XmlKeyManager 将创建适当的 IAuthenticatedEncryptorDescriptorDeserializer 实例,将文档反序列化为 IAuthenticatedEncryptorDescriptor 实例,然后将其包装在单独的 IKey 实例中。IKey 实例的集合将返回到调用方。

有关特定 XML 元素的详细信息,请参阅。

IXmlRepositoryIXmlRepository

IXmlRepository 接口表示可将 XML 保存到后备存储并从中检索 XML 的类型。它公开两个 Api:

  • GetAllElementsIReadOnlyCollection<XElement>

  • StoreElement(XElement element, string friendlyName)

有四种内置的具体类型可实现 IXmlRepository

有关详细信息,请参阅密钥存储提供程序文档

使用其他后备存储(例如 Azure 表存储)时,注册自定义 IXmlRepository 是合适的。

若要更改应用程序范围内的默认存储库,请注册自定义 IXmlRepository 实例:

IXmlEncryptor 接口表示可加密纯文本 XML 元素的类型。它公开一个 API:

  • 加密 (XElement plaintextElement): EncryptedXmlInfo

如果序列化的 IAuthenticatedEncryptorDescriptor 包含任何标记为 "需要加密" 的元素,则 XmlKeyManager 将通过配置的 IXmlEncryptorEncrypt 方法来运行这些元素,并将到加密元素而不是纯文本元素保存到 IXmlRepository 方法的输出是 EncryptedXmlInfo 对象。此对象是包含所生成的到加密 XElement 的包装,该类型表示可用于破译相应元素的 IXmlDecryptor

有四种内置的具体类型可实现 IXmlEncryptor

有关详细信息,请参阅。

若要更改应用程序范围内默认的密钥加密机制,请注册自定义 IXmlEncryptor 实例:

IXmlDecryptorIXmlDecryptor

IXmlDecryptor 接口表示一种类型,该类型知道如何解密通过 IXmlEncryptor到加密的 XElement它公开一个 API:

  • 解密 (XElement encryptedElement): XElement

Decrypt 方法撤销 IXmlEncryptor.Encrypt所执行的加密。通常,每个具体 IXmlEncryptor 实现都有相应的具体 IXmlDecryptor 实现。

实现 IXmlDecryptor 的类型应该具有以下两个公共构造函数之一:

  • .ctor(IServiceProvider)

备注

传递给构造函数的 IServiceProvider 可能为 null。

IKeyEscrowSink 接口表示可以执行敏感信息的委托的类型。请记住,序列化描述符可能包含敏感信息(如加密材料),这是第一个位置引入类型的结果。但是,意外的发生,并且密钥环可以删除或损坏。

托管接口提供了紧急转义影线,允许在任何已配置的IXmlEncryptor转换之前访问原始序列化的 XML。该接口公开单个 API:

  • 应用商店 (Guid keyId、 XElement 元素)

这取决于 IKeyEscrowSink 实现,以安全的方式处理所提供的元素,与业务策略一致。一个可能的实现可能是,托管接收器使用已知的公司 x.509 证书(其中证书的私钥已托管)对 XML 元素进行加密;CertificateXmlEncryptor 类型可帮助进行此类处理。IKeyEscrowSink 实现还负责正确保存提供的元素。

默认情况下,不启用任何托管机制,尽管服务器管理员可对。它还可以通过 IDataProtectionBuilder.AddKeyEscrowSink 方法以编程方式进行配置,如下面的示例中所示。AddKeyEscrowSink 方法重载会镜像 IServiceCollection.AddSingletonIServiceCollection.AddInstance 重载,因为 IKeyEscrowSink 实例将被单一实例。如果注册了多个 IKeyEscrowSink 实例,则会在密钥生成过程中调用每个实例,因此密钥可同时托管多个机制。

没有用于从 IKeyEscrowSink 实例读取材料的 API。这与托管机制的设计从理论上讲是一致: 它可用于使密钥材料的受信任的颁发机构,并且由于应用程序本身不是受信任的颁发机构,它不应该有权访问其自身托管的材料。

下面的示例代码演示如何创建和注册 IKeyEscrowSink,其中密钥是托管的,这样只有 "CONTOSODomain Admins" 的成员才能恢复它们。

若要运行此示例,必须是到已加入域的 Windows 8 / Windows Server 2012 计算机和域控制器必须是 Windows Server 2012 或更高版本。