- 通用
- 身份验证
- 授权
- 数据保护
- 机密管理
ASP.NET Core 的密钥管理可扩展性
提示
读取密钥管理然后再阅读本部分中,因为它介绍了这些 Api 的基本概念的某些部分。
警告
实现以下接口的任何类型应该是线程安全的多个调用方。
键
IKey
接口是加密系统中的键的基本表示形式。 在抽象意义上,"加密密钥材料"字面意义上不在此处使用术语该键。 一个键具有以下属性:
激活、 创建和过期日期
吊销状态
密钥标识符 (GUID)
此外,IKey
公开CreateEncryptor
方法用于创建IAuthenticatedEncryptor实例绑定到此密钥。
此外,IKey
公开CreateEncryptorInstance
方法用于创建IAuthenticatedEncryptor实例绑定到此密钥。
备注
没有 API 来检索从原始的加密材料IKey
实例。
IKeyManager
IKeyManager
接口表示负责常规密钥存储、 检索和操作的对象。 它公开三个高级操作:
创建新的密钥,并将其保存到存储。
从存储中获取所有键。
撤消一个或多个密钥并保存到存储吊销信息。
警告
编写IKeyManager
是一个非常高级的任务,和大多数开发人员不应尝试。 相反,大多数开发人员应充分利用所提供的功能XmlKeyManager类。
XmlKeyManager
XmlKeyManager
类型是内置具体实现IKeyManager
。 它提供了几个有用的功能,包括密钥托管和静态密钥加密。 在此系统中的密钥都表示为 XML 元素 (具体而言, XElement)。
XmlKeyManager
取决于在完成其任务的过程中的其他几个组件:
AlgorithmConfiguration
这决定了使用新的密钥的算法。IXmlRepository
其中将密钥保存在存储中的控件。IXmlEncryptor
[可选],它允许加密静态密钥。IKeyEscrowSink
[可选] 提供密钥托管服务。
IXmlRepository
其中将密钥保存在存储中的控件。IXmlEncryptor
[可选],它允许加密静态密钥。IKeyEscrowSink
[可选] 提供密钥托管服务。
下面是高级的关系图,指示如何这些组件连接在一起内XmlKeyManager
。
密钥创建 / CreateNewKey
在实现中的CreateNewKey
,则AlgorithmConfiguration
组件用于创建唯一IAuthenticatedEncryptorDescriptor
,然后序列化为 XML。 如果存在密钥托管接收器,则原始 (未加密) 的 XML 提供到接收器进行长期存储。 未加密的 XML 然后通过运行IXmlEncryptor
(如果需要) 来生成加密的 XML 文档。 此加密的文档保存到长期存储通过IXmlRepository
。 (如果没有IXmlEncryptor
是配置,未加密的文档保存在IXmlRepository
。)
密钥创建 / CreateNewKey
在实现中的CreateNewKey
,则IAuthenticatedEncryptorConfiguration
组件用于创建唯一IAuthenticatedEncryptorDescriptor
,然后序列化为 XML。 如果存在密钥托管接收器,则原始 (未加密) 的 XML 提供到接收器进行长期存储。 未加密的 XML 然后通过运行IXmlEncryptor
(如果需要) 来生成加密的 XML 文档。 此加密的文档保存到长期存储通过IXmlRepository
。 (如果没有IXmlEncryptor
是配置,未加密的文档保存在IXmlRepository
。)
密钥检索 / GetAllKeys
在实现中的GetAllKeys
、 XML 文档表示密钥和吊销读取从基础IXmlRepository
。 如果这些文档进行加密,系统将自动解密机密。 XmlKeyManager
创建适当IAuthenticatedEncryptorDescriptorDeserializer
实例进行反序列化文档回IAuthenticatedEncryptorDescriptor
实例,然后将封装在单个IKey
实例。 此集合的IKey
实例返回给调用方。
可在特定的 XML 元素的详细信息密钥存储格式的文档。
IXmlRepository
IXmlRepository
接口表示可以持久保存到 XML 并从后备存储中检索 XML 的类型。 它公开两个 Api:
GetAllElements
:IReadOnlyCollection<XElement>
StoreElement(XElement element, string friendlyName)
实现IXmlRepository
无需分析通过其传递的 XML。 它们应视为不透明的 XML 文档,让较高的层担心如何生成和分析文档。
有四种内置的具体类型实现IXmlRepository
:
请参阅密钥存储提供程序文档有关详细信息。
注册的自定义IXmlRepository
适合使用不同的后备存储 (例如,Azure 表存储) 时。
若要更改默认存储库应用程序范围,请注册自定义IXmlRepository
实例:
services.Configure<KeyManagementOptions>(options => options.XmlRepository = new MyCustomXmlRepository());
services.AddSingleton<IXmlRepository>(new MyCustomXmlRepository());
IXmlEncryptor
IXmlEncryptor
接口表示可以加密纯文本 XML 元素的类型。 它公开一个 API:
- Encrypt(XElement plaintextElement):EncryptedXmlInfo
如果一个序列化IAuthenticatedEncryptorDescriptor
包含任何元素标记为"需要加密",然后XmlKeyManager
将通过已配置运行这些元素IXmlEncryptor
的Encrypt
方法,并将保存到加密的元素而不是为纯文本元素IXmlRepository
。 输出Encrypt
方法是EncryptedXmlInfo
对象。 此对象是包含两个结果到加密的包装XElement
表示的类型和IXmlDecryptor
这可用于解密的相应元素。
有四种内置的具体类型实现IXmlEncryptor
:
请参阅rest 文档在密钥加密有关详细信息。
若要更改默认在静态密钥加密机制整个应用程序范围,请注册自定义IXmlEncryptor
实例:
services.Configure<KeyManagementOptions>(options => options.XmlEncryptor = new MyCustomXmlEncryptor());
services.AddSingleton<IXmlEncryptor>(new MyCustomXmlEncryptor());
IXmlDecryptor
IXmlDecryptor
接口表示一种类型,知道如何解密XElement
的已加密通过IXmlEncryptor
。 它公开一个 API:
- Decrypt(XElement encryptedElement) :XElement
Decrypt
方法撤消由执行的加密IXmlEncryptor.Encrypt
。 通常情况下,每个具体IXmlEncryptor
实现都将具有相应的具体IXmlDecryptor
实现。
类型实现IXmlDecryptor
应具有以下两个公共构造函数之一:
- .ctor(IServiceProvider)
- .ctor()
备注
IServiceProvider
传递给构造函数可能为 null。
IKeyEscrowSink
IKeyEscrowSink
接口表示可执行托管的敏感信息的类型。 回想一下,序列化的描述符可能包含敏感信息 (如加密材料),这是什么导致了引入IXmlEncryptor键入第一个位置中。 但是,意外的发生,并且密钥环可以删除或损坏。
托管接口提供了允许访问原始序列化的 XML,通过配置的任何转换前一个紧急应急IXmlEncryptor。 该接口公开单个 API:
- 应用商店 (Guid keyId、 XElement 元素)
这就需要通过IKeyEscrowSink
实现来处理提供的元素以安全的方式与业务策略保持一致。 一个可能的实现可能是托管接收器使用的是已知的公司 X.509 证书的 XML 元素进行加密的证书的私钥已托管;CertificateXmlEncryptor
可以帮助解决这个问题类型。 IKeyEscrowSink
实现程序还负责适当地保留提供的元素。
默认情况下没有托管启用了机制,但服务器管理员可以全局配置此。 它还可以配置以编程方式通过IDataProtectionBuilder.AddKeyEscrowSink
方法,如下面的示例中所示。 AddKeyEscrowSink
方法重载镜像IServiceCollection.AddSingleton
并IServiceCollection.AddInstance
重载,为IKeyEscrowSink
实例都应是单一实例。 如果多个IKeyEscrowSink
注册实例,每个将调用在密钥生成过程,因此密钥可同时托管多个机制。
没有 API 中读取数据从IKeyEscrowSink
实例。 这与托管机制的设计从理论上讲是一致: 它可用于使密钥材料的受信任的颁发机构,并且由于应用程序本身不是受信任的颁发机构,它不应该有权访问其自身托管的材料。
下面的示例代码演示如何创建并注册IKeyEscrowSink
密钥托管,以便只有"CONTOSODomain 管理员"的成员可以恢复它们。
备注
若要运行此示例,必须是到已加入域的 Windows 8 / Windows Server 2012 计算机和域控制器必须是 Windows Server 2012 或更高版本。
using System; using System.IO; using System.Xml.Linq; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.DataProtection.XmlEncryption; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; public class Program { public static void Main(string[] args) { var serviceCollection = new ServiceCollection(); serviceCollection.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys")) .ProtectKeysWithDpapi() .AddKeyEscrowSink(sp => new MyKeyEscrowSink(sp)); var services = serviceCollection.BuildServiceProvider(); // get a reference to the key manager and force a new key to be generated Console.WriteLine("Generating new key..."); var keyManager = services.GetService<IKeyManager>(); keyManager.CreateNewKey( activationDate: DateTimeOffset.Now, expirationDate: DateTimeOffset.Now.AddDays(7)); } // A key escrow sink where keys are escrowed such that they // can be read by members of the CONTOSO\Domain Admins group. private class MyKeyEscrowSink : IKeyEscrowSink { private readonly IXmlEncryptor _escrowEncryptor; public MyKeyEscrowSink(IServiceProvider services) { // Assuming I'm on a machine that's a member of the CONTOSO // domain, I can use the Domain Admins SID to generate an // encrypted payload that only they can read. Sample SID from // https://technet.microsoft.com/library/cc778824(v=ws.10).aspx. _escrowEncryptor = new DpapiNGXmlEncryptor( "SID=S-1-5-21-1004336348-1177238915-682003330-512", DpapiNGProtectionDescriptorFlags.None, new LoggerFactory()); } public void Store(Guid keyId, XElement element) { // Encrypt the key element to the escrow encryptor. var encryptedXmlInfo = _escrowEncryptor.Encrypt(element); // A real implementation would save the escrowed key to a // write-only file share or some other stable storage, but // in this sample we'll just write it out to the console. Console.WriteLine($"Escrowing key {keyId}"); Console.WriteLine(encryptedXmlInfo.EncryptedElement); // Note: We cannot read the escrowed key material ourselves. // We need to get a member of CONTOSO\Domain Admins to read // it for us in the event we need to recover it. } } } /* * SAMPLE OUTPUT * * Generating new key... * Escrowing key 38e74534-c1b8-4b43-aea1-79e856a822e5 * <encryptedKey> * <!-- This key is encrypted with Windows DPAPI-NG. --> * <!-- Rule: SID=S-1-5-21-1004336348-1177238915-682003330-512 --> * <value>MIIIfAYJKoZIhvcNAQcDoIIIbTCCCGkCAQ...T5rA4g==</value> * </encryptedKey> */