module AttrEncrypted::InstanceMethods

Public Instance Methods

decrypt(attribute, encrypted_value) click to toggle source

Decrypts a value for the attribute specified using options evaluated in the current object's scope

Example

class User
  attr_accessor :secret_key
  attr_encrypted :email, :key => :secret_key

  def initialize(secret_key)
    self.secret_key = secret_key
  end
end

@user = User.new('some-secret-key')
@user.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING')
# File lib/attr_encrypted.rb, line 279
def decrypt(attribute, encrypted_value)
  self.class.decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute))
end
encrypt(attribute, value) click to toggle source

Encrypts a value for the attribute specified using options evaluated in the current object's scope

Example

class User
  attr_accessor :secret_key
  attr_encrypted :email, :key => :secret_key

  def initialize(secret_key)
    self.secret_key = secret_key
  end
end

@user = User.new('some-secret-key')
@user.encrypt(:email, 'test@example.com')
# File lib/attr_encrypted.rb, line 298
def encrypt(attribute, value)
  self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute))
end

Protected Instance Methods

evaluate_attr_encrypted_option(option) click to toggle source

Evaluates symbol (method reference) or proc (responds to call) options

If the option is not a symbol or proc then the original option is returned

# File lib/attr_encrypted.rb, line 317
def evaluate_attr_encrypted_option(option)
  if option.is_a?(Symbol) && respond_to?(option)
    send(option)
  elsif option.respond_to?(:call)
    option.call(self)
  else
    option
  end
end
evaluated_attr_encrypted_options_for(attribute) click to toggle source

Returns attr_encrypted options evaluated in the current object's scope for the attribute specified

# File lib/attr_encrypted.rb, line 305
def evaluated_attr_encrypted_options_for(attribute)
  if evaluate_attr_encrypted_option(self.class.encrypted_attributes[attribute.to_sym][:mode]) == :per_attribute_iv_and_salt
    load_iv_for_attribute(attribute, self.class.encrypted_attributes[attribute.to_sym][:algorithm])
    load_salt_for_attribute(attribute)
  end

  self.class.encrypted_attributes[attribute.to_sym].inject({}) { |hash, (option, value)| hash[option] = evaluate_attr_encrypted_option(value); hash }
end
load_iv_for_attribute(attribute, algorithm) click to toggle source
# File lib/attr_encrypted.rb, line 327
def load_iv_for_attribute(attribute, algorithm)
  encrypted_attribute_name = self.class.encrypted_attributes[attribute.to_sym][:attribute]
  iv = send("#{encrypted_attribute_name}_iv")
  if(iv == nil)
    begin
      algorithm = algorithm || "aes-256-cbc"
      algo = OpenSSL::Cipher::Cipher.new(algorithm)
      iv = [algo.random_iv].pack("m")
      send("#{encrypted_attribute_name}_iv=", iv)
    rescue RuntimeError
    end
  end
  self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:iv => iv.unpack("m").first) if (iv && !iv.empty?)
end
load_salt_for_attribute(attribute) click to toggle source
# File lib/attr_encrypted.rb, line 342
def load_salt_for_attribute(attribute)
  encrypted_attribute_name = self.class.encrypted_attributes[attribute.to_sym][:attribute]
  salt = send("#{encrypted_attribute_name}_salt") || send("#{encrypted_attribute_name}_salt=", Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15])
  self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:salt => salt)
end