Teilen über


Subschlüsselableitung und authentifizierte Verschlüsselung in ASP.NET Core

Die meisten Schlüssel im Schlüsselring enthalten eine Form von Entropie und enthalten algorithmische Informationen, die "CBC-Modus-Verschlüsselung + HMAC-Validierung" oder "GCM-Verschlüsselung + Validierung" angeben. In diesen Fällen beziehen wir uns auf die eingebettete Entropie als Hauptschlüsselmaterial (oder KM) für diesen Schlüssel, und wir führen eine Schlüsselableitungsfunktion aus, um die Schlüssel abzuleiten, die für die tatsächlichen kryptografischen Vorgänge verwendet werden.

Hinweis

Schlüssel sind abstrakt, und eine benutzerdefinierte Implementierung verhält sich möglicherweise nicht wie unten. Wenn der Schlüssel eine eigene Implementierung von IAuthenticatedEncryptor bereitstellt, anstatt eine unserer integrierten Fabriken zu verwenden, gilt der in diesem Abschnitt beschriebene Mechanismus nicht mehr.

Zusätzliche authentifizierte Daten und Unterschlüsselableitung

Die IAuthenticatedEncryptor Schnittstelle dient als Kernschnittstelle für alle authentifizierten Verschlüsselungsvorgänge. Die Encrypt Methode verwendet zwei Puffer: Klartext und zusätzliche authentifizierte Daten (AAD). Der Klartextinhalt fließt unverändert an den Aufruf IDataProtector.Protect, aber der AAD wird vom System generiert und besteht aus drei Komponenten.

  1. Der 32-Bit-Zauberkopf 09 F0 C9 F0, der diese Version des Datenschutzsystems identifiziert.

  2. Die 128-Bit-Schlüssel-ID.

  3. Eine aus der Zweckkette gebildete Zeichenfolge mit variabler Länge, die diesen IDataProtector Vorgang erstellt hat.

Da die AAD für das Tupel aller drei Komponenten einzigartig ist, können wir sie verwenden, um neue Schlüssel von KM abzuleiten, anstatt KM selbst in allen kryptografischen Vorgängen zu verwenden. Für jeden Aufruf IAuthenticatedEncryptor.Encryptfindet der folgende Schlüsselableitungsprozess statt:

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

Hier rufen wir die NIST SP800-108 KDF im Zählermodus auf (siehe NIST SP800-108, Abschnitt 5.1) mit den folgenden Parametern:

  • Schlüsselableitungsschlüssel (KDK) = K_M

  • PRF = HMACSHA512

  • label = zusätzlicheAuthentifizierteDaten

  • context = contextHeader || keyModifier

Der Kontextheader ist von variabler Länge und dient im Wesentlichen als Fingerabdruck der Algorithmen, die wir von K_E und K_H ableiten. Der Schlüsselmodifizierer ist eine 128-Bit-Zeichenfolge, die zufällig für jeden Aufruf Encrypt generiert wird, und dient dazu, sicherzustellen, dass KE und KH für diesen spezifischen Authentifizierungsverschlüsselungsvorgang eindeutig sind, auch wenn alle anderen Eingaben für die KDF konstant sind.

Bei CBC-Modus-Verschlüsselungs- und HMAC-Validierungsvorgängen | K_E | ist die Länge des symmetrischen Blockchiffreschlüssels und | K_H | die Digestgröße der HMAC-Routine. Für GCM-Verschlüsselungs- und Validierungsvorgänge. | K_H | = 0

CBC-Modus-Verschlüsselung + HMAC-Überprüfung

Sobald K_E über den obigen Mechanismus generiert wird, generieren wir einen zufälligen Initialisierungsvektor und führen den symmetrischen Blockchiffrealgorithmus aus, um den Klartext zu entschlüsseln. Der Initialisierungsvektor und der Verschlüsselungstext werden dann durch die HMAC-Routine ausgeführt, die mit dem Schlüssel K_H initialisiert wird, um den MAC zu erzeugen. Dieser Prozess und der Rückgabewert werden unten grafisch dargestellt.

CBC-Modus-Prozess und -Rückgabe

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

Hinweis

Die IDataProtector.Protect Implementierung wird das magische Header und die Schlüssel-ID der Ausgabe voranstellen, bevor sie an den Aufrufer zurückgegeben wird. Da die magische Header- und Schlüssel-ID implizit Teil von AAD sind und der Schlüsselmodifizierer als Eingabe für die KDF gefüttert wird, bedeutet dies, dass jedes einzelne Byte der endgültig zurückgegebenen Nutzlast vom MAC authentifiziert wird.

Verschlüsselung und Validierung im Galois/Counter Mode

Sobald K_E über den obigen Mechanismus generiert wird, generieren wir eine zufällige 96-Bit-Nonce und führen den symmetrischen Blockchiffrealgorithmus aus, um den Klartext zu entschlüsseln und das 128-Bit-Authentifizierungstag zu erzeugen.

GCM-Modusprozess und Rückgabe

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

Hinweis

Obwohl GCM das Konzept von AAD nativ unterstützt, übermitteln wir AAD weiterhin nur an die ursprüngliche KDF und geben für den AAD-Parameter bei GCM stattdessen eine leere Zeichenfolge ein. Der Grund dafür ist zweifach. Erstens, um Flexibilität zu unterstützen , wollen wir nie direkt als Verschlüsselungsschlüssel verwenden K_M . Darüber hinaus erzwingt GCM sehr strenge Eindeutigkeitsanforderungen für seine Eingaben. Die Wahrscheinlichkeit, dass die GCM-Verschlüsselungsroutine jemals für zwei oder mehr unterschiedliche Eingabedatengruppen mit demselben (Schlüssel, Nonce)-Paar aufgerufen wird, darf 2^-32 nicht überschreiten. Wenn wir K_E festsetzen, können wir höchstens 2^32 Verschlüsselungsvorgänge ausführen, bevor wir gegen den Grenzwert von 2^-32 verstoßen. Dies mag wie eine sehr große Anzahl von Vorgängen aussehen, aber ein Webserver mit hohem Datenverkehr kann in nur wenigen Tagen etwa 4 Milliarden Anfragen bearbeiten, und zwar gut innerhalb der normalen Lebensdauer für diese Schlüssel. Um den 2^-32-Wahrscheinlichkeitsgrenzwert einzuhalten, verwenden wir weiterhin einen 128-Bit-Tastenmodifizierer und 96-Bit-Nonce, der die nutzbare Vorgangsanzahl für jeden gegebenen K_MVorgang radikal erweitert. Zur Vereinfachung des Entwurfs teilen wir den KDF-Codepfad zwischen CBC- und GCM-Vorgängen, und da AAD bereits in der KDF berücksichtigt wird, ist es nicht erforderlich, ihn an die GCM-Routine weiterzuleiten.