module Pod4::Encrypting::InstanceMethods

Public Instance Methods

decrypt(string) click to toggle source

Public facing manual decryption, compatible with the current model

# File lib/pod4/encrypting.rb, line 202
def decrypt(string)
  cipher = get_cipher(:decrypt)
  iv     = use_iv? ? encryption_iv : nil
  crypt(cipher, :decrypt, iv, string)
end
encrypt(string) click to toggle source

Public facing manual encryption, compatible with the current model

# File lib/pod4/encrypting.rb, line 193
def encrypt(string)
  cipher = get_cipher(:encrypt)
  iv     = use_iv? ? encryption_iv : nil
  crypt(cipher, :encrypt, iv, string)
end
encryption_iv() click to toggle source

The value of the IV field (whatever it is) _as currently stored on the model_

# File lib/pod4/encrypting.rb, line 185
def encryption_iv
  return nil unless use_iv?
  instance_variable_get( "@#{self.class.encryption_iv_column}".to_sym )
end
map_to_interface() click to toggle source

When mapping to the interface, encrypt the encryptable columns from the model

Calls superclass method
# File lib/pod4/encrypting.rb, line 141
def map_to_interface
  return super if self.class.encryption_key.nil?

  hash   = super.to_h
  cipher = get_cipher(:encrypt)

  # Each time we write, we set a new IV. We must also set it on the hash to go to the
  # interface, where it must be base64 encoded, just like the encrypted columns.
  if use_iv? 
    set_encryption_iv( cipher.random_iv )
    hash[self.class.encryption_iv_column] = Base64.strict_encode64(encryption_iv)
  end

  self.class.encryption_columns.each do |col|
    hash[col] = crypt(cipher, :encrypt, encryption_iv, hash[col])
  end

  Octothorpe.new(hash)
end
map_to_model(ot) click to toggle source

When mapping to the model, decrypt the encrypted columns from the interface

Calls superclass method
# File lib/pod4/encrypting.rb, line 164
def map_to_model(ot)
  return super(ot) if self.class.encryption_key.nil?

  hash   = ot.to_h
  cipher = get_cipher(:decrypt)

  # The IV column is not in columns, so we need to de-base-64 it and set it on the model here
  if use_iv? && (iv64 = hash[self.class.encryption_iv_column])
    set_encryption_iv Base64.strict_decode64(iv64)
  end

  self.class.encryption_columns.each do |col|
    hash[col] = crypt(cipher, :decrypt, encryption_iv, hash[col])
  end

  super Octothorpe.new(hash)
end

Private Instance Methods

crypt(cipher, direction, iv, string) click to toggle source

Encrypt / decrypt

# File lib/pod4/encrypting.rb, line 243
def crypt(cipher, direction, iv, string)
  return string if use_iv? and iv.nil?
  return string if string.nil? 
  cipher.key = self.class.encryption_key
  cipher.iv = iv if use_iv?

  case direction
    when :encrypt
      answer = string.to_s.empty? ? "" : cipher.update(string.to_s)
      answer << cipher.final
      Base64.strict_encode64(answer)

    when :decrypt
      answer = Base64.strict_decode64(string.to_s)
      cipher.update(answer) + cipher.final
  end

rescue OpenSSL::Cipher::CipherError, ArgumentError
  raise Pod4::Pod4Error, $!
end
get_cipher(direction) click to toggle source

Return the correct OpenSSL Cipher object

# File lib/pod4/encrypting.rb, line 228
def get_cipher(direction)
  cipher = OpenSSL::Cipher.new(use_iv? ? CIPHER_IV : CIPHER_NO_IV)
  case direction
    when :encrypt then cipher.encrypt
    when :decrypt then cipher.decrypt
  end
  cipher

rescue OpenSSL::Cipher::CipherError
  raise Pod4::Pod4Error, $!
end
set_encryption_iv(iv) click to toggle source

Set the iv column on the model, whatever it is

# File lib/pod4/encrypting.rb, line 213
def set_encryption_iv(iv)
  return unless use_iv?
  instance_variable_set( "@#{self.class.encryption_iv_column}".to_sym, iv )
end
use_iv?() click to toggle source

If we have declared an IV column, we can use IV in encryption

# File lib/pod4/encrypting.rb, line 221
def use_iv?
  !self.class.encryption_iv_column.nil?
end