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

Основной сценарий использования transit — шифрование данных из приложений с последующим хранением этих зашифрованных данных в основном хранилище. Это снимает с разработчиков приложений ответственность за правильное шифрования/дешифрования и перекладывает его на Stronghold.

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

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

Управление рабочим набором

Механизм Transit поддерживает версионирование ключей. Версии ключей, более ранние, чем заданное значение min_decryption_version ключа, архивируются, а остальные версии ключей попадают в рабочий набор. Это важно как для производительности для быстрой загрузки ключей, а так и для безопасности: запрещая расшифровку старыми версиями ключей, найденный шифртекст, соответствующий устаревшим (но конфиденциальные) данным, не может быть расшифрован большинством пользователей, но в экстренных случаях min_decryption_version может быть сдвинут назад, чтобы позволить легитимную расшифровку.

В настоящее время архив хранится в одной записи хранилища. В некоторых бэкендах, особенно тех, что используют Raft или Paxos для обеспечения высокой доступности (HA), частая ротация ключей может привести к увеличению размера записи архива сверх допустимого предела. Для сценариев с частой ротацией хорошей альтернативой может быть использование именованных ключей, привязанных к временным интервалам (например, 5-минутные периоды, округлённые до ближайшего, кратного пяти). Это позволяет одновременно использовать несколько ключей и детерминированно выбирать нужный ключ в любой момент времени.

Рекомендации NIST по ротации ключей

Периодически ротируйте ключи шифрования, даже если не было компрометации: так ограничивается объём данных, зашифрованных одной версией ключа. Для ключей AES-GCM ротацию следует проводить до достижения примерно 232 операций шифрования на одну версию ключа, в соответствии с рекомендациями NIST 800-38D. Операторам следует оценить интенсивность использования ключа и установить частоту ротации, чтобы не превысить указанные лимиты. Например, если ключ используется примерно 40 миллионов раз в день, то ротация раз в три месяца будет достаточной.

Типы ключей

На данный момент механизм транзитных секретов поддерживает следующие типы ключей (все типы ключей также генерируют отдельные ключи HMAC):

  • aes128-gcm96: AES-GCM с 128-битным ключом AES и 96-битным nonce; поддерживает шифрование, дешифрование, производные ключи и конвергентное шифрование
  • aes256-gcm96: AES-GCM с 256-битным ключом AES и 96-битным nonce; поддерживает шифрование, дешифрование, производные ключи и конвергентное шифрование (по умолчанию)
  • chacha20-poly1305: ChaCha20-Poly1305 с 256-битным ключом; поддерживает шифрование, дешифрование, производные ключи и конвергентное шифрование
  • ed25519: Ed25519; поддерживает подпись, проверку подписи и производные ключи
  • ecdsa-p256: ECDSA с использованием кривой P-256; поддерживает подпись и проверку подписи
  • ecdsa-p384: ECDSA с использованием кривой P-384; поддерживает подпись и проверку подписи
  • ecdsa-p521: ECDSA с использованием кривой P-521; поддерживает подпись и проверку подписи
  • rsa-2048: 2048-битный RSA ключ; поддерживает шифрование, дешифрование, подпись и проверку подписи
  • rsa-3072: 3072-битный RSA ключ; поддерживает шифрование, дешифрование, подпись и проверку подписи
  • rsa-4096: 4096-битный RSA ключ; поддерживает шифрование, дешифрование, подпись и проверку подписи
  • gost28147: ГОСТ 28147-89 с 256-битным ключом (S-блок CryptoPro-A) в режиме CFB с 8-байтным вектором инициализации и имитовставкой (encrypt-then-MAC); поддерживает шифрование, дешифрование, производные ключи и конвергентное шифрование
  • gost341264: ГОСТ Р 34.12-2015 «Магма» (64-битный блок) с 256-битным ключом в режиме CFB с 8-байтным вектором инициализации и имитовставкой; поддерживает шифрование, дешифрование, производные ключи и конвергентное шифрование
  • gost3412128: ГОСТ Р 34.12-2015 «Кузнечик» (128-битный блок) с 256-битным ключом в режиме CFB с 16-байтным вектором инициализации и имитовставкой; поддерживает шифрование, дешифрование, производные ключи и конвергентное шифрование
  • gost3410-256-paramset-a, gost3410-256-paramset-b, gost3410-256-paramset-c, gost3410-256-paramset-d: ГОСТ Р 34.10-2012 с 256-битным ключом на наборах параметров TC26 A, B, C и D соответственно; поддерживают подпись и проверку подписи
  • gost3410-512-paramset-a, gost3410-512-paramset-b, gost3410-512-paramset-c: ГОСТ Р 34.10-2012 с 512-битным ключом на наборах параметров TC26 A, B и C соответственно; поддерживают подпись и проверку подписи
  • hmac: HMAC; поддерживает генерацию и проверку HMAC.

