Module: SshTresor::Crypto

Defined in:
lib/ssh_tresor/crypto.rb

Constant Summary collapse

CHALLENGE_SIZE =
32
MASTER_KEY_SIZE =
32
NONCE_SIZE =
12
AUTH_TAG_SIZE =
16

Class Method Summary collapse

Class Method Details

.decrypt(key, nonce, ciphertext_with_tag) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ssh_tresor/crypto.rb', line 52

def decrypt(key, nonce, ciphertext_with_tag)
  raise DecryptionError, "ciphertext too short" if ciphertext_with_tag.bytesize < AUTH_TAG_SIZE

  ciphertext = ciphertext_with_tag.byteslice(0, ciphertext_with_tag.bytesize - AUTH_TAG_SIZE)
  tag = ciphertext_with_tag.byteslice(-AUTH_TAG_SIZE, AUTH_TAG_SIZE)

  cipher = OpenSSL::Cipher.new("aes-256-gcm")
  cipher.decrypt
  cipher.key = key
  cipher.iv = nonce
  cipher.auth_tag = tag
  cipher.auth_data = "".b

  cipher.update(ciphertext) + cipher.final
rescue OpenSSL::Cipher::CipherError
  raise DecryptionError, "authentication failed - wrong key or corrupted data"
end

.derive_key(signature) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/ssh_tresor/crypto.rb', line 29

def derive_key(signature)
  OpenSSL::KDF.hkdf(
    signature,
    salt: "ssh-tresor-v3",
    info: "slot-key-derivation",
    length: 32,
    hash: "SHA256"
  )
end

.encrypt(key, nonce, plaintext) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ssh_tresor/crypto.rb', line 39

def encrypt(key, nonce, plaintext)
  cipher = OpenSSL::Cipher.new("aes-256-gcm")
  cipher.encrypt
  cipher.key = key
  cipher.iv = nonce
  cipher.auth_data = "".b

  ciphertext = cipher.update(plaintext.b) + cipher.final
  ciphertext + cipher.auth_tag
rescue OpenSSL::Cipher::CipherError => e
  raise Error, "Encryption failed: AES-GCM encryption failed: #{e.message}"
end

.random_challengeObject



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

def random_challenge
  SecureRandom.random_bytes(CHALLENGE_SIZE)
end

.random_master_keyObject



21
22
23
# File 'lib/ssh_tresor/crypto.rb', line 21

def random_master_key
  SecureRandom.random_bytes(MASTER_KEY_SIZE)
end

.random_nonceObject



25
26
27
# File 'lib/ssh_tresor/crypto.rb', line 25

def random_nonce
  SecureRandom.random_bytes(NONCE_SIZE)
end