Blog of Heath

Ruby String Encryption

Posted in Ruby by heathanderson on September 25, 2009

Encrypting a string is fairly easy in Ruby. All you need to do is require 'openssl'. For this example I am using the ‘des-ede3-cbc’ (Triple DES using Cipher Block Chaining) cipher. Most–if not all–of the ciphers listed on OpenSSL.org as supported ciphers should work as well.

Triple DES requires a 24-byte key, with Ruby this means a string with 24 characters. We are also required to provide an initialization vector (IV). The IV is usually the same size as the block size of the cipher you are using (so says Wikipedia, so say we all). In our case this means an IV of 64-bits, or 8-bytes, or an 8 character Ruby String. If we randomize our IV and include it with our encrypted string then we can ensure that our encrypted data never looks the same even when we encrypt the same string multiple times.

require 'openssl'

KEY = '0123456789abcdef01234567890' # 24 characters

string = "encrypt this"

des = OpenSSL::Cipher::Cipher.new("des-ede3-cbc")
des.encrypt # this tells OpenSSL what mode to operate in, here we want to encrypt data
des.iv = iv = '01234567' # 8 characters, hard-coded for now

data = des.update(string) + des.final  
data = iv + data # this way when we randomize our IV it will be available when we need to decrypt the data

puts data

This should output something like 01234567z4¥K½ß) ©ˆˆ˜ž. This isn’t the friendliest way to send data, so lets do something about that. The easiest thing to do is Base 64 encode the data, and maybe URI escape it for good measure.

# be sure to put the following at the top of your code:
# require "base64"
# require 'uri'
# after 'the puts data' in the snippet above do the following:

data = Base64.encode64(data)
data = URI.escape(data, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))

puts data

This should give you the much nicer MDEyMzQ1Njd6jzSlS73fKSAdqYgRiJie%0A.

Decryption is similarly easy.

des = OpenSSL::Cipher::Cipher.new("des-ede3-cbc")
des.decrypt
des.key = KEY
encrypted_data = URI.unescape(data)
encrypted_data = Base64.decode64(data)
des.iv =  encrypted_data.slice!(0,8) #This gives us our iv back and removes it from the encrypted data
  
decrypted = des.update(encrypted_data) + des.final  
    
puts decrypted

If you are using Rails or have access to ActiveSupport ActiveSupport::SecureRandom is a great way to generate your key and IV. Also be sure to check out ActiveSupport::MessageEncryptor and my string_encryption plugin. I’ll probably do a writeup on the string_encryption plugin sometime next week.

Tagged with: ,

3 Responses

Subscribe to comments with RSS.

  1. […] you are looking for what size an initialization vector should be check out my post on encrypting a string with Ruby. Tagged with: Encryption, JRuby, Ruby 1 comment « Ruby […]

  2. Adam Rixey said, on November 21, 2009 at 2:50 am

    Very helpful. Thanks.

  3. […] The only cipher used is ‘des-ede3-cbc’ (Triple DES using Cipher Block Chaining) . See my post on encrypting/decrypting a string with Ruby for more information. First install the […]


Leave a comment