Class: Teak::AttrEncrypted::Encryptor

Inherits:
Object
  • Object
show all
Defined in:
lib/teak/attr_encrypted/encryptor.rb

Constant Summary collapse

CIPHER =
'aes-256-gcm'
CURRENT_VERSION =
'1'
IV =
'v'
TAG =
't'
KEY =
'k'
PACKET =
'p'
KEK_ID =
'i'

Instance Method Summary collapse

Constructor Details

#initialize(kek_provider) ⇒ Encryptor

Returns a new instance of Encryptor.



20
21
22
# File 'lib/teak/attr_encrypted/encryptor.rb', line 20

def initialize(kek_provider)
  @kek_provider = kek_provider
end

Instance Method Details

#decrypt(envelope, encryption_context) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/teak/attr_encrypted/encryptor.rb', line 44

def decrypt(envelope, encryption_context)
  version = envelope[0]
  case version
  when '1'
    structure = MessagePack.unpack(Base64.strict_decode64(envelope[1..-1]))
    key_info = @kek_provider.decrypt_data_key(structure[KEY], encryption_context)

    cipher = OpenSSL::Cipher.new(CIPHER).decrypt
    cipher.key = key_info.plaintext
    cipher.iv = structure[IV]
    cipher.auth_tag = structure[TAG]
    cipher.auth_data = ''

    cipher.update(structure[PACKET]) + cipher.final
  else
    raise Teak::AttrEncrypted::Error.new("Unrecognized envelope version #{version}")
  end
end

#encrypt(plaintext, encryption_context) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/teak/attr_encrypted/encryptor.rb', line 24

def encrypt(plaintext, encryption_context)
  key_info = @kek_provider.request_data_key(encryption_context)

  cipher = OpenSSL::Cipher.new(CIPHER).encrypt
  cipher.key = key_info.plaintext
  iv = cipher.random_iv
  cipher.auth_data = ''

  encrypted = cipher.update(plaintext) + cipher.final
  "#{CURRENT_VERSION}#{Base64.strict_encode64(
    MessagePack.pack({
      KEK_ID => @kek_provider.id,
      IV => iv,
      TAG => cipher.auth_tag,
      KEY => key_info.ciphertext_blob,
      PACKET => encrypted
    })
  )}"
end