module CryptKeeper::Model::ClassMethods

Public Instance Methods

crypt_keeper(*args) click to toggle source

Public: Setup fields for encryption

args - An array of fields to encrypt. The last argument should be
a hash of options. Note, an :encryptor is required. This should be
a class that takes a hash for initialize and provides an encrypt
and decrypt method.

Example

class MyModel < ActiveRecord::Base
  crypt_keeper :field, :other_field, :encryptor => :aes, :key => 'super_good_password'
end
# File lib/crypt_keeper/model.rb, line 51
def crypt_keeper(*args)
  class_attribute :crypt_keeper_fields
  class_attribute :crypt_keeper_encryptor
  class_attribute :crypt_keeper_options
  class_attribute :crypt_keeper_encoding

  self.crypt_keeper_options   = args.extract_options!
  self.crypt_keeper_encryptor = crypt_keeper_options.delete(:encryptor)
  self.crypt_keeper_encoding  = crypt_keeper_options.delete(:encoding)
  self.crypt_keeper_fields    = args

  ensure_valid_encryptor!

  before_save :enforce_column_types_callback

  if self.crypt_keeper_encoding
    after_find :force_encodings_on_fields
    before_save :force_encodings_on_fields
  end

  crypt_keeper_fields.each do |field|
    serialize field, encryptor
  end
end
decrypt_table!() click to toggle source

Public: Decrypt a table (reverse of encrypt_table!)

# File lib/crypt_keeper/model.rb, line 103
def decrypt_table!
  tmp_table = Class.new(ActiveRecord::Base).tap { |c| c.table_name = self.table_name }

  transaction do
    tmp_table.find_each do |r|
      crypt_keeper_fields.each do |field|
        r.send("#{field}=", encryptor.decrypt(r[field])) if r[field].present?
      end

      r.save!
    end
  end
end
encrypt_table!() click to toggle source

Public: Encrypt a table for the first time.

# File lib/crypt_keeper/model.rb, line 85
def encrypt_table!
  tmp_table = Class.new(ActiveRecord::Base).tap do |c|
    c.table_name = self.table_name
    c.inheritance_column = :type_disabled
  end

  transaction do
    tmp_table.find_each do |r|
      crypt_keeper_fields.each do |field|
        r.send("#{field}=", encryptor.encrypt(r[field])) if r[field].present?
      end

      r.save!
    end
  end
end
search_by_plaintext(field, criteria) click to toggle source
# File lib/crypt_keeper/model.rb, line 76
def search_by_plaintext(field, criteria)
  if crypt_keeper_fields.include?(field.to_sym)
    encryptor.search(all, field.to_s, criteria)
  else
    raise ArgumentError, "#{field} is not a crypt_keeper field"
  end
end

Private Instance Methods

encryptor() click to toggle source

Private: The encryptor instance.

# File lib/crypt_keeper/model.rb, line 125
def encryptor
  @encryptor ||= encryptor_klass.new(crypt_keeper_options)
end
encryptor_klass() click to toggle source

Private: The encryptor class

# File lib/crypt_keeper/model.rb, line 120
def encryptor_klass
  @encryptor_klass ||= "CryptKeeper::Provider::#{crypt_keeper_encryptor.to_s.camelize}".constantize
end
ensure_valid_encryptor!() click to toggle source

Private: Ensure we have a valid encryptor.

# File lib/crypt_keeper/model.rb, line 130
def ensure_valid_encryptor!
  unless defined?(encryptor_klass) && encryptor_klass.respond_to?(:new) &&
    %i(load dump).all? { |m| encryptor.respond_to?(m) }
    raise ArgumentError, "You must specify a valid encryptor that implements " \
      "the `load` and `dump` methods (you can inherit from CryptKeeper::Provider::Base). Example: `crypt_keeper :encryptor => :aes`"
  end
end