Subkey-härledning och autentiserad kryptering i ASP.NET Core

De flesta nycklar i nyckelringen innehåller någon form av entropi och har algoritmisk information som anger "CBC-lägeskryptering + HMAC-validering" eller "GCM-kryptering + validering". I dessa fall refererar vi till den inbäddade entropi som huvudnyckelmaterial (eller KM) för den här nyckeln, och vi utför en nyckelhärledningsfunktion för att härleda de nycklar som ska användas för de faktiska kryptografiska åtgärderna.

Anmärkning

Nycklarna är abstrakta och en anpassad implementering kanske inte fungerar som nedan. Om nyckeln tillhandahåller en egen implementering av IAuthenticatedEncryptor i stället för att använda någon av våra inbyggda fabriker gäller inte längre den mekanism som beskrivs i det här avsnittet.

Ytterligare autentiserade data och undernyckelhärledning

Gränssnittet IAuthenticatedEncryptor fungerar som kärngränssnitt för alla autentiserade krypteringsåtgärder. Dess Encrypt metod tar två buffertar: klartext och additionalAuthenticatedData (AAD). Innehållet i klartext flödar oförändrat genom anropet till IDataProtector.Protect, men AAD genereras av systemet och består av tre komponenter.

  1. Den 32-bitars magiska rubriken 09 F0 C9 F0 som identifierar den här versionen av dataskyddssystemet.

  2. 128-bitars nyckel-ID.

  3. En sträng med variabel längd som bildats från syfteskedjan som skapade åtgärden IDataProtector som utför den här åtgärden.

Eftersom AAD är unikt för tuppeln för alla tre komponenterna kan vi använda den för att härleda nya nycklar från KM i stället för att använda SJÄLVA KM i alla våra kryptografiska åtgärder. För varje anrop till IAuthenticatedEncryptor.Encryptsker följande nyckelhärledningsprocess:

( K_E, K_H ) = SP800_108_CTR_HMACSHA512(K_M, AAD, contextHeader || keyModifier)

Här anropar vi NIST SP800-108 KDF i räknarläge (se NIST SP800-108, s. 5.1) med följande parametrar:

  • Nyckelhärledningsnyckel (KDK) = K_M

  • PRF = HMACSHA512

  • label = ytterligareVerifieradeData

  • context = contextHeader || keyModifier

Kontextrubriken är av variabel längd och fungerar i princip som ett tumavtryck för de algoritmer som vi härleder K_E och K_H. Nyckelmodifieraren är en 128-bitars sträng som genereras slumpmässigt för varje anrop till Encrypt och säkerställer med överväldigande sannolikhet att KE och KH är unika för den här specifika autentiseringskrypteringsåtgärden, även om alla andra indata till KDF är konstanta.

För CBC-lägeskryptering + HMAC-valideringsåtgärder | K_E | är längden på den symmetriska blockkrypteringsnyckeln och | K_H | är den sammanfattade storleken på HMAC-rutinen. För GCM-kryptering + valideringsåtgärder, | K_H | = 0.

CBC-lägeskryptering + HMAC-validering

När K_E har genererats via mekanismen ovan genererar vi en slumpmässig initieringsvektor och kör den symmetriska blockkrypteringsalgoritmen för att tolka klartexten. Initieringsvektorn och chiffertexten körs sedan genom HMAC-rutinen som initieras med nyckeln K_H för att producera MAC. Den här processen och returvärdet representeras grafiskt nedan.

CBC-lägesprocess och retur

output:= keyModifier || iv || E_cbc (K_E,iv,data) || HMAC(K_H, iv || E_cbc (K_E,iv,data))

Anmärkning

Implementeringen IDataProtector.Protectlägger till den magiska headern och nyckel-ID:t till utdata innan det returneras till anroparen. Eftersom den magiska rubriken och nyckel-ID är implicit en del av AAD, och eftersom nyckelmodifieraren matas som indata till KDF, innebär det att varje byte av den slutliga returnerade nyttolasten autentiseras av MAC.

Kryptering i Galois/räknareläge + validering

När K_E har genererats via mekanismen ovan genererar vi en slumpmässig 96-bitars nonce och kör den symmetriska blockkrypteringsalgoritmen för att tolka klartexten och skapa taggen 128-bitars autentisering.

GCM-processläge och retur

output := keyModifier || nonce || E_gcm (K_E,nonce,data) || authTag

Anmärkning

Även om GCM internt stöder begreppet AAD matar vi fortfarande AAD endast till den ursprungliga KDF:n och väljer att skicka en tom sträng till GCM för dess AAD-parameter. Anledningen till detta är tvådelad. För att stödja flexibilitet vill vi aldrig använda K_M direkt som krypteringsnyckel. Dessutom ställer GCM mycket strikta unika krav på sina indata. Sannolikheten att GCM-krypteringsrutinen någonsin anropas på två eller flera distinkta uppsättningar med indata med samma (nyckel, nonce) par får inte överstiga 2^-32. Om vi åtgärdar K_E kan vi inte utföra fler än 2^32 krypteringsoperationer innan vi bryter mot gränsen på 2^-32. Detta kan verka som ett mycket stort antal åtgärder, men en webbserver med hög trafik kan gå igenom 4 miljarder begäranden på bara några dagar, långt inom den normala livslängden för dessa nycklar. För att hålla oss kompatibla med sannolikhetsgränsen 2^-32 fortsätter vi att använda en 128-bitars nyckelmodifierare och 96-bitars nonce, vilket radikalt utökar antalet användbara åtgärder för en viss K_M. För att förenkla designen delar vi KDF-kodvägen mellan CBC- och GCM-åtgärder, och eftersom AAD redan beaktas i KDF behöver vi inte vidarebefordra den till GCM-rutinen.