emancu/ork-encryption

View on GitHub
lib/ork/cipher.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'openssl'

module Ork::Encryption

  # Implements a simple object that can either
  # encrypt or decrypt arbitrary data.
  #
  # Example:
  #   cipher = Ork::Encryption::Cipher.new config_hash
  #   cipher.encrypt stuff
  #   cipher.decrypt stuff
  #
  class Cipher

    # Creates a cipher that is prepared to encrypt/decrypt a blob.
    # @param [Hash] config the key/cipher/iv needed to initialize OpenSSL
    #
    def initialize(config = {})
      Cipher.validate_config @config = config
      @cipher = OpenSSL::Cipher.new @config[:cipher]
    end

    # Validates the configuration has all the required values to
    # encrypt and decrypt an object
    #
    # Note: if the configuration is invalid, an
    # `Ork::Encryption::MissingConfig` error is raised.
    #
    def self.validate_config(config)
      if config.nil? || ([:cipher, :key] - config.keys).any?
        raise MissingConfig,
          'Make sure to provide the full configuration to Ork::Encryption. ' +
          'Use Ork::Encryption.init(config_hash) to set the configuration ' +
          'or assert that Ork::Encryption::Cipher.new receives a non empty' +
          ' hash with :cipher and :key values.'
      end
    end

    def random_iv!
      self.iv = @cipher.random_iv
    end

    def iv=(iv)
      @config[:iv] = iv
    end

    # Encrypt stuff.
    # @param [Object] blob the data to encrypt
    def encrypt(blob)
      initialize_cipher_for :encrypt
      "#{@cipher.update blob}#{@cipher.final}"
    end

    # Decrypt stuff.
    # @param [Object] blob the encrypted data to decrypt
    def decrypt(blob)
      initialize_cipher_for :decrypt
      "#{@cipher.update blob}#{@cipher.final}"
    end

    private

    # This sets the mode so OpenSSL knows to encrypt or decrypt, etc.
    # @param [Symbol] mode either :encrypt or :decrypt
    def initialize_cipher_for(mode)
      @cipher.send mode
      @cipher.key = @config[:key]
      @cipher.iv  = @config[:iv]
    end

  end
end