Все типы ключей поддерживают операции HMAC через использование второго случайно сгенерированного ключа, создаваемого при инициализации или ротации ключа. Тип ключа HMAC поддерживает только операции HMAC и ведёт себя идентично другим алгоритмам в отношении операций HMAC, но поддерживает импорт ключей. По умолчанию, тип ключа HMAC использует 256-битный ключ.

Операции RSA используют один из следующих методов:

  • OAEP (шифрование, дешифрование), с хеш-функцией SHA-256 и MGF,
  • PSS (подпись, проверка), с настраиваемой хеш-функцией, также используемой для MGF, и
  • PKCS#1v1.5: (подпись, проверка), с настраиваемой хеш-функцией.

Особенности ключей ГОСТ:

  • Ключи ГОСТ Р 34.10-2012 (gost3410-*) подписывают предварительно вычисленный дайджест Стрибог. Алгоритм хеширования — streebog-256 для 256-битных ключей и streebog-512 для 512-битных. Это значение используется по умолчанию, любой другой алгоритм хеширования отклоняется с ошибкой. Алгоритмы хеширования streebog-256 и streebog-512 не поддерживаются для ключей RSA.
  • Подпись ГОСТ не оборачивается в структуру ASN.1: это последовательность байтов s || r фиксированной длины (big-endian) в кодировке base64.
  • Ключи ГОСТ Р 34.10-2012 не поддерживают шифрование и дешифрование, а симметричные ключи ГОСТ (gost28147, gost341264, gost3412128) не поддерживают подпись.
  • Ключи ГОСТ Р 34.10-2012 поддерживают импорт открытых ключей и экспорт ключей (в формате PEM).
  • Ассоциированные данные (associated_data) для симметричных ключей ГОСТ не поддерживаются.

Конвергентное шифрование

Конвергентное шифрование — это режим, при котором один и тот же набор открытого текста и контекста всегда приводит к одному и тому же шифртексту. Это достигается путём получения ключа с использованием функции вывода ключа, а также детерминированного получения одноразового значения (nonce). Поскольку эти параметры различаются для любой комбинации открытого текста и шифртекста в ключевом пространстве размером 2^256, риск повторного использования nonce практически равен нулю.

У этого подхода есть множество практических применений. Одним из распространённых сценариев является хранение шифртекста в базе данных с ограниченной поддержкой поиска/запросов, так что строки с одинаковым значением для конкретного поля могут быть возвращены по результатам запроса.

Чтобы обеспечить возможность обновления алгоритма при необходимости, исторически поддерживались различные версии конвергентного шифрования:

  • Version 1 требовала от клиента самостоятельного предоставления nonce, что даёт высокую гибкость, но может быть опасным при неправильной реализации. Ключи, использующие эту версию, не могут быть обновлены.
  • Version 2 использовала алгоритмический подход для вычисления параметров. Однако применяемый алгоритм был уязвим к офлайн-атакам подтверждения открытого текста, что позволяло злоумышленникам выполнять перебор для расшифровки, если размер открытого текста был небольшим. Ключи с версией 2 можно обновить путём выполнения операции поворота (rotate) до новой версии ключа; после чего существующие значения могут быть повторно обёрнуты с использованием новой версии ключа и будут использовать алгоритм версии 3.
  • Versionя 3 использует иной алгоритм, разработанный с учётом устойчивости к офлайн-атакам подтверждения открытого текста. Он схож с AES-SIV тем, что использует псевдослучайную функцию (PRF) для генерации nonce на основе открытого текста.

Настройка

Большинство механизмов секретов требуют предварительной настройки перед использованием. Эти шаги обычно выполняются оператором или системой управления конфигурацией.

Включите Transit secrets engine:

$ stronghold secrets enable transit
Success! Enabled the transit secrets engine at: transit/

По умолчанию механизм секретов монтируется по имени механизма. Чтобы указать другой путь, используйте аргумент -path.

Создайте именованный ключ шифрования:

$ stronghold write -f transit/keys/my-key
Success! Data written to: transit/keys/my-key

Обычно каждое приложение использует собственный ключ шифрования.

Использование

После настройки механизма и получения пользователем или системой токена Stronghold с соответствующими разрешениями можно генерировать учётные данные.

Шифрование данных с помощью /encrypt и указанного ключа:

Примечание Все данные должны быть закодированы в base64. Это связано с тем, что Stronghold не требует, чтобы передаваемый открытый текст был текстом — это может быть бинарный файл (PDF, изображение и т.д.). Самый безопасный способ передачи таких данных в JSON — кодирование в base64.

$ stronghold write transit/encrypt/my-key plaintext=$(echo "my secret data" | base64)

Key           Value
---           -----
ciphertext    vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==

