Я работаю с командой разработчиков, которые внедряют шифрование в состоянии покоя на уровне приложения. Это для особо важных полей внутри RDB. (Базовое хранилище БД имеет дополнительный уровень шифрования, но здесь это не по теме.) Мы используем Spring AesBytesEncryptor и соответствующие классы для этого.
Мы еще не полностью решили ротацию ключей, и я изучаю, как сделать это безопасным образом. Мы хотели бы использовать отдельный инструмент смены ключей, который работал бы изолированно от приложения, потребляющего данные. Этот инструмент ротации ключей будет обращаться к БД асинхронно и выполнять повторное шифрование небольшими порциями. (Ни в одной транзакции БД, которая повторно зашифровала бы все данные.)
Для этого мы планируем, что приложение может быть настроено с несколькими (ну, двумя) ключами одновременно. Он всегда будет использовать первый ключ для шифрования новых данных. Но он может расшифровывать старые данные с помощью любого ключа, в зависимости от того, зашифровал ли уже инструмент смены ключей повторно шифрование конкретного поля.
Теперь вопрос в том, нужно ли нам хранить дополнительные ключевые метаданные версии в БД? Это сообщит приложению, какой ключ дешифрования использовать для любого фрагмента данных.
Я надеюсь обойти это, полагаясь вместо этого на некоторую контрольную сумму формы. Приложение будет просто пробовать ключи расшифровки по очереди, пока не получит расшифрованное значение, не нарушающее контрольную сумму.
Имхо, Spring AesBytesEncryptor, возможно, уже предоставляет все, что нам нужно. Но надежность будет зависеть от того, какой режим мы используем. Вот что я думаю о двух поддерживаемых режимах:
Режим AES/CBC/PKCS5Заполнение:
Не имеет контрольной суммы как таковой, но заполнение, скорее всего, сломается при попытке дешифрования с неправильным ключом. Однако это зависит от размера заполнения, которое зависит от размера данных открытого текста. В худшем случае может быть всего 1 байт заполнения. Таким образом, шансы найти правильное заполнение с неправильным ключом дешифрования могут достигать 1/256. Это кажется слишком рискованным, чтобы на него полагаться.
Режим AES/GCM/NoPadding:
Здесь «тег аутентификации» GCM служит формой контрольной суммы. Насколько я понимаю, для AES всегда 128 бит (16 байт). Это означает, что вероятность попадания действительного тега аутентификации с неправильным ключом дешифрования составляет примерно 1/(2^128).То есть практически никогда, поэтому я думаю, что это должно подойти для нашего приложения.
Верны ли приведенные выше предположения? Что я сделал не так?
Считаете ли вы, что это достаточно надежно, чтобы попробовать несколько ключей дешифрования по очереди во время ротации ключей при использовании AES/GCM/NoPadding? Или нам все-таки нужно хранить ключевую информацию о версиях вместе с зашифрованными данными?
Или есть еще лучший способ решения проблемы ротации ключей в нашем сценарии?