module Configliere::Crypter

Encrypt and decrypt values in configliere stores

Constants

CIPHER_TYPE

Public Class Methods

check_platform_can_encrypt!() click to toggle source
# File lib/configliere/crypter.rb, line 24
def self.check_platform_can_encrypt!
  return true unless PLATFORM_ENCRYPTION_ERROR
  raise PLATFORM_ENCRYPTION_ERROR.class, "Encryption broken on this platform: #{PLATFORM_ENCRYPTION_ERROR}"
end
decrypt(enc_ciphertext, encrypt_pass, options={}) click to toggle source

Decrypt the given string, using the key and iv supplied

@param ciphertext the text to decrypt, probably produced with Crypter#decrypt @param [String] encrypt_pass secret passphrase to decrypt with @return [String] the decrypted plaintext

# File lib/configliere/crypter.rb, line 53
def self.decrypt enc_ciphertext, encrypt_pass, options={}
  iv_and_ciphertext = Base64.decode64(enc_ciphertext)
  cipher    = new_cipher :decrypt, encrypt_pass, options
  cipher.iv, ciphertext = separate_iv_and_ciphertext(cipher, iv_and_ciphertext)
  plaintext = cipher.update(ciphertext)
  plaintext << cipher.final
  plaintext
end
encrypt(plaintext, encrypt_pass, options={}) click to toggle source

Encrypt the given string

@param plaintext the text to encrypt @param [String] encrypt_pass secret passphrase to encrypt with @return [String] encrypted text, suitable for deciphering with Crypter#decrypt

# File lib/configliere/crypter.rb, line 36
def self.encrypt plaintext, encrypt_pass, options={}
  # The cipher's IV (Initialization Vector) is prepended (unencrypted) to
  # the ciphertext, which as far as I can tell is safe for our purposes:
  # http://www.ciphersbyritter.com/NEWS6/CBCIV.HTM
  cipher     = new_cipher :encrypt, encrypt_pass, options
  cipher.iv  = iv = cipher.random_iv
  ciphertext = cipher.update(plaintext)
  ciphertext << cipher.final
  Base64.encode64(combine_iv_and_ciphertext(iv, ciphertext))
end

Protected Class Methods

combine_iv_and_ciphertext(iv, message) click to toggle source

prepend the initialization vector to the encoded message

# File lib/configliere/crypter.rb, line 77
def self.combine_iv_and_ciphertext iv, message
  message.force_encoding("BINARY") if message.respond_to?(:force_encoding)
  iv.force_encoding("BINARY")      if iv.respond_to?(:force_encoding)
  iv + message
end
encrypt_key(encrypt_pass, options={}) click to toggle source

Convert the encrypt_pass passphrase into the key used for encryption

# File lib/configliere/crypter.rb, line 89
def self.encrypt_key encrypt_pass, options={}
  encrypt_pass = encrypt_pass.to_s
  raise 'Missing encryption password!' if encrypt_pass.empty?
  # this provides the required 256 bits of key for the aes-256-cbc cipher
  Digest::SHA256.digest(encrypt_pass)
end
new_cipher(direction, encrypt_pass, options={}) click to toggle source

Create a new cipher machine, with its dials set in the given direction

@param [:encrypt, :decrypt] direction whether to encrypt or decrypt @param [String] encrypt_pass secret passphrase to decrypt with

# File lib/configliere/crypter.rb, line 68
def self.new_cipher direction, encrypt_pass, options={}
  check_platform_can_encrypt!
  cipher     = OpenSSL::Cipher::Cipher.new(CIPHER_TYPE)
  case direction when :encrypt then cipher.encrypt when :decrypt then cipher.decrypt else raise "Bad cipher direction #{direction}" end
  cipher.key = encrypt_key(encrypt_pass, options)
  cipher
end
separate_iv_and_ciphertext(cipher, iv_and_ciphertext) click to toggle source

pull the initialization vector from the front of the encoded message

# File lib/configliere/crypter.rb, line 83
def self.separate_iv_and_ciphertext cipher, iv_and_ciphertext
  idx = cipher.iv_len
  [ iv_and_ciphertext[0..(idx-1)], iv_and_ciphertext[idx..-1] ]
end