Я использую Ruby's Open SSL bindings для шифрования AES-256. Я могу зашифровать непустую строку. Однако, пытаясь зашифровать пустую строку, Ruby вызывает исключение, жалующееся на то, что данные не должны быть пустыми. Как я могу зашифровать пустую строку с помощью привязок OpenSSL Ruby?Шифровать пустую строку
код, чтобы воспроизвести проблему
require "openssl"
KEY = OpenSSL::Cipher::Cipher.new("aes-256-cbc").random_key
def encrypt(plaintext)
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.encrypt
iv = cipher.random_iv
cipher.iv = iv
cipher.key = KEY
ciphertext = cipher.update(plaintext) # <- ArgumentError here
ciphertext << cipher.final
[iv, ciphertext]
end
def decrypt(iv, ciphertext)
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.decrypt
cipher.iv = iv
cipher.key = KEY
plaintext = cipher.update(ciphertext)
plaintext << cipher.final
plaintext
end
p decrypt(*encrypt("foo")) # "foo"
p decrypt(*encrypt(""))
# /tmp/foo.rb:11:in `update': data must not be empty (ArgumentError)
# from /tmp/foo.rb:11:in `encrypt'
# from /tmp/foo.rb:27:in `<main>'
Версии
- рубинового 2.2.2p95
- OpenSSL :: версия "1.1.0"
- Microsoft SQL Server 2014 (12.0.2000.8)
Почему я хочу зашифровать пустые строки?
Я пишу программу ETL для переноса данных из одной базы данных в базу данных SqlServer. Некоторые столбцы из исходной базы данных должны быть зашифрованы перед записью их в целевую базу данных. Исходные столбцы могут содержать любые данные, включая пустые строки. Столбцы назначения обычно не имеют значения NULL. Столбцы назначения будут дешифрованы кодом .net.
Цель № 1: Никакая информация о зашифрованном поле, в том числе и не существует, должна быть восстановлена без надлежащего ее дешифрования. Зашифрованная пустая строка должна быть неотличима от любых других зашифрованных данных.
Цель №2: код .net, который расшифровывает эти значения, не должен обрабатывать пустые строки специально.
Если я могу получить openssl для шифрования пустых строк, я добьюсь обоих этих целей.
Обход - Не шифровать пустые строки
Я мог бы просто не шифровать пустые строки, пропуская их через.
def encrypt(plaintext)
return plaintext if plaintext.empty?
...
end
def decrypt(iv, ciphertext)
return ciphertext if ciphertext.empty?
...
end
Это имеет недостатки обнажая информации, а также требовать, взаимодействующий код должен быть записан на стороне .net.
Обход - Добавьте константу к открытому тексту
Я мог бы добавить некоторую постоянную строку в незашифрованном перед шифрованием, и удалить его после расшифровки:
PLAINTEXT_SUFFIX = " "
def encrypt(plaintext)
plaintext += PLAINTEXT_SUFFIX
...
end
def decrypt(iv, ciphertext)
...
plaintext.chomp(PLAINTEXT_SUFFIX)
end
Это скрывает, существуют ли данные или нет, но по-прежнему требует сотрудничества .net-кода.
OpenSSL поддерживает заполнение PKCS # 7, поэтому это должно работать. Это, вероятно, лучше подходит для отчета об ошибке. Кстати, вы пробовали просто пропустить 'cipher.update', если открытый текст пуст? 'cipher.final' может быть достаточно в этом случае. –
@ArtjomB. Я попытался отказаться от вызова обновления Cipher #. Это не сработало, когда я попробовал это раньше из-за ошибки ID10T, чем в то время не заметил. Похоже, это решение. Не могли бы вы добавить его в качестве ответа? –
Вы можете добавить его сами. Я понятия не имею о рубине, и я не хочу начинать учиться в это конкретное время. :) –