Udostępnij przez


Wyprowadzanie podklucza i uwierzytelnione szyfrowanie w ASP.NET Core

Większość kluczy w pierścieniu kluczy będzie zawierać jakąś formę entropii i będzie zawierać informacje algorytmiczne z informacją "Szyfrowanie w trybie CBC + walidacja HMAC" lub "Szyfrowanie I walidacja GCM". W takich przypadkach odwołujemy się do osadzonej entropii jako głównego materiału kluczowego (lub KM) dla tego klucza i wykonujemy funkcję wyprowadzania kluczy, aby uzyskać klucze, które będą używane do rzeczywistych operacji kryptograficznych.

Uwaga / Notatka

Klucze są abstrakcyjne, a implementacja niestandardowa może nie zachowywać się tak jak poniżej. Jeśli klucz zapewnia własną implementację IAuthenticatedEncryptor zamiast korzystać z jednej z naszych wbudowanych fabryk, mechanizm opisany w tej części przestaje mieć zastosowanie.

Dodatkowe uwierzytelnione dane i wyprowadzenie podklucza

Interfejs IAuthenticatedEncryptor służy jako podstawowy interfejs dla wszystkich uwierzytelnionych operacji szyfrowania. Metoda Encrypt przyjmuje dwa bufory: zwykły tekst i dodatkowe dane uwierzytelnione (AAD). Zawartość zwykłego tekstu przepływa przez wywołanie do IDataProtector.Protect bez zmian, ale AAD jest generowane przez system i składa się z trzech elementów.

  1. 32-bitowy magiczny nagłówek 09 F0 C9 F0, który identyfikuje tę wersję systemu ochrony danych.

  2. Identyfikator klucza 128-bitowego.

  3. Ciąg o zmiennej długości utworzony na podstawie łańcucha celów, który utworzył IDataProtector, wykonującego tę operację.

Ponieważ AAD jest unikatowy dla krotki wszystkich trzech składników, możemy go użyć do wyprowadzania nowych kluczy z KM, zamiast używać samego KM we wszystkich naszych operacjach kryptograficznych. Dla każdego wywołania metody IAuthenticatedEncryptor.Encryptnastępuje następujący proces wyprowadzania klucza:

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

W tym miejscu uruchamiamy NIST SP800-108 KDF w trybie zliczającym (zobacz NIST SP800-108, s. 5.1) z następującymi parametrami:

  • Klucz wyprowadzania kluczy (KDK) = K_M

  • PRF = HMACSHA512

  • label = dodatkoweUwierzytelnioneDane

  • context = contextHeader || keyModifier

Nagłówek kontekstu ma zmienną długość i zasadniczo służy jako odcisk palca algorytmów, dla których wyprowadzamy K_E i K_H. Modyfikator klucza jest ciągiem 128-bitowym generowanym losowo dla każdego wywołania Encrypt i służy w celu zapewnienia z przytłaczającym prawdopodobieństwem, że KE i KH są unikatowe dla tej konkretnej operacji szyfrowania uwierzytelniania, nawet jeśli wszystkie inne dane wejściowe do KDF są stałe.

W operacjach szyfrowania w trybie CBC i weryfikacji HMAC, | K_E | oznacza długość klucza symetrycznego dla algorytmu blokowego, a | K_H | jest rozmiarem skrótu dla procedury HMAC. W przypadku operacji szyfrowania i walidacji GCM, | K_H | = 0.

Szyfrowanie w trybie CBC i walidacja HMAC

Po K_E wygenerowaniu za pomocą powyższego mechanizmu generujemy losowy wektor inicjowania i uruchamiamy algorytm szyfrowania bloków symetrycznych, aby zaszyfrować zwykły tekst. Wektor inicjowania i tekst szyfrowania są następnie uruchamiane przez procedurę HMAC zainicjowaną przy użyciu klucza K_H w celu utworzenia adresu MAC. Ten proces i zwracana wartość są reprezentowane graficznie poniżej.

Proces i powrót w trybie CBC

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

Uwaga / Notatka

Implementacja IDataProtector.Protectbędzie poprzedzać magiczny nagłówek i identyfikator klucza do danych wyjściowych przed zwróceniem ich do obiektu wywołującego. Ponieważ nagłówek magiczny i identyfikator klucza są niejawnie częścią AAD, a modyfikator klucza jest przekazywany jako dane wejściowe do KDF, oznacza to, że każdy bajt końcowego zwróconego ładunku jest uwierzytelniany przez MAC.

Szyfrowanie w trybie Galois/Counter + walidacja

Po wygenerowaniu K_E za pomocą powyższego mechanizmu, generujemy losowy nonce 96-bitowy i uruchamiamy symetryczny algorytm szyfrujący blokowy, aby zaszyfrować tekst jawny i utworzyć 128-bitowy tag uwierzytelniania.

Proces i powrót w trybie GCM

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

Uwaga / Notatka

Nawet jeśli GCM natywnie obsługuje mechanizm AAD, nadal przekazujemy AAD tylko do oryginalnego KDF, decydując się przekazać pusty ciąg znaków do GCM jako jego parametr AAD. Przyczyna tego jest dwojaka. Po pierwsze, aby zapewnić elastyczność , nigdy nie chcemy używać K_M bezpośrednio jako klucza szyfrowania. Ponadto usługa GCM nakłada na swoje dane wejściowe bardzo ścisłe wymagania dotyczące unikatowości. Prawdopodobieństwo, że procedura szyfrowania GCM jest kiedykolwiek wywoływana na co najmniej dwóch odrębnych zestawach danych wejściowych z tą samą parą (klucz, nonce), nie może przekraczać 2^-32. Jeśli naprawimy K_E, nie możemy wykonać więcej niż 2^32 operacji szyfrowania, zanim przekroczymy limit 2^-32. Może wydawać się to bardzo dużą liczbą operacji, ale serwer internetowy o dużym natężeniu ruchu może obsłużyć 4 miliardy żądań w ciągu zaledwie kilku dni, co jest znacznie w granicach normalnego czasu życia tych kluczy. Aby zachować zgodność z limitem prawdopodobieństwa 2^-32, nadal używamy modyfikatora 128-bitowego i 96-bitowego nonce, co znacznie zwiększa liczbę operacji możliwych do wykonania dla danego K_M. Dla uproszczenia projektu udostępniamy ścieżkę kodu KDF między operacjami CBC i GCM, a ponieważ AAD jest już uwzględniane w KDF, nie ma potrzeby przekazywania go do procedury GCM.