I am using Ruby Open SSL bindings for AES-256 encryption. I can encrypt a non-empty string. However, when trying to encrypt an empty string, Ruby throws an exception complaining that the data should not be empty. How can I encrypt an empty string using Ruby OpenSSL bindings?
Code to reproduce the problem
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)
Version
- ruby 2.2.2p95
- OpenSSL :: VERSION - "1.1.0"
- Microsoft SQL Server 2014 (12.0.2000.8)
Why do I want to encrypt blank lines?
I am writing an ETL program to transfer data from one database to a SqlServer database. Some columns from the source database must be encrypted before being written to the target database. Source columns can contain any data, including empty rows. Destination columns are usually not NULL. Destination columns will be decrypted with .net code.
Goal No. 1: no information about the encrypted field, including that exists, should be restored without proper decryption. The encrypted empty string must be indistinguishable from any other encrypted data.
Goal # 2: The .net code that decrypts these values should not process blank lines specifically.
If I can get openssl to encrypt empty strings, I will achieve both of these goals.
Workaround - do not encrypt blank lines
I could simply not encrypt blank lines by passing them.
def encrypt(plaintext) return plaintext if plaintext.empty? ... end def decrypt(iv, ciphertext) return ciphertext if ciphertext.empty? ... end
This has drawbacks in disclosing information, as well as the need to write collaboration code on the .net side.
Workaround - Add a constant to plaintext
I can add some constant to plaintext before encryption and delete it after decryption:
PLAINTEXT_SUFFIX = " " def encrypt(plaintext) plaintext += PLAINTEXT_SUFFIX ... end def decrypt(iv, ciphertext) ... plaintext.chomp(PLAINTEXT_SUFFIX) end
This hides whether or not the data exists, but still requires .net code collaboration.