Несоответствие заголовка SDK AWS Encryption между регионами
Я использую Amazon Encryption SDK для шифрования данных перед их сохранением в базе данных. Я также использую Amazon KMS. Как часть процесса шифрования, SDK хранит идентификатор поставщика ключа для ключа данных, используемого для шифрования, в сгенерированном заголовке зашифрованного текста.
Как описано в документации здесь http://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html
Операции шифрования в AWS Encryption SDK возвращают одну структуру данных или сообщение, которое содержит зашифрованные данные (зашифрованный текст) и все зашифрованные ключи данных. Чтобы понять эту структуру данных или создать библиотеки, которые читают и пишут ее, вам необходимо понять формат сообщения.
Формат сообщения состоит как минимум из двух частей: заголовка и тела. В некоторых случаях формат сообщения состоит из третьей части, нижнего колонтитула.
Значение идентификатора ключевого поставщика содержит имя ресурса Amazon (ARN) главного ключа клиента (CMK) AWS KMS.
Здесь возникает проблема. Сейчас у меня есть два разных региона KMS для шифрования. Каждый идентификатор поставщика ключей имеет одно и то же значение ключа шифрованных данных. Таким образом, любой ключ может быть использован для расшифровки данных. Однако проблема заключается в заголовках зашифрованного текста. Допустим, у меня есть KMS1 и KMS2. Если я зашифрую данные с помощью ключа, предоставленного KMS1, то идентификатор поставщика ключей будет сохранен в заголовке зашифрованного текста. Если я попытаюсь расшифровать данные с помощью KMS2, несмотря на то, что ключ зашифрованных данных одинаков, расшифровка завершится неудачно, поскольку заголовок не содержит поставщика ключей для KMS2. У него есть идентификатор поставщика ключей для KMS1. Это терпит неудачу с этой ошибкой:
com.amazonaws.encryptionsdk.exception.BadCiphertextException: Header integrity check failed.
at com.amazonaws.encryptionsdk.internal.DecryptionHandler.verifyHeaderIntegrity(DecryptionHandler.java:312) ~[application.jar:na]
at com.amazonaws.encryptionsdk.internal.DecryptionHandler.readHeaderFields(DecryptionHandler.java:389) ~[application.jar:na]
...
com.amazonaws.encryptionsdk.internal.DecryptionHandler.verifyHeaderIntegrity(DecryptionHandler.java:310) ~[application.jar:na]
... 16 common frames omitted
Caused by: javax.crypto.AEADBadTagException: Tag mismatch!
Не удается проверить целостность заголовка и не удается. Это нехорошо, потому что я планировал иметь несколько KMS в случае сбоя KMS в одном регионе. Мы дублируем наши данные во всех наших регионах и думаем, что можем использовать любую KMS из этих регионов для расшифровки, если ключи зашифрованных данных совпадают. Тем не менее, похоже, что я заблокировал использование только оригинального KMS, который шифровал данные? Как же мы можем масштабировать это на несколько регионов, если мы можем полагаться только на одну KMS?
Я мог бы включить все основные ключи региона в вызов для шифрования данных. Таким образом, заголовки всегда будут совпадать, хотя это не будет отражать, какой KMS он на самом деле использует. Однако это также не масштабируется, поскольку в будущем мы можем добавлять / удалять регионы, что может вызвать проблемы со всеми данными, которые уже зашифрованы.
Я что-то пропустил? Я думал об этом, и я хочу решить эту проблему, не нанося вред проверкам целостности, предоставляемым SDK/Encryption.
Обновить:
Основано на комментарии @jarmod
Использование псевдонима также не работает, потому что мы можем связать псевдоним только с ключом в регионе, и в нем хранится разрешенное имя ключа ARN, на который он все равно указывает.
Я читаю этот документ, и он говорит
Кроме того, шифрование конвертов может помочь спроектировать ваше приложение для аварийного восстановления. Вы можете перемещать зашифрованные данные как есть между регионами, и вам нужно только перешифровать ключи данных с помощью CMK для конкретного региона
Однако это не совсем точно, поскольку SDK для шифрования не сможет расшифровать другой регион, поскольку идентификатор поставщика ключей для зашифрованных ключей данных будет совершенно другим!
1 ответ
Извините, так как я не знаком с программированием на Java, но я полагаю, что существует путаница, как вы используете CMK KMS для шифрования (или дешифрования) данных с использованием ключей из более чем одного региона для DR.
Когда вы используете несколько мастер-ключей для шифрования открытого текста, любой из мастер-ключей может использоваться для дешифрования открытого текста. Обратите внимание, что только один главный ключ (скажем, MKey1) генерирует ключ данных в виде открытого текста, который используется для шифрования данных. Затем этот ключ данных в незашифрованном виде шифруется другим главным ключом (MKey2).
В результате вы получите зашифрованные данные + зашифрованный ключ данных (используя MKey1) + зашифрованный ключ данных (используя MKey2).
Если по какой-либо причине MKey1 недоступен и вы хотите расшифровать зашифрованный текст, SDK можно использовать для расшифровки зашифрованного ключа данных с помощью MKey2, который может расшифровать зашифрованный текст.
Итак, да, вы должны указать несколько KMS CMK ARN в вашей программе, если вы хотите использовать несколько KMS. У документа, которым вы поделились, также есть пример, который, я уверен, вы знаете.