yaodong
8/13/2015 - 2:49 PM

active record with ssl encryption

active record with ssl encryption

require 'openssl'
require 'digest/sha1'
require 'base64'
require 'json'

class Setting < ActiveRecord::Base

  belongs_to :user, inverse_of: :settings

  serialize :content, JSON

  validates :user, presence: true
  validates :name, presence: true, format: /\A[a-z0-9_\.]+\z/

  @decrypted = nil

  before_save do
    @decrypted   = content
    self.content = encrypt(content)
  end

  after_save do
    self.content = @decrypted
  end

  after_find do
    self.content = decrypt(content)
  end

  private

    def encrypt(content)
      content = ActiveSupport::JSON.encode(content)
      cipher  = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
      cipher.encrypt
      random_iv  = cipher.random_iv
      self.salt  = Base64.encode64(random_iv)
      cipher.key = crypt_key
      cipher.iv  = random_iv
      encrypted  = cipher.update(content)
      encrypted << cipher.final
      Base64.encode64(encrypted)
    end

    def decrypt(content)
      content = Base64.decode64(content)
      cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
      cipher.decrypt
      cipher.key = crypt_key
      cipher.iv  = Base64.decode64(salt)
      decrypted  = cipher.update(content)
      decrypted << cipher.final
      ActiveSupport::JSON.decode(decrypted)
    end

    def crypt_key
      Digest::SHA1.hexdigest(ENV['APP_SETTINGS_SALT'])
    end
end