Udostępnij za pośrednictwem


Nagłówki kontekstu w ASP.NET Core

Tło i teoria

W systemie ochrony danych "klucz" oznacza obiekt, który może zapewnić uwierzytelnione usługi szyfrowania. Każdy klucz jest identyfikowany przez unikatowy identyfikator (identyfikator GUID) i niesie ze sobą informacje algorytmiczne i materiał entropiczny. Jest to zamierzone, że każdy klucz nosi unikatową entropię, ale system nie może tego wymusić, a także musimy uwzględnić deweloperów, którzy mogą ręcznie zmienić pierścień kluczy, modyfikując informacje algorytmiczne istniejącego klucza w pierścieniu kluczy. Aby osiągnąć nasze wymagania dotyczące zabezpieczeń, biorąc pod uwagę te przypadki, system ochrony danych ma koncepcję elastyczności kryptograficznej, która umożliwia bezpieczne korzystanie z jednej wartości entropowej w wielu algorytmach kryptograficznych.

Większość systemów, które obsługują zwinność kryptograficzną, w tym niektóre identyfikujące informacje o algorytmie wewnątrz ładunku. OID algorytmu jest zazwyczaj dobrym kandydatem do tego. Jednak jednym z problemów, które napotkaliśmy, jest to, że istnieje wiele sposobów określania tego samego algorytmu: "AES" (CNG) i zarządzane Aes, AesManaged, AesCryptoServiceProvider, AesCng i RijndaelManaged (podane określone parametry) klasy są w rzeczywistości takie same, i musimy zachować mapowanie wszystkich tych elementów na poprawny identyfikator OID. Jeśli deweloper chce udostępnić niestandardowy algorytm (a nawet inną implementację AES!), musi powiedzieć nam jego identyfikator OID. Ten dodatkowy krok rejestracji sprawia, że konfiguracja systemu jest szczególnie bolesna.

Cofając się, zdecydowaliśmy, że zbliżamy się do problemu z niewłaściwego kierunku. Identyfikator OID informuje o tym, czym jest algorytm, ale tak naprawdę nie zależy nam na tym. Jeśli musimy bezpiecznie użyć jednej wartości entropowej w dwóch różnych algorytmach, nie trzeba wiedzieć, jakie są algorytmy. To, co naprawdę zależy nam na tym, jak zachowują się. Każdy przyzwoity algorytm szyfrowania bloków symetrycznych jest również silną permutacją pseudorandom (PRP): napraw dane wejściowe (klucz, tryb łańcucha, IV, zwykły tekst) i dane wyjściowe szyfrowania będą z dużym prawdopodobieństwem różnią się od innych algorytmów szyfrowania bloków symetrycznych, biorąc pod uwagę te same dane wejściowe. Podobnie każda przyzwoita funkcja skrótu klucza jest również silną funkcją pseudorandom (PRF), a biorąc pod uwagę stały zestaw danych wejściowych, jego dane wyjściowe będą w przeważającej mierze odrębne od każdej innej funkcji skrótu klucza.

Używamy tej koncepcji silnych żądań ściągnięcia i żądań ściągnięcia w celu utworzenia nagłówka kontekstu. Ten nagłówek kontekstu zasadniczo działa jako stabilny odcisk palca nad algorytmami używanymi dla danej operacji i zapewnia elastyczność kryptograficzną wymaganą przez system ochrony danych. Ten nagłówek jest powtarzalny i jest używany później w ramach procesu wyprowadzania podklucza. Istnieją dwa różne sposoby tworzenia nagłówka kontekstu w zależności od trybów działania algorytmów bazowych.

Szyfrowanie w trybie CBC i uwierzytelnianie HMAC

Nagłówek kontekstu składa się z następujących składników:

  • [16 bitów] Wartość 00 00, czyli znacznik oznaczający "szyfrowanie CBC + uwierzytelnianie HMAC".

  • [32 bity] Długość klucza (w bajtach big-endian) algorytmu szyfrowania bloków symetrycznych.

  • [32 bity] Rozmiar bloku (w bajtach big-endian) algorytmu szyfrowania bloków symetrycznych.

  • [32 bity] Długość klucza (w bajtach big-endian) algorytmu HMAC. (Obecnie rozmiar klucza zawsze odpowiada rozmiarowi skrótu).

  • [32 bity] Rozmiar skrótu (w bajtach big-endian) algorytmu HMAC.

  • EncCBC(K_E, IV, ""), który jest wyjściem algorytmu szyfrowania bloków symetrycznych, biorąc pod uwagę puste dane wejściowe ciągu i gdzie IV jest wektorem all-zero. Konstrukcja programu została opisana K_E poniżej.

  • MAC(K_H, ""), który jest wyjściem algorytmu HMAC, biorąc pod uwagę puste dane wejściowe ciągu. Konstrukcja programu została opisana K_H poniżej.

