Rozšiřitelnost správy klíčů v ASP.NET Core
Před čtením této části si přečtěte část správy klíčů, protože vysvětluje některé základní koncepty těchto rozhraní API.
Upozornění: Typy, které implementují některá z následujících rozhraní, by měly být pro více volajících bezpečné pro více volajících.
Klíč
Rozhraní IKey
je základní reprezentace klíče v kryptografickém systému. Klíč termínu se zde používá v abstraktním smyslu, ne v literálovém smyslu "kryptografický klíč materiálu". Klíč má následující vlastnosti:
Data aktivace, vytváření a vypršení platnosti
Stav odvolání
Identifikátor klíče (identifikátor GUID)
Kromě toho zveřejňuje metoduCreateEncryptor
, IKey
která se dá použít k vytvoření instance IAuthenticatedEncryptor svázané s tímto klíčem.
Kromě toho zveřejňuje metoduCreateEncryptorInstance
, IKey
která se dá použít k vytvoření instance IAuthenticatedEncryptor svázané s tímto klíčem.
Poznámka:
Z instance neexistuje žádné rozhraní API k načtení nezpracovaného IKey
kryptografického materiálu.
IKeyManager
Rozhraní IKeyManager
představuje objekt zodpovědný za obecné úložiště klíčů, načítání a manipulaci. Zpřístupňuje tři operace vysoké úrovně:
Vytvořte nový klíč a uložte ho do úložiště.
Získejte všechny klíče z úložiště.
Odvolejte jeden nebo více klíčů a uchováte informace o odvolání do úložiště.
Upozorňující
Psaní je IKeyManager
velmi pokročilý úkol a většina vývojářů by se o to neměla pokoušet. Místo toho by většina vývojářů měla využívat možnosti nabízené třídou XmlKeyManager .
XmlKeyManager
Typ XmlKeyManager
je in-box beton implementace IKeyManager
. Poskytuje několik užitečných zařízení, včetně klíče escrow a šifrování klíčů na restadrese . Klíče v tomto systému jsou reprezentovány jako elementy XML (konkrétně XElement).
XmlKeyManager
závisí na několika dalších komponentách v průběhu plnění svých úkolů:
AlgorithmConfiguration
, který určuje algoritmy používané novými klíči.IXmlRepository
– určuje, kde se klíče uchovávají v úložišti.IXmlEncryptor
[volitelné], což umožňuje šifrování klíčů na adrese rest.IKeyEscrowSink
[volitelné], které poskytuje služby pro úschovu klíčů.
IXmlRepository
– určuje, kde se klíče uchovávají v úložišti.IXmlEncryptor
[volitelné], což umožňuje šifrování klíčů na adrese rest.IKeyEscrowSink
[volitelné], které poskytuje služby pro úschovu klíčů.
Níže jsou uvedeny diagramy vysoké úrovně, které ukazují, jak jsou tyto komponenty propojeny v rámci XmlKeyManager
.
Vytvoření klíče / CreateNewKey
Při implementaci CreateNewKey
se komponenta AlgorithmConfiguration
používá k vytvoření jedinečného IAuthenticatedEncryptorDescriptor
, který se pak serializuje jako XML. Pokud je k dispozici jímka pro escrow klíče, nezpracovaný (nešifrovaný) XML je k dispozici jímce pro dlouhodobé úložiště. Nešifrovaný XML se pak spustí prostřednictvím IXmlEncryptor
(pokud je to nutné) pro vygenerování šifrovaného dokumentu XML. Tento šifrovaný dokument je trvale uložen do dlouhodobého úložiště prostřednictvím IXmlRepository
. (Pokud není nakonfigurovaný žádný IXmlEncryptor
, nezašifrovaný dokument se zachovají v souboru IXmlRepository
.)
Vytvoření klíče / CreateNewKey
Při implementaci CreateNewKey
se komponenta IAuthenticatedEncryptorConfiguration
používá k vytvoření jedinečného IAuthenticatedEncryptorDescriptor
, který se pak serializuje jako XML. Pokud je k dispozici jímka pro escrow klíče, nezpracovaný (nešifrovaný) XML je k dispozici jímce pro dlouhodobé úložiště. Nešifrovaný XML se pak spustí prostřednictvím IXmlEncryptor
(pokud je to nutné) pro vygenerování šifrovaného dokumentu XML. Tento šifrovaný dokument je trvale uložen do dlouhodobého úložiště prostřednictvím IXmlRepository
. (Pokud není nakonfigurovaný žádný IXmlEncryptor
, nezašifrovaný dokument se zachovají v souboru IXmlRepository
.)
Načítání klíčů / GetAllKeys
Při implementaci GetAllKeys
jsou dokumenty XML představující klíče a odvolání načteny z podkladového IXmlRepository
souboru . Pokud jsou tyto dokumenty šifrované, systém je automaticky dešifruje. XmlKeyManager
vytvoří příslušné IAuthenticatedEncryptorDescriptorDeserializer
instance pro deserializaci dokumentů zpět do IAuthenticatedEncryptorDescriptor
instancí, které jsou pak zabaleny do jednotlivých IKey
instancí. Tato kolekce IKey
instancí se vrátí volajícímu.
Další informace o konkrétních elementech XML najdete v dokumentu formátu úložiště klíčů.
IXmlRepository
Rozhraní IXmlRepository
představuje typ, který může zachovat XML do a načíst XML z záložního úložiště. Zpřístupňuje dvě rozhraní API:
GetAllElements
:IReadOnlyCollection<XElement>
StoreElement(XElement element, string friendlyName)
IXmlRepository
Implementace nemusí parsovat kód XML, který je předává. S dokumenty XML by měli zacházet jako s neprůhlenou a nechat vyšší vrstvy obavy, že dokumenty vygenerují a parsují.
Existují čtyři předdefinované typy betonů, které implementují IXmlRepository
:
Další informace najdete v dokumentu poskytovatelé úložiště klíčů.
Registrace vlastního IXmlRepository
úložiště je vhodná při použití jiného záložního úložiště (například Azure Table Storage).
Pokud chcete změnit výchozí aplikaci úložiště, zaregistrujte vlastní IXmlRepository
instanci:
services.Configure<KeyManagementOptions>(options => options.XmlRepository = new MyCustomXmlRepository());
services.AddSingleton<IXmlRepository>(new MyCustomXmlRepository());
IXmlEncryptor
Rozhraní IXmlEncryptor
představuje typ, který může šifrovat element XML ve formátu prostého textu. Zpřístupňuje jedno rozhraní API:
- Encrypt(XElement plaintextElement) : EncryptedXmlInfo
Pokud serializovaný IAuthenticatedEncryptorDescriptor
obsahuje všechny prvky označené jako "vyžaduje šifrování", pak XmlKeyManager
tyto prvky spustí prostřednictvím konfigurované IXmlEncryptor
metody 's Encrypt
, a zachová šifrovaný element místo elementu prostého textu do IXmlRepository
. Výstupem Encrypt
metody je EncryptedXmlInfo
objekt. Tento objekt je obálka, která obsahuje výslednou šifru XElement
i typ, který představuje IXmlDecryptor
, který lze použít k dešifru odpovídajícího prvku.
Existují čtyři předdefinované typy betonů, které implementují IXmlEncryptor
:
Další informace najdete v rest dokumentu v šifrování klíče.
Pokud chcete změnit výchozí šifrování klíčů narest úrovni aplikace, zaregistrujte vlastní IXmlEncryptor
instanci:
services.Configure<KeyManagementOptions>(options => options.XmlEncryptor = new MyCustomXmlEncryptor());
services.AddSingleton<IXmlEncryptor>(new MyCustomXmlEncryptor());
IXmlDecryptor
Rozhraní IXmlDecryptor
představuje typ, který ví, jak dešifrovat XElement
, který byl šifrován prostřednictvím IXmlEncryptor
. Zpřístupňuje jedno rozhraní API:
- Decrypt(XElement encryptedElement) : XElement
Metoda Decrypt
vrátí zpět šifrování provedené .IXmlEncryptor.Encrypt
Obecně platí, že každá konkrétní IXmlEncryptor
implementace bude mít odpovídající konkrétní IXmlDecryptor
implementaci.
Typy, které implementují IXmlDecryptor
, by měly mít jeden z následujících dvou veřejných konstruktorů:
- .ctor(IServiceProvider)
- .ctor()
Poznámka:
Předání IServiceProvider
konstruktoru může mít hodnotu null.
IKeyEscrowSink
Rozhraní IKeyEscrowSink
představuje typ, který může provádět escrow citlivých informací. Vzpomeňte si, že serializované popisovače můžou obsahovat citlivé informace (například kryptografický materiál), a to je to, co vedlo k zavedení typu IXmlEncryptor na prvním místě. Dojde ale k nehodám a klíče se dají odstranit nebo poškodit.
Rozhraní escrow poskytuje nouzový únikový šraf, který umožňuje přístup k nezpracované serializované XML předtím, než je transformován všemi nakonfigurovanými IXmlEncryptor. Rozhraní zveřejňuje jedno rozhraní API:
- Store(Guid keyId, element XElement)
Je na implementaci IKeyEscrowSink
, aby zvládla poskytnutý prvek zabezpečeným způsobem konzistentním s obchodními zásadami. Jednou z možných implementací může být, aby jímka escrow zašifrovala element XML pomocí známého podnikového certifikátu X.509, kde je privátní klíč certifikátu escrowed; tento CertificateXmlEncryptor
typ vám může pomoct. Implementace IKeyEscrowSink
je také zodpovědná za zachování poskytnutého prvku odpovídajícím způsobem.
Ve výchozím nastavení není povolen žádný mechanismus escrow, ale správci serveru můžou tento mechanismus nakonfigurovat globálně. Dá se také nakonfigurovat programově prostřednictvím IDataProtectionBuilder.AddKeyEscrowSink
metody, jak je znázorněno v ukázce níže. Metoda AddKeyEscrowSink
přetěžuje zrcadlení IServiceCollection.AddSingleton
a IServiceCollection.AddInstance
přetížení, protože IKeyEscrowSink
instance mají být singletony. Pokud je zaregistrovaných více IKeyEscrowSink
instancí, bude každý z nich volána během generování klíčů, takže klíče je možné současně vysunout do několika mechanismů.
Z instance neexistuje žádné rozhraní API ke čtení materiálu IKeyEscrowSink
. To je konzistentní s teorii návrhu mechanismu escrow: je určeno, aby byl klíčový materiál přístupný důvěryhodné autoritě, a vzhledem k tomu, že aplikace není důvěryhodnou autoritou, neměla by mít přístup k vlastnímu escrowed materiálu.
Následující ukázkový kód ukazuje vytvoření a registraci klíče, kde IKeyEscrowSink
jsou klíče v escrowd, aby je mohli obnovit pouze členové "CONTOSODomain Admins".
Poznámka:
Abyste mohli tuto ukázku spustit, musíte být na počítači s Windows 8 nebo Windows Serverem 2012 připojeným k doméně a řadič domény musí být Windows Server 2012 nebo novější.
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>
*/