Class: Secretbox

Inherits:
Object
  • Object
show all
Defined in:
lib/secretbox.rb,
lib/secretbox/version.rb

Defined Under Namespace

Classes: DecryptionError, InvalidKeyError

Constant Summary collapse

ALGORITHM =
'aes-256-gcm'.freeze
KEY_SIZE =
32
IV_SIZE =
12
TAG_SIZE =
16
VERSION =
'1.0.0'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key) ⇒ Secretbox

Returns a new instance of Secretbox.

Raises:



21
22
23
24
25
# File 'lib/secretbox.rb', line 21

def initialize(key)
  validate_string! key, :key
  @key = decode_base64! key, :key, error: InvalidKeyError
  raise InvalidKeyError, "key must be #{KEY_SIZE} bytes" unless @key.bytesize == KEY_SIZE
end

Class Method Details

.generate_keyObject



17
18
19
# File 'lib/secretbox.rb', line 17

def self.generate_key
  Base64.strict_encode64(SecureRandom.random_bytes(KEY_SIZE))
end

Instance Method Details

#decrypt(ciphertext, auth_data: '') ⇒ Object



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

def decrypt(ciphertext, auth_data: '')
  validate_string! ciphertext, :ciphertext
  validate_string! auth_data,  :auth_data

  raw       = decode_base64! ciphertext, :ciphertext
  iv        = raw[0, IV_SIZE]
  auth_tag  = raw[IV_SIZE, TAG_SIZE]
  encrypted = raw[(IV_SIZE + TAG_SIZE)..-1]

  cipher = OpenSSL::Cipher.new(ALGORITHM).tap(&:decrypt)
  cipher.key       = key
  cipher.iv        = iv
  cipher.auth_tag  = auth_tag
  cipher.auth_data = auth_data

  cipher.update(encrypted) + cipher.final
rescue OpenSSL::Cipher::CipherError => e
  raise DecryptionError, e.message
end

#encrypt(plaintext, auth_data: '') ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/secretbox.rb', line 27

def encrypt(plaintext, auth_data: '')
  validate_string! plaintext, :plaintext
  validate_string! auth_data, :auth_data

  cipher = OpenSSL::Cipher.new(ALGORITHM).tap(&:encrypt)
  iv     = cipher.random_iv
  cipher.key       = key
  cipher.auth_data = auth_data

  encrypted = cipher.update(plaintext) + cipher.final

  Base64.strict_encode64(iv + cipher.auth_tag + encrypted)
end