W idealnym przypadku możemy przekazać wektory all-zero dla i K_E K_H. Chcemy jednak uniknąć sytuacji, w której podstawowy algorytm sprawdza istnienie słabych kluczy przed wykonaniem jakichkolwiek operacji (w szczególności DES i 3DES), co uniemożliwia użycie prostego lub powtarzalnego wzorca, takiego jak wektor all-zero.

Zamiast tego używamy NIST SP800-108 KDF w trybie licznika (zobacz NIST SP800-108, Sec. 5.1) z kluczem o zerowej długości, etykiecie i kontekście i HMACSHA512 jako podstawowy prF. Uzyskujemy | K_E | + | K_H | bajty danych wyjściowych, a następnie rozkładamy wynik na K_E i K_H same. Matematycznie jest to reprezentowane w następujący sposób.

( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")

Przykład: AES-192-CBC + HMACSHA256

Rozważmy na przykład przypadek, w którym algorytm szyfrowania bloków symetrycznych to AES-192-CBC, a algorytm sprawdzania poprawności jest HMACSHA256. System wygeneruje nagłówek kontekstu, wykonując następujące kroki.

Najpierw pozwól ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), gdzie | K_E | = 192 bits i | K_H | = 256 bits zgodnie z określonymi algorytmami. Prowadzi to do K_E = 5BB6..21DD i K_H = A04A..00A9 w poniższym przykładzie:

5B B6 C9 83 13 78 22 1D 8E 10 73 CA CF 65 8E B0
61 62 42 71 CB 83 21 DD A0 4A 05 00 5B AB C0 A2
49 6F A5 61 E3 E2 49 87 AA 63 55 CD 74 0A DA C4
B7 92 3D BF 59 90 00 A9

Następnie oblicz obliczenia Enc_CBC (K_E, IV, "") dla AES-192-CBC podane IV = 0* i K_E jak powyżej.

result := F474B1872B3B53E4721DE19C0841DB6F

Następnie oblicz MAC(K_H, "") HMACSHA256 podane K_H powyżej.

result := D4791184B996092EE1202F36E8608FA8FBD98ABDFF5402F264B1D7211536220C

Spowoduje to utworzenie poniższego pełnego nagłówka kontekstu:

00 00 00 00 00 18 00 00 00 10 00 00 00 20 00 00
00 20 F4 74 B1 87 2B 3B 53 E4 72 1D E1 9C 08 41
DB 6F D4 79 11 84 B9 96 09 2E E1 20 2F 36 E8 60
8F A8 FB D9 8A BD FF 54 02 F2 64 B1 D7 21 15 36
22 0C

Ten nagłówek kontekstu to odcisk palca pary uwierzytelnionego algorytmu szyfrowania (szyfrowanie AES-192-CBC + weryfikacja HMACSHA256). Składniki, jak opisano powyżej , to:

  • znacznik (00 00)

  • długość klucza szyfrowania bloku (00 00 00 18)

  • rozmiar bloku szyfrowania (00 00 00 10)

  • długość klucza HMAC (00 00 00 20)

  • rozmiar skrótu HMAC (00 00 00 20)

  • dane wyjściowe (F4 74 - DB 6F) szyfrowania szyfrowania blokowego i

  • dane wyjściowe (D4 79 - end)HMAC PRF .

Uwaga

Szyfrowanie w trybie CBC i nagłówek kontekstu uwierzytelniania HMAC jest zbudowany w taki sam sposób, niezależnie od tego, czy implementacje algorytmów są dostarczane przez CNG systemu Windows, czy przez zarządzane typy SymmetricAlgorithm i KeyedHashAlgorithm. Dzięki temu aplikacje działające w różnych systemach operacyjnych mogą niezawodnie tworzyć ten sam nagłówek kontekstu, mimo że implementacje algorytmów różnią się między systemami operacyjnymi. (W praktyce keyedHashAlgorithm nie musi być odpowiednim HMAC. Może to być dowolny typ algorytmu skrótu klucza.

Przykład: 3DES-192-CBC + HMACSHA1

Najpierw pozwól ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), gdzie | K_E | = 192 bits i | K_H | = 160 bits zgodnie z określonymi algorytmami. Prowadzi to do K_E = A219..E2BB i K_H = DC4A..B464 w poniższym przykładzie:

