Class: Quonfig::Encryption

Inherits:
Object
  • Object
show all
Defined in:
lib/quonfig/encryption.rb

Constant Summary collapse

CIPHER_TYPE =

32/12

"aes-256-gcm"
SEPARATOR =
"--"
AUTH_TAG_LENGTH =
16

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key_string_hex) ⇒ Encryption

Returns a new instance of Encryption.



18
19
20
# File 'lib/quonfig/encryption.rb', line 18

def initialize(key_string_hex)
  @key = [key_string_hex].pack("H*")
end

Class Method Details

.generate_new_hex_keyObject

Hexadecimal format ensures that generated keys are representable with plain text

To convert back to the original string with the desired length:

[ value ].pack("H*")


14
15
16
# File 'lib/quonfig/encryption.rb', line 14

def self.generate_new_hex_key
  generate_random_key.unpack("H*")[0]
end

.generate_random_keyObject



66
67
68
# File 'lib/quonfig/encryption.rb', line 66

def self.generate_random_key
  SecureRandom.random_bytes(key_length)
end

.key_lengthObject



70
71
72
# File 'lib/quonfig/encryption.rb', line 70

def self.key_length
  OpenSSL::Cipher.new(CIPHER_TYPE).key_len
end

Instance Method Details

#decrypt(encrypted_string) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/quonfig/encryption.rb', line 41

def decrypt(encrypted_string)
  encrypted_data, iv, auth_tag = encrypted_string.split(SEPARATOR).map { |p| [p].pack("H*") }
  
  # Currently the OpenSSL bindings do not raise an error if auth_tag is
  # truncated, which would allow an attacker to easily forge it. See
  # https://github.com/ruby/openssl/issues/63
  if auth_tag.bytesize != AUTH_TAG_LENGTH
    raise "truncated auth_tag"
  end

  cipher = OpenSSL::Cipher.new(CIPHER_TYPE)
  cipher.decrypt
  cipher.key = @key
  cipher.iv = iv
  
  cipher.auth_tag = auth_tag
 
  # and decrypt it
  decrypted = cipher.update(encrypted_data)
  decrypted << cipher.final
  decrypted
end

#encrypt(clear_text) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/quonfig/encryption.rb', line 22

def encrypt(clear_text)
  cipher = OpenSSL::Cipher.new(CIPHER_TYPE)
  cipher.encrypt
  iv = cipher.random_iv

  # load them into the cipher
  cipher.key = @key
  cipher.iv = iv
  cipher.auth_data = ""

  # encrypt the message
  encrypted = cipher.update(clear_text)
  encrypted << cipher.final
  tag = cipher.auth_tag
  
  # pack and join
  [encrypted, iv, tag].map { |p| p.unpack("H*")[0] }.join(SEPARATOR)
end