Возвращаемый шифртекст начинается с vault:v1:. Префикс (stronghold) обозначает, что данные зашифрованы Stronghold. Версия v1 указывает, что использовалась первая версия ключа. Это важно при ротации, так как Stronghold использует правильную версию ключа для расшифровки.

Обратите внимание: Stronghold не хранит шифртекст. Ответственность за их сохранение лежит на вызывающей стороне. Чтобы расшифровать данные, необходимо снова передать шифртекст в Stronghold.

Stronghold HTTP API ограничивает размер запроса до 32MB во избежание атак типа DoS. Этот лимит можно изменить в блоке listener конфигурации Stronghold.

Расшифровка данных с использованием /decrypt:

$ stronghold write transit/decrypt/my-key ciphertext=vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==

Key          Value
---          -----
plaintext    bXkgc2VjcmV0IGRhdGEK

Результат — строка в base64. Декодируйте её, чтобы получить исходные данные:

$ base64 --decode <<< "bXkgc2VjcmV0IGRhdGEK"
my secret data

Или в одну команду:

$ stronghold write -field=plaintext transit/decrypt/my-key ciphertext=... | base64 --decode
my secret data

Через ACL можно ограничить доступ: доверенным операторам — управление ключами, а приложениям — только шифрование/дешифровку с нужными ключами.

Ротация базового ключа шифрования. В результате будет сгенерирован новый ключ шифрования и добавлен в связку ключей для именованного ключа:

$ stronghold write -f transit/keys/my-key/rotate
Success! Data written to: transit/keys/my-key/rotate

В последующих шифрованиях будет использоваться этот новый ключ. Старые данные все ещё могут быть расшифрованы благодаря использованию связки ключей.

Обновление уже зашифрованных данных на новый ключ. Stronghold расшифрует значение, используя соответствующий ключ в связке ключей, а затем зашифрует полученный открытый текст с помощью новейшего ключа в связке ключей:

$ stronghold write transit/rewrap/my-key ciphertext=vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==

Key           Value
---           -----
ciphertext    vault:v2:...

Этот процесс не раскрывает исходные данные. Поэтому политика Stronghold может позволить даже недоверенным процессам выполнять “rewrap”, не выдавая им доступ к самим данным.

Импорт собственного ключа (Bring your own key BYOK)

Импорт ключей нужен в случаях, когда необходимо перенести ключ из HSM или другой системы. Однако, безопаснее, если ключ будет сгенерирован и управляться внутри Stronghold.

Сначала получите wrapping key из Transit:

stronghold read transit/wrapping_key

Этот ключ будет 4096 битным публичным RSA-ключом.

Далее этот ключ используется для создания шифрованного значения для import, как описано ниже. Ниже под целевым ключом подразумевается импортируемый ключ.

HSM

Если ключ импортируется из HSM, поддерживающего PKCS#11, возможны два сценария:

  • Если HSM поддерживает механизм CKM_RSA_AES_KEY_WRAP, его можно использовать для обёртывания целевого ключа с помощью обертывающего ключа.

  • В противном случае для обёртывания целевого ключа можно использовать два механизма. Сначала нужно сгенерировать 256-битный ключ AES, а затем использовать его для обёртывания целевого ключа с помощью механизма CKM_AES_KEY_WRAP_KWP. Затем ключ AES должен быть обёрнут под обертывающий ключ с помощью механизма CKM_RSA_PKCS_OAEP с использованием MGF1 и либо SHA-1, SHA-224, SHA-256, SHA-384, либо SHA-512.

Шифртекст создаётся путем добавления обёрнутого целевого ключа к обёрнутому ключу AES.

Байты шифртекста должны быть закодированы в base64.

Процесс вручную

Если целевой ключ не хранится в HSM или KMS, то для создания шифртекста на входе эндпоинта import можно использовать следующие шаги:

  • Сгенерируйте эфемерный 256-битный ключ AES.

  • Оберните целевой ключ эфемерным ключом AES с помощью AES-KWP.

При обёртывании симметричного ключа (например, ключа AES или ChaCha20) оберните необработанные байты ключа. Например, для 128-битного ключа AES это будет байтовый массив длиной 16 символов, который будет непосредственно обёрнут без base64 или других кодировок. При обёртывании асимметричного ключа (например, ключа RSA или ECDSA) оберните PKCS8 закодированный формат этого ключа в сырой DER/бинарной форме. Не применяйте PEM-кодировку перед шифрованием и не кодируйте base64.

  • Оберните ключ AES в ключ обертки Stronghold с помощью RSAES-OAEP с MGF1 и SHA-1, SHA-224, SHA-256, SHA-384 или SHA-512.

  • Удалите эфемерный ключ AES.

  • Добавьте обёрнутый целевой ключ к обёрнутому ключу AES.

  • Закодируйте результат в Base64.

Дополнительные ресурсы