Class: Lockbox::AES_GCM

Inherits:
Object
  • Object
show all
Defined in:
lib/lockbox/aes_gcm.rb

Instance Method Summary collapse

Constructor Details

#initialize(key) ⇒ AES_GCM

Returns a new instance of AES_GCM.

Raises:

  • (ArgumentError)


3
4
5
6
7
8
# File 'lib/lockbox/aes_gcm.rb', line 3

def initialize(key)
  raise ArgumentError, "Key must be 32 bytes" unless key && key.bytesize == 32
  raise ArgumentError, "Key must be binary" unless key.encoding == Encoding::BINARY

  @key = key
end

Instance Method Details

#decrypt(nonce, ciphertext, associated_data) ⇒ Object



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
# File 'lib/lockbox/aes_gcm.rb', line 28

def decrypt(nonce, ciphertext, associated_data)
  auth_tag, ciphertext = extract_auth_tag(ciphertext.to_s)

  fail_decryption if nonce.to_s.bytesize != nonce_bytes
  fail_decryption if auth_tag.to_s.bytesize != auth_tag_bytes

  cipher = OpenSSL::Cipher.new("aes-256-gcm")
  # do not change order of operations
  cipher.decrypt
  cipher.key = @key
  cipher.iv = nonce
  cipher.auth_tag = auth_tag
  # From Ruby 2.5.3 OpenSSL::Cipher docs:
  # If no associated data shall be used, this method must still be called with a value of ""
  # When decrypting, set it only after calling #decrypt, #key=, #iv= and #auth_tag= first.
  cipher.auth_data = associated_data || ""

  begin
    message = String.new
    message << cipher.update(ciphertext) unless ciphertext.to_s.empty?
    message << cipher.final
    message
  rescue OpenSSL::Cipher::CipherError
    fail_decryption
  end
end

#encrypt(nonce, message, associated_data) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/lockbox/aes_gcm.rb', line 10

def encrypt(nonce, message, associated_data)
  cipher = OpenSSL::Cipher.new("aes-256-gcm")
  # do not change order of operations
  cipher.encrypt
  cipher.key = @key
  cipher.iv = nonce
  # From Ruby 2.5.3 OpenSSL::Cipher docs:
  # If no associated data shall be used, this method must still be called with a value of ""
  # In encryption mode, it must be set after calling #encrypt and setting #key= and #iv=
  cipher.auth_data = associated_data || ""

  ciphertext = String.new
  ciphertext << cipher.update(message) unless message.empty?
  ciphertext << cipher.final
  ciphertext << cipher.auth_tag
  ciphertext
end

#inspectObject

protect key



60
61
62
# File 'lib/lockbox/aes_gcm.rb', line 60

def inspect
  to_s
end

#nonce_bytesObject



55
56
57
# File 'lib/lockbox/aes_gcm.rb', line 55

def nonce_bytes
  12
end