25

In a Rails 3.0 (Ruby 1.9.2) app I'm trying to encrypt some data using something like this:

cipher = OpenSSL::Cipher.new 'aes-256-cbc'
cipher.encrypt
cipher.key = cipher.random_key
cipher.iv = cipher.random_iv

encrypted = cipher.update 'most secret data in the world'
encrypted << cipher.final

That will go into a UTF-8 database. My problem is that

> encrypted.encoding
 => #<Encoding:ASCII-8BIT>

> encrypted.encode 'utf-8'
Encoding::UndefinedConversionError: "\xF7" from ASCII-8BIT to UTF-8

How can I get an UTF-8 encrypted string?

Henrique Zambon
  • 1,301
  • 1
  • 11
  • 20

2 Answers2

46

The solution is to convert the ASCII-8BIT string to Base64 and then encode to UTF-8.

cipher = OpenSSL::Cipher.new 'aes-256-cbc'
cipher.encrypt
cipher.key = cipher.random_key
cipher.iv = cipher.random_iv

encrypted = cipher.update 'most secret data in the world'
encrypted << cipher.final

encoded = Base64.encode64(encrypted).encode('utf-8')

Once persisted and retrieved from the database,

decoded = Base64.decode64 encoded.encode('ascii-8bit')

and finally decrypt it.


PS: If you're curious:

cipher = OpenSSL::Cipher.new 'aes-256-cbc'
cipher.decrypt
cipher.key = random_key
cipher.iv = random_iv

decrypted = cipher.update encoded
decrypted << cipher.final

> decrypted
 => 'most secret data in the world'
Henrique Zambon
  • 1,301
  • 1
  • 11
  • 20
0

I believe your best bet is to use force_encoding found here.

> encrypted.encoding
  => #<Encoding:ASCII-8BIT>

> encrypted.force_encoding "utf-8"

> encrypted.encoding
  => #<Encoding:UTF-8>
mzaccari
  • 111
  • 2
  • 6