Механизм транзитных секретов выполняет криптографические операции с данными в процессе передачи. 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 ключ; поддерживает шифрование, дешифрование, подпись и проверку подписиhmac
: HMAC; поддерживает генерацию и проверку HMAC.
Все типы ключей поддерживают операции HMAC через использование второго случайно сгенерированного ключа, создаваемого при инициализации или ротации ключа. Тип ключа HMAC поддерживает только операции HMAC и ведет себя идентично другим алгоритмам в отношении операций HMAC, но поддерживает импорт ключей. По умолчанию, тип ключа HMAC использует 256-битный ключ.
Операции RSA используют один из следующих методов:
- OAEP (шифрование, дешифрование), с хеш-функцией SHA-256 и MGF,
- PSS (подпись, проверка), с настраиваемой хеш-функцией, также используемой для MGF, и
- PKCS#1v1.5: (подпись, проверка), с настраиваемой хеш-функцией.
Конвергентное шифрование
Конвергентное шифрование — это режим, при котором один и тот же набор открытого текста и контекста всегда приводит к одному и тому же шифротексту. Это достигается путём получения ключа с использованием функции вывода ключа, а также детерминированного получения одноразового значения (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 не требует, чтобы передаваемый plaintext был текстом — это может быть бинарный файл (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.