class SfnParameters::Safe::Ssl

OpenSSL based Safe implementation

Constants

CRYPT_ITER

Maximum computation iteration length

CRYPT_KEY_LENGTH

Default length of generated key

DEFAULT_CIPHER

Default cipher

Public Class Methods

new(*_) click to toggle source

Create OpenSSL backed safe

@param args [Hash] @option :args [String] :cipher name of cipher @option :args [String] :key shared key value @option :args [Integer] :iterations generation interation @option :args [String] :salt value for salting @option :args [Integer] :key_length length of generated key @return [self]

Calls superclass method SfnParameters::Safe::new
# File lib/sfn-parameters/safe/ssl.rb, line 26
def initialize(*_)
  super
  unless arguments[:salt]
    arguments[:salt] = OpenSSL::Random.random_bytes(16)
  end
  unless arguments[:key]
    raise ArgumentError.new "Required `:key` argument unset for `Safe::Ssl`!"
  end
end

Public Instance Methods

lock(value) click to toggle source

Lock a given value for storage

@param value [String] value to lock @return [Hash] locked content in form {:iv, :content}

# File lib/sfn-parameters/safe/ssl.rb, line 40
def lock(value)
  cipher = build(arguments[:salt])
  new_iv = cipher.random_iv
  cipher.iv = new_iv
  result = cipher.update(value) + cipher.final
  Smash.new(
    :iv => Base64.urlsafe_encode64(new_iv),
    :cipher => arguments.fetch(:cipher, DEFAULT_CIPHER),
    :content => Base64.urlsafe_encode64(result),
    :salt => Base64.urlsafe_encode64(arguments[:salt]),
    :sfn_parameters_lock => Bogo::Utility.snake(self.class.name.split("::").last),
  )
end
unlock(value) click to toggle source

Unlock a given value for access

@param value [Hash] content to unlock @option :value [String] :iv initialization vector value @option :value [String] :salt random salt value @option :value [String] :content stored content @return [String]

# File lib/sfn-parameters/safe/ssl.rb, line 61
def unlock(value)
  value = value.to_smash
  [:content, :iv, :salt].each do |key|
    unless value[key]
      raise ArgumentError.new("Missing required information `#{key}`")
    end
  end
  o_cipher = arguments[:cipher]
  arguments[:cipher] = value[:cipher] if value[:cipher]
  cipher = build(
    Base64.urlsafe_decode64(value[:salt]),
    Base64.urlsafe_decode64(value[:iv])
  )
  arguments[:cipher] = o_cipher
  string = Base64.urlsafe_decode64(value[:content])
  cipher.update(string) + cipher.final
end

Protected Instance Methods

build(salt = nil, iv = nil) click to toggle source

Build a new cipher

@param iv [String] initialization vector @param salt [String] random value @return [OpenSSL::Cipher]

# File lib/sfn-parameters/safe/ssl.rb, line 86
def build(salt = nil, iv = nil)
  cipher = OpenSSL::Cipher.new(arguments[:cipher] || DEFAULT_CIPHER)
  iv ? cipher.decrypt : cipher.encrypt
  key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(
    arguments[:key],
    salt,
    arguments.fetch(:iterations, CRYPT_ITER),
    arguments.fetch(:key_length, CRYPT_KEY_LENGTH)
  )
  cipher.iv = iv if iv
  cipher.key = key
  cipher
end