Sha256: a989af601f648cc1511f0ed0b720b674301dddb358b35b831113f4f42e1458fe

Contents?: true

Size: 1.84 KB

Versions: 10

Compression:

Stored size: 1.84 KB

Contents

require 'base64'

module AttrVault
  module Cryptor

    def self.encrypt(value, key)
      return value if value.nil? || value.empty?

      secret = AttrVault::Secret.new(key)
      encrypted_message, iv = Encryption.encrypt(key: secret.encryption_key,
                                                 message: value)
      encrypted_payload = iv + encrypted_message
      mac = Encryption.hmac_digest(secret.signing_key, encrypted_payload)

      Sequel.blob(mac + encrypted_payload)
    end

    def self.decrypt(encrypted, key)
      return encrypted if encrypted.nil? || encrypted.empty?

      secret = AttrVault::Secret.new(key)
      hmac, encrypted_payload = encrypted[0...32], encrypted[32..-1]
      expected_hmac = Encryption.hmac_digest(secret.signing_key, encrypted_payload)

      unless verify_signature(expected_hmac, hmac)
        raise InvalidCiphertext,
          "Expected hmac #{Base64.encode64(expected_hmac)} for this value; " +
          "got #{Base64.encode64(hmac)}"
      end

      iv, encrypted_message = encrypted_payload[0...16], encrypted_payload[16..-1]
      block_size = Encryption::AES_BLOCK_SIZE
      unless (encrypted_message.size % block_size).zero?
        raise InvalidCiphertext,
          "Expected message size to be multiple of #{block_size}; got #{encrypted_message.size}"
      end

      begin
        Encryption.decrypt(key: secret.encryption_key,
                           ciphertext: encrypted_message,
                           iv: iv)
      rescue OpenSSL::Cipher::CipherError
        raise InvalidCiphertext, "Could not decrypt field"
      end
    end

    private

    def self.verify_signature(expected, actual)
      expected_bytes = expected.bytes.to_a
      actual_bytes = actual.bytes.to_a
      actual_bytes.inject(0) do |accum, byte|
        accum |= byte ^ expected_bytes.shift
      end.zero?
    end
  end
end

Version data entries

10 entries across 10 versions & 1 rubygems

Version Path
attr_vault-2.1.2 lib/attr_vault/cryptor.rb
attr_vault-2.1.1 lib/attr_vault/cryptor.rb
attr_vault-2.1.0 lib/attr_vault/cryptor.rb
attr_vault-2.0.0 lib/attr_vault/cryptor.rb
attr_vault-1.0.1 lib/attr_vault/cryptor.rb
attr_vault-1.0.0 lib/attr_vault/cryptor.rb
attr_vault-0.2.1 lib/attr_vault/cryptor.rb
attr_vault-0.2.0 lib/attr_vault/cryptor.rb
attr_vault-0.1.2 lib/attr_vault/cryptor.rb
attr_vault-0.1.1 lib/attr_vault/cryptor.rb