Поделиться через


Заголовки контекста в ASP.NET Core

Фон и теория

В системе защиты данных ключ означает объект, который может предоставлять службы шифрования, прошедшие проверку подлинности. Каждый ключ определяется уникальным идентификатором (GUID), и он несет с ним алгоритмическую информацию и энтропический материал. Предполагается, что каждый ключ несет уникальную энтропию, но система не может применить это, и нам также нужно учитывать разработчиков, которые могут вручную изменить кольцо ключей, изменив алгоритмическую информацию существующего ключа в кольце ключей. Для достижения наших требований безопасности, учитывая эти случаи, система защиты данных имеет концепцию криптографической гибкости, которая позволяет безопасно использовать одно энтропическое значение в нескольких алгоритмах шифрования.

Большинство систем, поддерживающих криптографическую гибкость, делают это путем включения некоторых сведений об алгоритме в составе полезной нагрузки. OID алгоритма, как правило, хороший кандидат для этого. Однако одна из проблем, с которыми мы столкнулись, заключается в том, что существует несколько способов указать один и тот же алгоритм: "AES" (CNG) и управляемые AesManaged, AesCryptoServiceProvider, AesCng и RijndaelManaged (с определенными параметрами) — это все то же самое, и мы должны поддерживать сопоставление всех этих элементов с правильным OID. Если разработчик хотел предоставить пользовательский алгоритм (или даже другую реализацию AES!), им придется сообщить нам о своем OID. Этот дополнительный шаг регистрации делает конфигурацию системы особенно болезненной.

Отступая назад, мы решили, что мы приближались к проблеме из неправильного направления. OID сообщает вам, что такое алгоритм, но мы на самом деле не заботимся об этом. Если нам нужно безопасно использовать одно энтропическое значение в двух разных алгоритмах, нам не нужно знать, какие алгоритмы на самом деле являются. Что нас действительно интересует, так это как они ведут себя. Любой достойный алгоритм симметричного блочного шифра также является сильной псевдорандомной перестановкой (PRP): зафиксировав входные данные (ключ, режим сцепления, IV, открытый текст), шифротекст с подавляющей вероятностью будет отличаться от любого другого симметричного блочного шифра при тех же входных данных. Аналогичным образом любая достойная хэш-функция с ключом также является сильной псевдорандомной функцией (PRF), и при условии фиксированного входного набора его выходные данные в подавляющем большинстве будут отличаться от любой другой хэш-функции с ключом.

Мы используем эту концепцию надежных PRP и PRF для создания заголовка контекста. Заголовок контекста выступает в качестве стабильного отпечатка для алгоритмов, применяемых для любой данной операции, и обеспечивает криптографическую гибкость, необходимую системе защиты данных. Этот заголовок воспроизводим и используется позже в процессе выведения побочного ключа. Существует два разных способа построения заголовка контекста в зависимости от режимов работы базовых алгоритмов.

Шифрование в режиме CBC + проверка подлинности HMAC

Заголовок контекста состоит из следующих компонентов:

  • [16 бит] Значение 00 00, которое является маркером, что означает "шифрование CBC + проверка подлинности HMAC".

  • [32 бита] Длина ключа (в байтах, биг-эндиан) симметричного блочного шифра.

  • [32 бита] Размер блока (в байтах, биг-эндиан) алгоритма симметричного блочного шифрования.

  • [32 бита] Длина ключа (в байтах, биг-энди) алгоритма HMAC. (В настоящее время размер ключа всегда соответствует размеру дайджеста.)

  • [32 бита] Размер дайджеста (в байтах, биг-эндиан) алгоритма HMAC.

  • EncCBC(K_E, IV, ""), который является выходным результатом алгоритма шифра симметричного блока с использованием пустого строкового ввода и где IV является все равнонулевым вектором. Построение K_E описано ниже.

  • MAC(K_H, "")— выходные данные алгоритма HMAC с пустыми строковыми входами. Построение K_H описано ниже.

В идеале мы могли бы передать все нулевые векторы для K_E и K_H. Однако мы хотим избежать ситуации, когда базовый алгоритм проверяет наличие слабых ключей перед выполнением каких-либо операций (в частности DES и 3DES), что исключает использование простого или повторяемого шаблона, например вектора all-zero.

Вместо этого мы используем NIST SP800-108 KDF в режиме счетчика (см. NIST SP800-108, Sec. 5.1) с ключом нулевой длины, меткой и контекстом и HMACSHA512 в качестве базового PRF. Мы получаем | K_E | + | K_H | байтов выходных данных, а затем разлагаем результат в K_E и K_H. Математически это представлено следующим образом.

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

Пример: AES-192-CBC + HMACSHA256

В качестве примера рассмотрим случай, когда алгоритм шифра симметричного блока — AES-192-CBC, а алгоритм проверки — HMACSHA256. Система создаст заголовок контекста, выполнив следующие действия.

Во-первых, пусть ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), где | K_E | = 192 bits и | K_H | = 256 bits в соответствии с указанными алгоритмами. Это приводит к K_E = 5BB6..21DD и K_H = A04A..00A9 в примере ниже:

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