A2 19 60 2F 83 A9 13 EA B0 61 3A 39 B8 A6 7E 22
61 D9 F8 6C 10 51 E2 BB DC 4A 00 D7 03 A2 48 3E
D1 F7 5A 34 EB 28 3E D7 D4 67 B4 64

Następnie oblicz obliczenia Enc_CBC (K_E, IV, "") dla 3DES-192-CBC podane IV = 0* i K_E jak powyżej.

result := ABB100F81E53E10E

Następnie oblicz MAC(K_H, "") HMACSHA1 podane K_H powyżej.

result := 76EB189B35CF03461DDF877CD9F4B1B4D63A7555

Spowoduje to utworzenie pełnego nagłówka kontekstu, który jest odciskiem palca pary algorytmów szyfrowania uwierzytelnionego (szyfrowanie 3DES-192-CBC + HMACSHA1 walidacja), pokazano poniżej:

00 00 00 00 00 18 00 00 00 08 00 00 00 14 00 00
00 14 AB B1 00 F8 1E 53 E1 0E 76 EB 18 9B 35 CF
03 46 1D DF 87 7C D9 F4 B1 B4 D6 3A 75 55

Składniki są rozdzielane w następujący sposób:

  • znacznik (00 00)

  • długość klucza szyfrowania bloku (00 00 00 18)

  • rozmiar bloku szyfrowania (00 00 00 08)

  • długość klucza HMAC (00 00 00 14)

  • rozmiar skrótu HMAC (00 00 00 14)

  • dane wyjściowe (AB B1 - E1 0E) szyfrowania szyfrowania blokowego i

  • dane wyjściowe (76 EB - end)HMAC PRF .

Szyfrowanie w trybie galois/licznika i uwierzytelnianie

Nagłówek kontekstu składa się z następujących składników:

  • [16 bitów] Wartość 00 01, czyli znacznik oznaczający "szyfrowanie I uwierzytelnianie GCM".

  • [32 bity] Długość klucza (w bajtach big-endian) algorytmu szyfrowania bloków symetrycznych.

  • [32 bity] Rozmiar inny niż (w bajtach big-endian) używany podczas operacji szyfrowania uwierzytelnionego. (W naszym systemie jest to stałe w rozmiarze innej niż 96 bitów).

  • [32 bity] Rozmiar bloku (w bajtach big-endian) algorytmu szyfrowania bloków symetrycznych. (W przypadku usługi GCM jest to stałe w rozmiarze bloku = 128 bitów).

  • [32 bity] Rozmiar tagu uwierzytelniania (w bajtach big-endian) generowany przez uwierzytelnioną funkcję szyfrowania. (W naszym systemie jest to stałe przy rozmiarze tagu = 128 bitów).

  • [128 bitów] Tag Enc_GCM (K_E, nonce, ""), który jest wynikiem symetrycznego algorytmu szyfrowania bloków, biorąc pod uwagę puste dane wejściowe ciągu i gdzie nonce jest 96-bitowym wektorem all-zero.

K_E jest uzyskiwany przy użyciu tego samego mechanizmu co w scenariuszu szyfrowania CBC i uwierzytelniania HMAC. Jednak ponieważ w tym miejscu nie K_H ma grać, zasadniczo mamy | K_H | = 0wartość , a algorytm zwija się do poniższego formularza.

K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")

Przykład: AES-256-GCM

Najpierw zajmijmy K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")element , gdzie | K_E | = 256 bits.

K_E := 22BC6F1B171C08C4AE2F27444AF8FC8B3087A90006CAEA91FDCFB47C1B8733B8

Następnie należy obliczyć tag Enc_GCM (K_E, nonce, "") uwierzytelniania dla AES-256-GCM podane nonce = 096 i K_E jak powyżej.

result := E7DCCE66DF855A323A6BB7BD7A59BE45

Spowoduje to utworzenie poniższego pełnego nagłówka kontekstu:

00 01 00 00 00 20 00 00 00 0C 00 00 00 10 00 00
00 10 E7 DC CE 66 DF 85 5A 32 3A 6B B7 BD 7A 59
BE 45

Składniki są rozdzielane w następujący sposób:

  • znacznik (00 01)

  • długość klucza szyfrowania bloku (00 00 00 20)

  • rozmiar niezwiązany (00 00 00 0C)

  • rozmiar bloku szyfrowania (00 00 00 10)

  • rozmiar (00 00 00 10) tagu uwierzytelniania i

  • tag uwierzytelniania z uruchamiania szyfru (E7 DC - end)blokowego .