32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
# File 'lib/zwiebel/utilities.rb', line 32
def self.decrypt_layer(encrypted_data:, constant:, revision_counter:, subcredential:, blinded_key:)
cleaned_data = encrypted_data.gsub("-----BEGIN MESSAGE-----\n", "").gsub("\n-----END MESSAGE-----", "")
encrypted = Base64.decode64(cleaned_data)
if encrypted.length < SALT_LENGTH + MAC_LENGTH
raise ContentLengthError, "encrypted data should be at least #{SALT_LENGTH + MAC_LENGTH} bytes"
end
salt = encrypted.byteslice(0, SALT_LENGTH)
ciphertext = encrypted.byteslice(SALT_LENGTH..-(MAC_LENGTH + 1))
expected_mac = encrypted.byteslice(-MAC_LENGTH..-1)
key_digest = blinded_key + subcredential + [revision_counter].pack("Q>") + salt + constant
bit_length = (S_KEY_LENGTH + S_IV_LENGTH + MAC_LENGTH) * 8
keys = Shake256.new(bit_length: bit_length, message_type: "hex").hexdigest(key_digest.unpack1("H*"))
keys = [keys].pack("H*")
secret_key = keys.byteslice(0, S_KEY_LENGTH)
secret_iv = keys.byteslice(S_KEY_LENGTH, S_IV_LENGTH)
mac_key = keys.byteslice(S_KEY_LENGTH + S_IV_LENGTH, MAC_LENGTH)
mac_prefix = [mac_key.length].pack("Q>") + mac_key + [salt.length].pack("Q>") + salt
mac_for = OpenSSL::Digest.digest("SHA3-256", mac_prefix + ciphertext)
if expected_mac != mac_for
raise DataError, "incorrect message authentication code"
end
decipher = OpenSSL::Cipher.new("aes-256-ctr")
decipher.decrypt
decipher.key = secret_key
decipher.iv = secret_iv
decipher.update(ciphertext) + decipher.final
end
|