AES Key Wrap: A128KW, A192KW, A256KW

AES Key Wrap в контексте JOSE применяется как механизм защиты ключа содержимого (Content Encryption Key, CEK) при формировании JWE. Он решает задачу безопасной передачи симметричного ключа, который используется для шифрования данных, без необходимости использовать асимметричное шифрование или передавать ключ в открытом виде.

AES Key Wrap основан на алгоритмах, определённых в RFC 3394 и расширении RFC 5649. В спецификации JOSE он представлен тремя вариантами:

  • A128KW — AES Key Wrap с 128-битным ключом
  • A192KW — AES Key Wrap с 192-битным ключом
  • A256KW — AES Key Wrap с 256-битным ключом

Каждый из этих алгоритмов отличается только длиной ключа шифрования (KEK — Key Encryption Key), который используется для упаковки CEK.


В структуре JWE (JSON Web Encryption) всегда присутствуют два уровня ключей:

  • CEK (Content Encryption Key) — ключ, которым шифруются данные (например, через AES-GCM)
  • KEK (Key Encryption Key) — ключ, которым защищается CEK

AES Key Wrap выполняет функцию обёртки CEK:

  1. Генерируется случайный CEK
  2. Данные шифруются CEK
  3. CEK шифруется (wrap) с помощью KEK через A128KW / A192KW / A256KW
  4. Полученный wrapped key помещается в поле encrypted_key

Поддержка в библиотеке jose

Библиотека jose реализует AES Key Wrap как часть JWE алгоритмов шифрования ключей. При использовании high-level API разработчик обычно не вызывает алгоритм напрямую — он выбирается через поле alg в заголовке JWE.

Пример использования A128KW:

import { generateSecret, CompactEncrypt } from 'jose'

// ключ шифрования контента (CEK будет сгенерирован автоматически)
const plaintext = new TextEncoder().encode('секретные данные')

// симметричный ключ для wrapping (KEK)
const kek = await generateSecret('A128KW')

const jwe = await new CompactEncrypt(plaintext)
  .setProtectedHeader({
    alg: 'A128KW',
    enc: 'A256GCM'
  })
  .encrypt(kek)

console.log(jwe)

В этом примере:

  • alg: 'A128KW' определяет способ упаковки CEK
  • enc: 'A256GCM' определяет алгоритм шифрования данных
  • kek используется для защиты ключа CEK

Отличия A128KW, A192KW и A256KW

A128KW

Использует 128-битный ключ AES. Это наиболее распространённый вариант благодаря балансу между безопасностью и производительностью.

  • Меньший размер ключа
  • Быстрее вычисления
  • Подходит для большинства веб-сценариев

A192KW

Использует 192-битный ключ AES. Менее распространён, но повышает криптостойкость по сравнению с 128-битным вариантом.

  • Средний уровень производительности
  • Используется в системах с повышенными требованиями безопасности
  • Реже поддерживается аппаратным ускорением

A256KW

Использует 256-битный ключ AES. Максимальный уровень стойкости среди трёх вариантов.

  • Наибольшая криптографическая устойчивость
  • Более высокая вычислительная нагрузка
  • Рекомендуется для чувствительных данных и долгосрочного хранения

Механика AES Key Wrap

AES Key Wrap не является режимом шифрования данных в классическом смысле (как CBC или GCM). Он предназначен исключительно для защиты ключей.

Основные особенности:

  • Работает с блоками фиксированной структуры
  • Не требует IV в классическом понимании
  • Обеспечивает целостность обёрнутого ключа
  • Встроенная защита от модификации (integrity check)

Внутренне алгоритм выполняет несколько раундов AES-шифрования над блоками ключа CEK, перемешивая их с контрольными значениями.


Использование в JWE заголовках

При формировании JWE структура заголовка обычно выглядит так:

{
  "alg": "A256KW",
  "enc": "A256GCM"
}

Где:

  • alg — алгоритм защиты CEK (AES Key Wrap)
  • enc — алгоритм шифрования содержимого

В зависимости от выбранного alg библиотека jose автоматически применяет соответствующий Key Wrap.


Взаимодействие с ключами в jose

В библиотеке jose KEK может быть:

  • симметричным ключом (CryptoKey через Web Crypto API)
  • секретом, полученным через generateSecret
  • импортированным ключом через importKey

Пример импорта ключа:

import { importJWK, CompactEncrypt } from 'jose'

const jwk = {
  kty: 'oct',
  k: 'GawgguFyGrWKav7AX4VKUg',
  alg: 'A128KW'
}

const key = await importJWK(jwk, 'A128KW')

const jwe = await new CompactEncrypt(
  new TextEncoder().encode('данные')
)
  .setProtectedHeader({ alg: 'A128KW', enc: 'A128GCM' })
  .encrypt(key)

Совместимость и ограничения

AES Key Wrap алгоритмы в JOSE имеют строгие требования:

  • KEK должен соответствовать длине алгоритма
  • A128KW требует 128-битный ключ
  • A192KW требует 192-битный ключ
  • A256KW требует 256-битный ключ

Несоответствие длины ключа приводит к ошибке на этапе шифрования или импорта.


Практическое применение

AES Key Wrap используется в следующих сценариях:

  • защита ключей API в микросервисной архитектуре
  • безопасная передача токенов JWE между сервисами
  • хранение зашифрованных секретов в конфигурациях
  • обмен ключами в браузер-сервер взаимодействии

Особенно важен он в системах, где требуется:

  • симметричное шифрование данных (AES-GCM)
  • но безопасная передача ключа без RSA/ECDH

Поведение при ошибках реализации

В реализации jose типичны следующие проблемы:

  • использование ключа неподходящей длины
  • несоответствие alg и фактического типа ключа
  • попытка использовать raw bytes вместо CryptoKey
  • смешивание алгоритмов wrapping и content encryption

Библиотека строго валидирует параметры на этапе выполнения, поэтому ошибки проявляются сразу при создании JWE.