Simple encryption of ActiveRecord fields

For past week, I have been working on encryption solution for a Rails app. The requirement was to encrypt chosen fields like ssn of an ActiveRecord model.

I've research a variety of solutions, including attr_encrypted and encryptor gems.

I want to show a simple way of encryption that combines ActiveRecord::Base.serialize and OpenSSL::Cipher, which comes with the Ruby stdlib.

Few things to bear in mind:

  • this kind of encryption helps only in case when your database is stolen
  • if hacker gets access to Rails console or ENV['ENCRYPTION_KEY'], you're hacked
  • you may want to use IV and salt for sensitive data
  • by using Marshal, our encrypted field can store instance of any class (Date, Time, whatever!)

{% highlight ruby %}


module Crypt class << self def encrypt(value) crypt(:encrypt, value) end

def decrypt(value)
  crypt(:decrypt, value)

def encryption_key

ALGO = 'aes-256-cbc'.freeze
def crypt(cipher_method, value)
  cipher =
  result = cipher.update(value)
  result <<

end end


custom coder for Rails serialized attribute

more examples:

encrypted value has to be stored as base64 because it's not UTF-safe

class EncryptedCoder def load(value) return if value.nil?



def dump(value) Base64.encode64( Crypt.encrypt( Marshal.dump(value))) end end


class WowSuchSecureModel < ActiveRecord::Base serialize :ssn, end {% endhighlight %}

Done! You can use EncryptedCoder in any model.

A quick demo:

{% highlight ruby %} pry(main)> model = WowSuchSecureModel.create(ssn: "11-22-333") (0.2ms) BEGIN SQL (13.2ms) INSERT INTO "table" ("ssn", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["ssn", "S9CTpTxsuG1mFExrFzyy1XD1qtxpiTKGOiopvFhuuwY=\n"], ["created_at", "2015-12-18 21:52:24.425346"], ["updated_at", "2015-12-18 21:52:24.425346"]] (7.5ms) COMMIT => #<WowSuchSecureModel:0x007f803a19f4f8 id: 4, ssn: "11-22-333", created_at: Fri, 18 Dec 2015 21:52:24 UTC +00:00, updated_at: Fri, 18 Dec 2015 21:52:24 UTC +00:00> pry(main)> model.ssn => "11-22-333" pry(main)> WowSuchSecureModel.last.ssn => "11-22-333" pry(main)> WowSuchSecureModel.last.ssn_before_type_cast => "S9CTpTxsuG1mFExrFzyy1XD1qtxpiTKGOiopvFhuuwY=\n" {% endhighlight %}

Written in December 2015.
Kir Shatrov

Kir Shatrov helps businesses to grow by scaling the infrastructure. He writes about software, scalability and the ecosystem. Follow him on Twitter to get the latest updates.