Module: Tanker::Crypto

Defined in:
lib/tanker/crypto.rb

Defined Under Namespace

Classes: InvalidSignature

Constant Summary collapse

HASH_MIN_SIZE =

16

RbNaCl::Hash::Blake2b::BYTES_MIN
BLOCK_HASH_SIZE =
32

Class Method Summary collapse

Class Method Details

.generate_encryption_keypairObject



59
60
61
62
63
64
65
66
# File 'lib/tanker/crypto.rb', line 59

def self.generate_encryption_keypair
  encryption_key = RbNaCl::PrivateKey.generate

  {
    private_key: encryption_key.to_bytes,
    public_key: encryption_key.public_key.to_bytes
  }
end

.generate_signature_keypairObject



50
51
52
53
54
55
56
57
# File 'lib/tanker/crypto.rb', line 50

def self.generate_signature_keypair
  signing_key = RbNaCl::SigningKey.generate

  {
    private_key: signing_key.keypair_bytes,
    public_key: signing_key.verify_key.to_bytes
  }
end

.generichash(input, size) ⇒ Object



12
13
14
15
# File 'lib/tanker/crypto.rb', line 12

def self.generichash(input, size)
  binary_input = input.dup.force_encoding(Encoding::ASCII_8BIT)
  RbNaCl::Hash.blake2b(binary_input, digest_size: size)
end

.hash_user_id(app_id, user_id) ⇒ Object



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

def self.hash_user_id(app_id, user_id)
  binary_user_id = user_id.dup.force_encoding(Encoding::ASCII_8BIT)
  Crypto.generichash(binary_user_id + app_id, BLOCK_HASH_SIZE)
end

.hashed_provisional_email(email) ⇒ Object



22
23
24
# File 'lib/tanker/crypto.rb', line 22

def self.hashed_provisional_email(email)
  Base64.strict_encode64(Crypto.generichash(email, BLOCK_HASH_SIZE))
end

.hashed_provisional_value(value, private_signature_key) ⇒ Object



26
27
28
29
# File 'lib/tanker/crypto.rb', line 26

def self.hashed_provisional_value(value, private_signature_key)
  secret_salt = Crypto.generichash(Base64.strict_decode64(private_signature_key), BLOCK_HASH_SIZE)
  Base64.strict_encode64(Crypto.generichash(secret_salt + value, BLOCK_HASH_SIZE))
end

.random_bytes(size) ⇒ Object



68
69
70
# File 'lib/tanker/crypto.rb', line 68

def self.random_bytes(size)
  SecureRandom.bytes(size)
end

.sign_detached(message, private_signature_key) ⇒ Object

We need this static method since a RbNaCl::SigningKey instance can’t be directly initialized with a given private_signature_key



33
34
35
36
37
38
39
40
41
# File 'lib/tanker/crypto.rb', line 33

def self.sign_detached(message, private_signature_key)
  signature_bytes = RbNaCl::SigningKey.signature_bytes
  buffer = RbNaCl::Util.prepend_zeros(signature_bytes, message)
  buffer_len = RbNaCl::Util.zeros(8) # 8 bytes for an int64 (FFI::Type::LONG_LONG.size)

  RbNaCl::SigningKey.sign_ed25519(buffer, buffer_len, message, message.bytesize, private_signature_key)

  buffer[0, signature_bytes]
end

.verify_sign_detached(message, signature, public_signature_key) ⇒ Object



43
44
45
46
47
48
# File 'lib/tanker/crypto.rb', line 43

def self.verify_sign_detached(message, signature, public_signature_key)
  verify_key = RbNaCl::VerifyKey.new(public_signature_key)
  verify_key.verify(signature, message)
rescue RbNaCl::BadSignatureError
  raise InvalidSignature.new
end