require 'rbnacl' require 'base64' class Example attr_reader :secret_box, :index_key def initialize key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes) @index_key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes) @secret_box = RbNaCl::SecretBox.new(key) end def encrypt_ssn(ssn) nonce = RbNaCl::Random.random_bytes(secret_box.nonce_bytes) ciphertext = secret_box.encrypt(nonce, ssn) nonce.concat(ciphertext).unpack('H*').first end def decrypt_ssn(ciphertext) ciphertext = [ciphertext].pack('H*') nonce = ciphertext[0..secret_box.nonce_bytes - 1] secret_box.decrypt(nonce, ciphertext[secret_box.nonce_bytes..-1]) end def get_ssn_blind_index(ssn) salt = RbNaCl::Hash.blake2b(index_key, digest_size: 16) digest = RbNaCl::PasswordHash.argon2( ssn, salt, RbNaCl::PasswordHash::Argon2::OPSLIMIT_INTERACTIVE, RbNaCl::PasswordHash::Argon2::MEMLIMIT_INTERACTIVE, 33 ) digest.unpack('H*').first end end