Затем вычислить Enc_CBC (K_E, IV, "") для AES-192-CBC с заданными IV = 0* и K_E, как указано выше.

result := F474B1872B3B53E4721DE19C0841DB6F

Затем вычислить MAC(K_H, "") для HMACSHA256, используя K_H, как указано выше.

result := D4791184B996092EE1202F36E8608FA8FBD98ABDFF5402F264B1D7211536220C

При этом создается полный заголовок контекста ниже:

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

Этот заголовок контекста представляет собой отпечаток пары алгоритма шифрования с проверкой подлинности (шифрование AES-192-CBC + проверка HMACSHA256). Ниже приведены компоненты, как описано выше .

  • маркер (00 00)

  • Длина ключа блочного шифра (00 00 00 18)

  • Размер блока шифра (00 00 00 10)

  • Длина ключа HMAC (00 00 00 20)

  • Размер дайджеста HMAC (00 00 00 20)

  • Выходные данные блочного шифра PRP (F4 74 - DB 6F) и

  • Выходные данные PRF HMAC (D4 79 - end).

Замечание

Заголовок контекста шифрования в режиме CBC и проверки подлинности HMAC создается одинаково, независимо от того, предоставляются ли реализации алгоритмов как через Windows CNG, так и через управляемые типы SymmetricAlgorithm и KeyedHashAlgorithm. Это позволяет приложениям, работающим в разных операционных системах, надежно создавать один и тот же заголовок контекста, несмотря на то, что реализации алгоритмов отличаются в разных ОС. (На практике, алгоритм с ключом не обязательно должен быть HMAC. Это может быть любой тип алгоритма хэширования с ключом.)

Пример: 3DES-192-CBC + HMACSHA1

Во-первых, пусть ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), где | K_E | = 192 bits и | K_H | = 160 bits в соответствии с указанными алгоритмами. Это приводит к K_E = A219..E2BB и K_H = DC4A..B464 в примере ниже:

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

Затем вычислите Enc_CBC (K_E, IV, "") для 3DES-192-CBC, используя IV = 0* и K_E, как указано выше.

result := ABB100F81E53E10E

Затем вычислите MAC(K_H, "") для HMACSHA1, используя K_H как указано выше.

result := 76EB189B35CF03461DDF877CD9F4B1B4D63A7555

Это создает полный заголовок контекста, который является отпечатком пары алгоритмов шифрования с проверкой подлинности (шифрование 3DES-192-CBC + проверка HMACSHA1), показанной ниже:

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

Компоненты разбиваются следующим образом:

  • маркер (00 00)

  • Длина ключа блочного шифра (00 00 00 18)

  • Размер блока блочного шифра (00 00 00 08)

  • Длина ключа HMAC (00 00 00 14)

  • Размер дайджеста HMAC (00 00 00 14)

  • Выходные данные блочного шифра PRP и

  • Выходные данные HMAC PRF(76 EB - end).

Шифрование и проверка подлинности в режиме Галуа/счетчика

Заголовок контекста состоит из следующих компонентов:

  • [16 бит] Значение 00 01, которое означает "шифровка GCM + аутентификация".

  • [32 бита] Длина ключа (в байтах, биг-эндиан) симметричного блочного шифра.

  • [32 бита] Размер nonce (в байтах, big-endian), используемый во время операций шифрования, прошедших проверку подлинности. (Для нашей системы размер nonce фиксирован на 96 бит.)

  • [32 бита] Размер блока (в байтах, биг-эндиан) алгоритма симметричного блочного шифрования. (Для GCM это фиксировано при размере блока 128 бит.)

  • [32 бита] Размер тега аутентификации (в байтах, big-endian), созданного функцией аутентифицированного шифрования. (Для нашей системы размер тега фиксирован и равен 128 битам.)

  • [128 бит] Тег Enc_GCM (K_E, nonce, ""), который является выходом симметричного блочного шифра при пустой строке на входе и где nonce — это 96-битный вектор, состоящий из нулей.

K_E производится с использованием того же механизма, что и в сценарии шифрования CBC + аутентификации с помощью HMAC. Тем не менее, так как K_H здесь не задействован, у нас по сути есть | K_H | = 0, и алгоритм сводится к следующей форме.

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

Пример: AES-256-GCM

Сначала пусть K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), где | K_E | = 256 bits.

K_E := 22BC6F1B171C08C4AE2F27444AF8FC8B3087A90006CAEA91FDCFB47C1B8733B8

Затем вычислите тег проверки подлинности Enc_GCM (K_E, nonce, "") для AES-256-GCM, используя nonce = 096 и K_E, как указано выше.

result := E7DCCE66DF855A323A6BB7BD7A59BE45

При этом создается полный заголовок контекста ниже:

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

Компоненты разбиваются следующим образом:

  • маркер (00 01)

  • Длина ключа шифра блока (00 00 00 20)

  • размер nonce (00 00 00 0C)

  • Размер блока блочного шифра (00 00 00 10)

  • размер тега аутентификации (00 00 00 10) и

  • тег проверки подлинности, полученный во время работы блочного шифра (E7 DC - end).