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


Извлечение и проверка подлинности шифрования подключа в ASP.NET Core

Большинство ключей в кольце ключей будут содержать некоторую форму энтропии и будут иметь алгоритмическую информацию о том, что "шифрование в режиме CBC + проверка HMAC" или "шифрование GCM + проверка". В этих случаях мы ссылаемся на внедренную энтропию как материал главного ключа (или KM) для этого ключа, и мы выполняем функцию производных ключей для получения ключей, которые будут использоваться для фактических криптографических операций.

Примечание.

Ключи абстрактны, а пользовательская реализация может не вести себя так, как показано ниже. Если ключ предоставляет собственную реализацию IAuthenticatedEncryptor , а не использовать одну из встроенных фабрик, механизм, описанный в этом разделе, больше не применяется.

Дополнительные данные, прошедшие проверку подлинности и производные подраздела

Интерфейс IAuthenticatedEncryptor служит основным интерфейсом для всех операций шифрования, прошедших проверку подлинности. Его Encrypt метод принимает два буфера: обычный текст и дополнительныйauthenticatedData (AAD). Поток содержимого с открытым текстом не изменил вызов IDataProtector.Protect, но AAD создается системой и состоит из трех компонентов:

  1. 32-разрядный волшебный заголовок 09 F0 C9 F0, определяющий эту версию системы защиты данных.

  2. Идентификатор 128-разрядного ключа.

  3. Строка переменной длины, сформированная из цепочки назначений, создающей IDataProtector эту операцию.

Так как AAD является уникальным для кортежа всех трех компонентов, мы можем использовать его для получения новых ключей от KM, а не использования KM в всех наших криптографических операциях. Для каждого вызова IAuthenticatedEncryptor.Encryptпроисходит следующий процесс получения ключа:

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

Здесь мы вызываем NIST SP800-108 KDF в режиме счетчика (см . NIST SP800-108, sec. 5.1) со следующими параметрами:

  • Ключ производных ключей (KDK) = K_M

  • PRF = HMACSHA512

  • label = additionalAuthenticatedData

  • context = contextHeader || keyModifier

Заголовок контекста имеет переменную длину и, по сути, служит отпечатком алгоритмов, для которых мы наследуем K_E и K_H. Модификатор ключа — это 128-разрядная строка, созданная случайным образом для каждого вызова Encrypt и служит для обеспечения подавляющей вероятности того, что KE и KH являются уникальными для этой конкретной операции шифрования проверки подлинности, даже если все остальные входные данные KDF являются константой.

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

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

После K_E создания с помощью приведенного выше механизма мы создадим вектор случайной инициализации и запустите алгоритм шифра симметричного блока для расшифровки открытого текста. Затем вектор инициализации и зашифрованный текст выполняются через подпрограмму HMAC, инициализируется ключом K_H для создания MAC. Этот процесс и возвращаемое значение представлены графически ниже.

CBC-mode process and return

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

Примечание.

Реализация IDataProtector.Protect будет предопределена волшебным заголовком и идентификатором ключа для выходных данных перед возвратом вызывающему объекту. Так как магический заголовок и идентификатор ключа неявно являются частью AAD, и поскольку модификатор ключей предоставляется в качестве входных данных в KDF, это означает, что каждый байт конечной возвращаемой полезных данных проходит проверку подлинности MAC.

Шифрование в режиме галуа и счетчика + проверка

После K_E создания с помощью приведенного выше механизма мы создадим случайный 96-разрядный нецелевой алгоритм и запустите алгоритм шифра симметричного блока, чтобы зашифровать открытый текст и создать 128-разрядный тег проверки подлинности.

GCM-mode process and return

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

Примечание.

Несмотря на то, что GCM изначально поддерживает концепцию AAD, мы по-прежнему кормим AAD только исходному KDF, выбирая передачу пустой строки в GCM для его параметра AAD. Причина этого заключается в двухкратном. Во-первых, для поддержки гибкости мы никогда не хотим использовать K_M непосредственно в качестве ключа шифрования. Кроме того, GCM накладывает очень строгие требования к уникальности для входных данных. Вероятность того, что подпрограмма шифрования GCM когда-либо вызывается на двух или более разных наборах входных данных с той же парой (ключ, nonce) не должно превышать 2^-32. Если мы исправим K_E , мы не можем выполнять более 2^32 операций шифрования, прежде чем выполнять сход с ограничением 2^-32. Это может показаться очень большим количеством операций, но веб-сервер с высоким трафиком может пройти через 4 миллиарда запросов в течение всего нескольких дней, хорошо в течение нормального времени существования этих ключей. Чтобы оставаться в соответствии с ограничением вероятности 2^-32, мы продолжаем использовать модификатор ключей 128-разрядного и 96-разрядного nonce, который радикально расширяет число операций, доступных для использования для любого заданного.K_M Для простоты проектирования мы разделяем путь кода KDF между операциями CBC и GCM, и так как AAD уже рассматривается в KDF, нет необходимости пересылать его в подпрограмму GCM.