Správa klíčů v ASP.NET Core

Systém ochrany dat automaticky spravuje životnost hlavních klíčů používaných k ochraně a zrušení ochrany datových částí. Každý klíč může existovat v jedné ze čtyř fází:

  • Vytvořeno – klíč existuje v okruhu klíčů, ale ještě nebyl aktivován. Klíč by neměl být použit pro nové operace ochrany, dokud dostatek času neuplyne, že klíč měl šanci rozšířit na všechny počítače, které tento okruh klíčů využívají.

  • Aktivní – klíč existuje v okruhu klíčů a měl by se použít pro všechny nové operace ochrany.

  • Platnost vypršela – klíč má spuštěnou přirozenou životnost a už by se neměl používat pro nové operace ochrany.

  • Odvolán – klíč je ohrožen a nesmí se používat pro nové operace ochrany.

Všechny vytvořené, aktivní a prošlé klíče se můžou použít k odemknutí příchozích datových částí. Odvolávané klíče se ve výchozím nastavení nemusí používat k odemknutí datových částí, ale vývojář aplikace může toto chování v případě potřeby přepsat.

Upozorňující

Vývojář může být lákavý odstranit klíč z okruhu klíčů (např. odstraněním odpovídajícího souboru ze systému souborů). V tomto okamžiku jsou všechna data chráněná klíčem trvale nešifrovatelná a neexistuje žádné přepsání tísňového volání, jako je u odvolaných klíčů. Odstranění klíče je skutečně destruktivní chování, a proto systém ochrany dat nezpřístupňuje žádné prvotřídní rozhraní API pro provedení této operace.

Výchozí výběr klíče

Když systém ochrany dat přečte okruh klíčů z backingového úložiště, pokusí se vyhledat "výchozí" klíč z okruhu klíčů. Výchozí klíč se používá pro nové operace ochrany.

Obecně platí, že systém ochrany dat jako výchozí klíč zvolí klíč s posledním datem aktivace. (Existuje malý faktor, který umožňuje nerovnoměrnou distribuci hodin mezi servery.) Pokud platnost klíče vypršela nebo byla odvolána a pokud aplikace nezablokovala automatické generování klíčů, vygeneruje se nový klíč s okamžitou aktivací podle vypršení platnosti klíče a následujících zásad postupného používání.

Důvodem, proč systém ochrany dat vygeneruje nový klíč okamžitě a nevrátí se k jinému klíči, je to, že nové generování klíčů by mělo být považováno za implicitní vypršení platnosti všech klíčů, které byly aktivovány před novým klíčem. Obecně platí, že nové klíče můžou být nakonfigurované s různými algoritmy nebo mechanismy šifrování neaktivních uložených dat než staré klíče a systém by měl upřednostňovat aktuální konfiguraci před vrácením zpět.

Došlo k výjimce. Pokud vývojář aplikace zakázal automatické generování klíčů, musí systém ochrany dat zvolit něco jako výchozí klíč. V tomto záložním scénáři systém zvolí odvolaný klíč s nejnovějším datem aktivace s předvolbou pro klíče, které měly čas rozšířit na jiné počítače v clusteru. Náhradní systém může skončit tak, že jako výsledek zvolí výchozí klíč s vypršenou platností. Záložní systém nikdy jako výchozí klíč nevybere odvolaný klíč a pokud je okruh klíčů prázdný nebo byl odvolán každý klíč, systém při inicializaci vyvolá chybu.

Vypršení platnosti a postupné uvedení klíče

Při vytvoření klíče se automaticky udělí datum aktivace { now + 2 dny } a datum vypršení platnosti { now + 90 dnů }. 2denní prodleva před aktivací dává klíč času šíření prostřednictvím systému. To znamená, že umožňuje ostatním aplikacím směřujícím na záložní úložiště sledovat klíč v dalším období automatické aktualizace, čímž maximalizuje šance, že když se okruh klíčů aktivuje, rozšíří se do všech aplikací, které by ho mohly potřebovat použít.

Pokud výchozí klíč vyprší do 2 dnů a pokud okruh klíčů ještě nemá klíč, který bude aktivní po vypršení platnosti výchozího klíče, systém ochrany dat automaticky zachovají nový klíč v okruhu klíčů. Tento nový klíč má datum aktivace { datum vypršení platnosti výchozího klíče } a datum vypršení platnosti { now + 90 dnů }. To umožňuje systému pravidelně sčítat klíče bez přerušení provozu.

Může se stát, že se klíč vytvoří s okamžitou aktivací. Jedním z příkladů může být, že aplikace nespustí nějakou dobu a platnost všech klíčů v okruhu klíčů vyprší. Když k tomu dojde, klíč dostane datum aktivace { now } bez normálního 2denního zpoždění aktivace.

