ASP.NET Core의 키 관리 확장성
이 섹션을 읽기 전에 키 관리 섹션을 읽어보세요. 이러한 API의 이면에 있는 몇 가지 기본 개념을 설명합니다.
경고: 다음 인터페이스 중 하나를 구현하는 형식은 여러 호출자에 대해 스레드로부터 안전해야 합니다.
키
IKey
인터페이스는 암호화 시스템에 있는 키의 기본 표현입니다. 여기서 키라는 용어는 "암호화 키 자료"의 리터럴 의미가 아니라 추상적인 의미로 사용됩니다. 키에는 다음과 같은 속성이 있습니다.
활성화, 만들기 및 만료 날짜
해지 상태
키 식별자(GUID)
또한 IKey
는 이 키에 연결된 IAuthenticatedEncryptor 인스턴스를 만드는 데 사용할 수 있는 CreateEncryptor
메서드를 노출합니다.
또한 IKey
는 이 키에 연결된 IAuthenticatedEncryptor 인스턴스를 만드는 데 사용할 수 있는 CreateEncryptorInstance
메서드를 노출합니다.
참고 항목
IKey
인스턴스에서 원시 암호화 자료를 검색하는 API가 없습니다.
IKeyManager
IKeyManager
인터페이스는 일반 키 스토리지, 검색 및 조작을 담당하는 개체를 나타냅니다. 세 가지 상위 수준 작업을 노출합니다.
새 키를 만들고 스토리지에 유지합니다.
스토리지에서 모든 키를 가져옵니다.
하나 이상의 키를 해지하고 해지 정보를 스토리지에 유지합니다.
Warning
IKeyManager
작성은 매우 고급 작업이며 대부분의 개발자는 이 작업을 시도해서는 안 됩니다. 대신 대부분의 개발자는 XmlKeyManager 클래스에서 제공하는 기능을 활용해야 합니다.
XmlKeyManager
XmlKeyManager
형식은 IKeyManager
의 기본 제공되는 구체적인 구현입니다. 키 에스크로 및 키 rest암호화를 비롯한 몇 가지 유용한 기능을 제공합니다. 이 시스템의 키는 XML 요소(특히 XElement)로 표시됩니다.
XmlKeyManager
는 작업을 수행하는 과정에서 몇 가지 다른 구성 요소에 따라 달라집니다.
AlgorithmConfiguration
는 새 키에서 사용하는 알고리즘을 나타냅니다.IXmlRepository
는 스토리지에서 키가 유지되는 위치를 제어합니다.IXmlEncryptor
[선택 사항]: .에서 rest키를 암호화할 수 있습니다.IKeyEscrowSink
[선택 사항] - 주요 에스크로 서비스를 제공합니다.
IXmlRepository
는 스토리지에서 키가 유지되는 위치를 제어합니다.IXmlEncryptor
[선택 사항]: .에서 rest키를 암호화할 수 있습니다.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
를 구현하는 네 가지 기본 제공된 구체적인 형식이 있습니다.
자세한 내용은 키 스토리지 공급자 문서를 참조하세요.
다른 백업 저장소(예: Azure Table Storage)를 사용하는 경우 사용자 지정 IXmlRepository
를 등록하는 것이 적절합니다.
애플리케이션 전체에서 기본 리포지토리를 변경하려면 사용자 지정 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 를 참조하세요.
애플리케이션 전체에서rest 기본 키 암호화 메커니즘을 변경하려면 사용자 지정 IXmlEncryptor
인스턴스를 등록합니다.
services.Configure<KeyManagementOptions>(options => options.XmlEncryptor = new MyCustomXmlEncryptor());
services.AddSingleton<IXmlEncryptor>(new MyCustomXmlEncryptor());
IXmlDecryptor
IXmlDecryptor
인터페이스는 IXmlEncryptor
를 통해 암호화된 XElement
의 암호를 해독하는 방법을 알고 있는 형식을 나타냅니다. 단일 API를 노출합니다.
- Decrypt(XElement encryptedElement) : XElement
Decrypt
메서드는 IXmlEncryptor.Encrypt
에서 수행하는 암호화를 실행 취소합니다. 일반적으로 각 구체적인 IXmlEncryptor
구현에는 해당하는 구체적인 IXmlDecryptor
구현이 있습니다.
IXmlDecryptor
를 구현하는 형식에는 다음 두 개의 공용 생성자 중 하나가 있어야 합니다.
- .ctor(IServiceProvider)
- .ctor()
참고 항목
생성자에 전달된 IServiceProvider
는 Null일 수 있습니다.
IKeyEscrowSink
IKeyEscrowSink
인터페이스는 중요한 정보의 에스크로를 수행할 수 있는 형식을 나타냅니다. 직렬화된 설명자에는 중요한 정보(예: 암호화 자료)가 포함될 수 있으며, 이로 인해 IXmlEncryptor 형식이 처음으로 도입되었습니다. 그러나 인시던트가 발생하고 키 링이 삭제되거나 손상될 수 있습니다.
에스크로 인터페이스는 구성된 IXmlEncryptor에 의해 변환되기 전에 직렬화된 원시 XML에 액세스할 수 있도록 응급 이스케이프 해지를 제공합니다. 인터페이스는 단일 API를 노출합니다.
- 스토어(Guid keyId, XElement 요소)
비즈니스 정책과 일치하는 안전한 방식으로 제공된 요소를 처리하는 것은 IKeyEscrowSink
구현에 달려 있습니다. 한 가지 가능한 구현은 에스크로 싱크가 인증서의 프라이빗 키가 에스크로된 알려진 회사 X.509 인증서를 사용하여 XML 요소를 암호화하는 것입니다. CertificateXmlEncryptor
형식이 이 작업을 지원할 수 있습니다. 또한 IKeyEscrowSink
구현은 제공된 요소를 적절하게 유지합니다.
기본적으로 에스크로 메커니즘은 활성화되어 있지 않지만 서버 관리자는 이를 전역적으로 구성할 수 있습니다. 아래 샘플과 같이 IDataProtectionBuilder.AddKeyEscrowSink
메서드를 통해 프로그래밍 방식으로 구성할 수도 있습니다. IKeyEscrowSink
인스턴스가 싱글톤으로 사용되기 때문에 AddKeyEscrowSink
메서드 오버로드는 IServiceCollection.AddSingleton
및 IServiceCollection.AddInstance
오버로드를 미러링합니다. 여러 IKeyEscrowSink
인스턴스가 등록되면 키 생성 중에 각 인스턴스가 호출되므로 키를 동시에 여러 메커니즘에 에스크로할 수 있습니다.
IKeyEscrowSink
인스턴스에서 자료를 읽을 API가 없습니다. 이는 에스크로 메커니즘의 디자인 이론과 일치합니다. 즉, 신뢰할 수 있는 기관에서 키 자료에 액세스할 수 있도록 하기 위한 것이며, 애플리케이션 자체가 신뢰할 수 있는 기관이 아니므로 자체 에스크로된 자료에 액세스할 수 없어야 합니다.
다음 샘플 코드에서는 "CONTOSODomain Admins"의 멤버만 복구할 수 있도록 키가 에스크로되는 IKeyEscrowSink
를 만들고 등록하는 방법을 보여줍니다.
참고 항목
이 샘플을 실행하려면 도메인에 가입된 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>
*/
ASP.NET Core