Module: Sequel::Plugins::Vault::ClassMethods

Defined in:
lib/sequel_vault.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#vault_attrsArray<Symbol> (readonly)

Returns array of all attributes to be encrypted.

Returns:

  • (Array<Symbol>)

    array of all attributes to be encrypted



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/sequel_vault.rb', line 22

module ClassMethods
  attr_reader :vault_attrs
  attr_reader :vault_keys

  Plugins.inherited_instance_variables(self, :@vault_attrs => :dup, :@vault_keys => :dup)

  # Setup vault with the given keys for the given attributes.
  #
  # @param [Array<String>] keys to be used
  # @param [Array<Symbol>] attributes that will be encrypted
  def vault_attributes(keys, *attributes)
    raise(Error, 'must provide both keys name and attrs when setting up vault') unless keys && attributes
    @vault_keys = keys
    @vault_attrs = attributes

    self.class.instance_eval do
      attributes.each do |attr|
        define_method("#{attr}_lookup") do |plain|
          digests = keys.map { |key| Sequel.blob(digest(key, plain)) }
          where("#{attr}_digest": digests).first
        end
      end
    end
  end

  # Returns the HMAC digest of plain text.
  #
  # @param [Array<String>] keys to be used
  # @param [String] plain text
  # @return [String] HMAC digest of the plain text
  def digest(keys, plain)
    OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), Array(keys).last, plain)
  end

  # Returns the encrypted version of plain text.
  #
  # @param [Array<String>] keys to be used
  # @param [String] plain text
  # @return [String] encrypted version of the plain text
  def encrypt(keys, plain)
    ::Fernet.generate(keys.last, plain)
  end

  # Returns the decryped version of encrypted text.
  #
  # @param [Array<String>] keys to be used
  # @param [String] cypher text
  # @return [String] plain version of the cypher text
  def decrypt(keys, cypher)
    keys.each do |key|
      verifier = ::Fernet.verifier(key, cypher, enforce_ttl: false)
      next unless verifier.valid?
      return verifier.message
    end
    cypher # Return cypher has it's probably just plain text
  end
end

#vault_keysArray<String> (readonly)

Returns array of all keys to be used.

Returns:

  • (Array<String>)

    array of all keys to be used.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/sequel_vault.rb', line 22

module ClassMethods
  attr_reader :vault_attrs
  attr_reader :vault_keys

  Plugins.inherited_instance_variables(self, :@vault_attrs => :dup, :@vault_keys => :dup)

  # Setup vault with the given keys for the given attributes.
  #
  # @param [Array<String>] keys to be used
  # @param [Array<Symbol>] attributes that will be encrypted
  def vault_attributes(keys, *attributes)
    raise(Error, 'must provide both keys name and attrs when setting up vault') unless keys && attributes
    @vault_keys = keys
    @vault_attrs = attributes

    self.class.instance_eval do
      attributes.each do |attr|
        define_method("#{attr}_lookup") do |plain|
          digests = keys.map { |key| Sequel.blob(digest(key, plain)) }
          where("#{attr}_digest": digests).first
        end
      end
    end
  end

  # Returns the HMAC digest of plain text.
  #
  # @param [Array<String>] keys to be used
  # @param [String] plain text
  # @return [String] HMAC digest of the plain text
  def digest(keys, plain)
    OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), Array(keys).last, plain)
  end

  # Returns the encrypted version of plain text.
  #
  # @param [Array<String>] keys to be used
  # @param [String] plain text
  # @return [String] encrypted version of the plain text
  def encrypt(keys, plain)
    ::Fernet.generate(keys.last, plain)
  end

  # Returns the decryped version of encrypted text.
  #
  # @param [Array<String>] keys to be used
  # @param [String] cypher text
  # @return [String] plain version of the cypher text
  def decrypt(keys, cypher)
    keys.each do |key|
      verifier = ::Fernet.verifier(key, cypher, enforce_ttl: false)
      next unless verifier.valid?
      return verifier.message
    end
    cypher # Return cypher has it's probably just plain text
  end
end

Instance Method Details

#decrypt(keys, cypher) ⇒ String

Returns the decryped version of encrypted text.

Parameters:

  • keys (Array<String>)

    to be used

  • cypher (String)

    text

Returns:

  • (String)

    plain version of the cypher text



70
71
72
73
74
75
76
77
# File 'lib/sequel_vault.rb', line 70

def decrypt(keys, cypher)
  keys.each do |key|
    verifier = ::Fernet.verifier(key, cypher, enforce_ttl: false)
    next unless verifier.valid?
    return verifier.message
  end
  cypher # Return cypher has it's probably just plain text
end

#digest(keys, plain) ⇒ String

Returns the HMAC digest of plain text.

Parameters:

  • keys (Array<String>)

    to be used

  • plain (String)

    text

Returns:

  • (String)

    HMAC digest of the plain text



52
53
54
# File 'lib/sequel_vault.rb', line 52

def digest(keys, plain)
  OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), Array(keys).last, plain)
end

#encrypt(keys, plain) ⇒ String

Returns the encrypted version of plain text.

Parameters:

  • keys (Array<String>)

    to be used

  • plain (String)

    text

Returns:

  • (String)

    encrypted version of the plain text



61
62
63
# File 'lib/sequel_vault.rb', line 61

def encrypt(keys, plain)
  ::Fernet.generate(keys.last, plain)
end

#vault_attributes(keys, *attributes) ⇒ Object

Setup vault with the given keys for the given attributes.

Parameters:

  • keys (Array<String>)

    to be used

  • attributes (Array<Symbol>)

    that will be encrypted

Raises:

  • (Error)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/sequel_vault.rb', line 32

def vault_attributes(keys, *attributes)
  raise(Error, 'must provide both keys name and attrs when setting up vault') unless keys && attributes
  @vault_keys = keys
  @vault_attrs = attributes

  self.class.instance_eval do
    attributes.each do |attr|
      define_method("#{attr}_lookup") do |plain|
        digests = keys.map { |key| Sequel.blob(digest(key, plain)) }
        where("#{attr}_digest": digests).first
      end
    end
  end
end