Výchozí životnost klíče je 90 dní, i když je to možné konfigurovat jako v následujícím příkladu.

services.AddDataProtection()
       // use 14-day lifetime instead of 90-day lifetime
       .SetDefaultKeyLifetime(TimeSpan.FromDays(14));

Správce může také změnit výchozí systém, i když explicitní volání SetDefaultKeyLifetime přepíše všechny zásady pro celý systém. Výchozí životnost klíče nesmí být kratší než 7 dnů.

Automatická aktualizace vyzvánění kláves

Když se systém ochrany dat inicializuje, načte okruh klíčů z podkladového úložiště a uloží ho do mezipaměti v paměti. Tato mezipaměť umožňuje operace Chránit a Odemknout, aby pokračovaly bez zásahu do záložního úložiště. Systém automaticky zkontroluje změny v záložním úložišti přibližně každých 24 hodin nebo když vyprší platnost aktuálního výchozího klíče, podle toho, co nastane dříve.

Upozorňující

Vývojáři by měli velmi zřídka (pokud vůbec někdy) používat přímo rozhraní API pro správu klíčů. Systém ochrany dat provede automatickou správu klíčů, jak je popsáno výše.

Systém ochrany dat zveřejňuje rozhraní IKeyManager , které lze použít ke kontrole a provádění změn v okruhu klíčů. Systém DI, který poskytl instanci IDataProtectionProvider , může také poskytnout instanci IKeyManager pro vaši spotřebu. Alternativně můžete načíst IKeyManager přímo z příkladu IServiceProvider níže.

Jakákoli operace, která změní okruh klíčů (vytvoření nového klíče explicitně nebo provádí odvolání), zneplatní mezipaměť v paměti. Další volání Protect nebo Unprotect způsobí, že systém ochrany dat znovu načte vyzvánění klíčů a znovu vytvoří mezipaměť.

Následující ukázka ukazuje použití IKeyManager rozhraní ke kontrole a manipulaci s okruhem klíčů, včetně odvolání existujících klíčů a ručního vygenerování nového klíče.

using System;
using System.IO;
using System.Threading;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
    public static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection()
            // point at a specific folder and use DPAPI to encrypt keys
            .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys"))
            .ProtectKeysWithDpapi();
        var services = serviceCollection.BuildServiceProvider();

        // perform a protect operation to force the system to put at least
        // one key in the key ring
        services.GetDataProtector("Sample.KeyManager.v1").Protect("payload");
        Console.WriteLine("Performed a protect operation.");
        Thread.Sleep(2000);

        // get a reference to the key manager
        var keyManager = services.GetService<IKeyManager>();

        // list all keys in the key ring
        var allKeys = keyManager.GetAllKeys();
        Console.WriteLine($"The key ring contains {allKeys.Count} key(s).");
        foreach (var key in allKeys)
        {
            Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}");
        }

        // revoke all keys in the key ring
        keyManager.RevokeAllKeys(DateTimeOffset.Now, reason: "Revocation reason here.");
        Console.WriteLine("Revoked all existing keys.");

        // add a new key to the key ring with immediate activation and a 1-month expiration
        keyManager.CreateNewKey(
            activationDate: DateTimeOffset.Now,
            expirationDate: DateTimeOffset.Now.AddMonths(1));
        Console.WriteLine("Added a new key.");

        // list all keys in the key ring
        allKeys = keyManager.GetAllKeys();
        Console.WriteLine($"The key ring contains {allKeys.Count} key(s).");
        foreach (var key in allKeys)
        {
            Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}");
        }
    }
}

/*
 * SAMPLE OUTPUT
 *
 * Performed a protect operation.
 * The key ring contains 1 key(s).
 * Key {1b948618-be1f-440b-b204-64ff5a152552}: Created = 2015-03-18 22:20:49Z, IsRevoked = False
 * Revoked all existing keys.
 * Added a new key.
 * The key ring contains 2 key(s).
 * Key {1b948618-be1f-440b-b204-64ff5a152552}: Created = 2015-03-18 22:20:49Z, IsRevoked = True
 * Key {2266fc40-e2fb-48c6-8ce2-5fde6b1493f7}: Created = 2015-03-18 22:20:51Z, IsRevoked = False
 */

Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků, než je angličtina, dejte nám vědět v této diskuzi na GitHubu.

Úložiště klíčů

Systém ochrany dat má heuristická metoda, kdy se pokusí automaticky odvodit příslušné umístění úložiště klíčů a mechanismus šifrování neaktivních uložených dat. Klíčový mechanismus trvalosti je také konfigurovatelný vývojářem aplikace. V následujících dokumentech jsou popsány vložené implementace těchto mechanismů: