Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
sha256.test.cpp
Go to the documentation of this file.
1#include "sha256.hpp"
7
8using namespace bb;
9using namespace bb::stdlib;
10
11namespace {
13}
14
18
29TEST(stdlib_sha256, test_sha256_block_NIST_vector_one)
30{
31 auto builder = Builder();
32
33 // SHA-256 initial hash values (FIPS 180-4 section 5.3.3)
34 constexpr std::array<uint32_t, 8> H_INIT = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
35 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
36
37 // Manually padded block for "abc" (FIPS 180-4 section 5.1.1)
38 // Message "abc" = 0x616263
39 // Pad: append 1 bit, then zeros, then 64-bit length
40 // Block: 0x61626380 00000000 ... 00000000 00000018
41 constexpr std::array<uint32_t, 16> PADDED_BLOCK = {
42 0x61626380, // "abc" + padding bit
43 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
44 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
45 0x00000018 // length in bits (24)
46 };
47
48 // Expected output: SHA-256("abc") from NIST
49 constexpr std::array<uint32_t, 8> EXPECTED = { 0xba7816bf, 0x8f01cfea, 0x414140de, 0x5dae2223,
50 0xb00361a3, 0x96177a9c, 0xb410ff61, 0xf20015ad };
51
52 // Verify native implementation first
53 auto native_output = crypto::sha256_block(H_INIT, PADDED_BLOCK);
54 for (size_t i = 0; i < 8; i++) {
55 EXPECT_EQ(native_output[i], EXPECTED[i]) << "Native mismatch at index " << i;
56 }
57
58 // Create circuit witnesses
60 for (size_t i = 0; i < 8; i++) {
61 h_init[i] = witness_ct(&builder, H_INIT[i]);
62 }
63
65 for (size_t i = 0; i < 16; i++) {
66 block[i] = witness_ct(&builder, PADDED_BLOCK[i]);
67 }
68
69 // Run circuit compression
70 auto circuit_output = SHA256<Builder>::sha256_block(h_init, block);
71
72 // Verify circuit correctness
73 EXPECT_TRUE(CircuitChecker::check(builder));
74
75 // Compare outputs
76 for (size_t i = 0; i < 8; i++) {
77 uint32_t circuit_val = static_cast<uint32_t>(uint256_t(circuit_output[i].get_value()));
78 EXPECT_EQ(circuit_val, EXPECTED[i]) << "Circuit mismatch at index " << i;
79 }
80
81 info("sha256_block num gates = ", builder.get_num_finalized_gates_inefficient());
82}
83
94TEST(stdlib_sha256, test_sha256_block_NIST_vector_two)
95{
96 auto builder = Builder();
97
98 // SHA-256 initial hash values
99 constexpr std::array<uint32_t, 8> H_INIT = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
100 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
101
102 // First block: first 64 bytes of padded message
103 // "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" = 56 bytes
104 // After padding bit, need second block for length
105 constexpr std::array<uint32_t, 16> BLOCK_1 = {
106 0x61626364, 0x62636465, 0x63646566, 0x64656667, // "abcd" "bcde" "cdef" "defg"
107 0x65666768, 0x66676869, 0x6768696a, 0x68696a6b, // "efgh" "fghi" "ghij" "hijk"
108 0x696a6b6c, 0x6a6b6c6d, 0x6b6c6d6e, 0x6c6d6e6f, // "ijkl" "jklm" "klmn" "lmno"
109 0x6d6e6f70, 0x6e6f7071, 0x80000000, 0x00000000 // "mnop" "nopq" + padding bit
110 };
111
112 // Second block: zeros + 64-bit length (448 bits = 0x1c0)
113 constexpr std::array<uint32_t, 16> BLOCK_2 = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
114 0x00000000, 0x00000000, 0x00000000, 0x00000000,
115 0x00000000, 0x00000000, 0x00000000, 0x00000000,
116 0x00000000, 0x00000000, 0x00000000, 0x000001c0 };
117
118 // Expected output from NIST
119 constexpr std::array<uint32_t, 8> EXPECTED = { 0x248d6a61, 0xd20638b8, 0xe5c02693, 0x0c3e6039,
120 0xa33ce459, 0x64ff2167, 0xf6ecedd4, 0x19db06c1 };
121
122 // Verify native implementation
123 auto h_after_block1 = crypto::sha256_block(H_INIT, BLOCK_1);
124 auto native_output = crypto::sha256_block(h_after_block1, BLOCK_2);
125 for (size_t i = 0; i < 8; i++) {
126 EXPECT_EQ(native_output[i], EXPECTED[i]) << "Native mismatch at index " << i;
127 }
128
129 // Circuit: first block
131 for (size_t i = 0; i < 8; i++) {
132 h_init[i] = witness_ct(&builder, H_INIT[i]);
133 }
134
136 for (size_t i = 0; i < 16; i++) {
137 block1[i] = witness_ct(&builder, BLOCK_1[i]);
138 }
139
140 auto h_mid = SHA256<Builder>::sha256_block(h_init, block1);
141
142 // Circuit: second block
144 for (size_t i = 0; i < 16; i++) {
145 block2[i] = witness_ct(&builder, BLOCK_2[i]);
146 }
147
148 auto circuit_output = SHA256<Builder>::sha256_block(h_mid, block2);
149
150 // Verify circuit correctness
151 EXPECT_TRUE(CircuitChecker::check(builder));
152
153 // Compare outputs
154 for (size_t i = 0; i < 8; i++) {
155 uint32_t circuit_val = static_cast<uint32_t>(uint256_t(circuit_output[i].get_value()));
156 EXPECT_EQ(circuit_val, EXPECTED[i]) << "Circuit mismatch at index " << i;
157 }
158
159 info("sha256_block (2 blocks) num gates = ", builder.get_num_finalized_gates_inefficient());
160}
161
170TEST(stdlib_sha256, test_extend_witness_constraints)
171{
173
174 auto builder = Builder();
176
177 // Create random input witnesses and ensure they are constrained
178 for (size_t i = 0; i < 16; i++) {
179 auto random32bits = engine.get_random_uint32();
180 field_ct elt(witness_ct(&builder, fr(random32bits)));
181 elt.fix_witness();
182 input[i] = elt;
183 }
184
185 // Extend the witness
187
188 // Verify circuit is initially valid
189 EXPECT_TRUE(CircuitChecker::check(builder));
190
191 // Try modifying each extended witness and verify circuit fails
192 bool any_modification_passed = false;
193 for (auto& single_extended_witness : w_ext) {
194 auto random32bits = engine.get_random_uint32();
195 uint32_t variable_index = single_extended_witness.get_witness_index();
196
197 // Ensure our random value is different from current
198 while (builder.get_variable(variable_index) == fr(random32bits)) {
199 random32bits = engine.get_random_uint32();
200 }
201
202 auto backup = builder.get_variable(variable_index);
203 builder.set_variable(variable_index, fr(random32bits));
204
205 // Circuit should fail with modified witness
207 any_modification_passed = true;
208 }
209
210 builder.set_variable(variable_index, backup);
211 }
212
213 // If any modification didn't cause failure, we have a problem
214 EXPECT_FALSE(any_modification_passed);
215}
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:32
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
virtual uint32_t get_random_uint32()=0
static std::array< field_ct, 64 > extend_witness(const std::array< field_ct, 16 > &w_in)
Definition sha256.cpp:60
static std::array< field_ct, 8 > sha256_block(const std::array< field_ct, 8 > &h_init, const std::array< field_ct, 16 > &input)
Apply the SHA-256 compression function to a single 512-bit message block.
Definition sha256.cpp:248
void info(Args... args)
Definition log.hpp:75
AluTraceBuilder builder
Definition alu.test.cpp:124
numeric::RNG & engine
std::array< uint32_t, 8 > sha256_block(const std::array< uint32_t, 8 > &h_init, const std::array< uint32_t, 16 > &input)
SHA-256 compression function (FIPS 180-4 Section 6.2.2)
Definition sha256.cpp:73
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:190
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field< Bn254FrParams > fr
Definition fr.hpp:174
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
UltraCircuitBuilder Builder
witness_t< Builder > witness_ct