Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
hmac.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
11#include <algorithm>
12#include <array>
13#include <cstdint>
14#include <string>
15#include <vector>
16
17namespace bb::crypto {
28template <typename Hash, typename MessageContainer, typename KeyContainer>
29std::array<uint8_t, Hash::OUTPUT_SIZE> hmac(const MessageContainer& message, const KeyContainer& key)
30{
31 constexpr size_t B = Hash::BLOCK_SIZE;
32 // ensures truncated_key fits into k_prime
33 static_assert(Hash::OUTPUT_SIZE <= B);
34 constexpr uint8_t IPAD_CONST = 0x36;
35 constexpr uint8_t OPAD_CONST = 0x5c;
38 ipad.fill(IPAD_CONST);
39 opad.fill(OPAD_CONST);
40
41 // initialize k_prime to 0x00,...,0x00
42 // copy key or truncated key to start.
43 // TODO: securely erase `k_prime`
44 std::array<uint8_t, B> k_prime{};
45 if (key.size() > B) {
46 const auto truncated_key = Hash::hash(key);
47 std::copy(truncated_key.begin(), truncated_key.end(), k_prime.begin());
48 } else {
49 std::copy(key.begin(), key.end(), k_prime.begin());
50 }
51
52 // TODO: securely erase `h1`
54 for (size_t i = 0; i < B; ++i) {
55 h1[i] = k_prime[i] ^ opad[i];
56 }
57
58 // TODO: securely erase `h2`
60 for (size_t i = 0; i < B; ++i) {
61 h2[i] = k_prime[i] ^ ipad[i];
62 }
63
64 // TODO: securely erase copy of `h2` in `message_buffer`,
65 // ensure `message_buffer` is not re-allocated
66 std::vector<uint8_t> message_buffer;
67 std::copy(h2.begin(), h2.end(), std::back_inserter(message_buffer));
68 std::copy(message.begin(), message.end(), std::back_inserter(message_buffer));
69
70 const auto h3 = Hash::hash(message_buffer);
71
72 // TODO: securely erase copy of `h1` in `hmac_buffer`,
73 // ensure `hmac_buffer` is not re-allocated
74 std::vector<uint8_t> hmac_buffer;
75 std::copy(h1.begin(), h1.end(), std::back_inserter(hmac_buffer));
76 std::copy(h3.begin(), h3.end(), std::back_inserter(hmac_buffer));
77
78 const auto hmac_key = Hash::hash(hmac_buffer);
79
81 std::copy(hmac_key.begin(), hmac_key.end(), result.begin());
82 return result;
83}
84
101template <typename Hash, typename Fr, typename MessageContainer, typename KeyContainer>
102Fr get_unbiased_field_from_hmac(const MessageContainer& message, const KeyContainer& key)
103 requires(Hash::OUTPUT_SIZE == 32)
104{
105 // Strong assumption that works for now with our suite of Hashers
106 static_assert(Hash::BLOCK_SIZE > Hash::OUTPUT_SIZE);
107 constexpr size_t DOMAIN_SEPARATOR_SIZE = Hash::BLOCK_SIZE - Hash::OUTPUT_SIZE;
108
109 // Domain separators whose size ensures we hash a block of the exact size expected by
110 // the Hasher.
111 constexpr std::array<uint8_t, DOMAIN_SEPARATOR_SIZE> KLO_DOMAIN_SEPARATOR{ 0x0 };
112 constexpr std::array<uint8_t, DOMAIN_SEPARATOR_SIZE> KHI_DOMAIN_SEPARATOR{ 0x1 };
113
114 auto input = hmac<Hash, MessageContainer, KeyContainer>(message, key);
115
116 // klo = H(00...0 || input)
117 std::vector<uint8_t> lo_buffer(KLO_DOMAIN_SEPARATOR.begin(), KLO_DOMAIN_SEPARATOR.end());
118 std::copy(input.begin(), input.end(), std::back_inserter(lo_buffer));
119 auto klo = Hash::hash(lo_buffer);
120
121 // khi = H(10...0 || input)
122 std::vector<uint8_t> hi_buffer(KHI_DOMAIN_SEPARATOR.begin(), KHI_DOMAIN_SEPARATOR.end());
123 std::copy(input.begin(), input.end(), std::back_inserter(hi_buffer));
124 auto khi = Hash::hash(hi_buffer);
125
126 // full_buffer = khi || klo
127 std::vector<uint8_t> full_buffer(khi.begin(), khi.end());
128 std::copy(klo.begin(), klo.end(), std::back_inserter(full_buffer));
129
130 auto field_as_u512 = from_buffer<numeric::uint512_t>(full_buffer);
131
132 Fr result((field_as_u512 % Fr::modulus).lo);
133 return result;
134}
135} // namespace bb::crypto
Fr get_unbiased_field_from_hmac(const MessageContainer &message, const KeyContainer &key)
Takes a size-HASH_OUTPUT buffer from HMAC and converts into a field element.
Definition hmac.hpp:102
std::array< uint8_t, Hash::OUTPUT_SIZE > hmac(const MessageContainer &message, const KeyContainer &key)
Compute an HMAC given a secret key and a message.
Definition hmac.hpp:29
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr uint256_t modulus