Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
aes128.test.cpp
Go to the documentation of this file.
1#include "aes128.hpp"
5
6#include <gtest/gtest.h>
7
8using namespace bb;
9
10// Helper function to create field element as either constant or witness
21
22// Helper function to convert byte array to uint256_t
24{
25 uint256_t converted(0);
26 for (uint64_t i = 0; i < 16; ++i) {
27 uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8);
28 converted += to_add;
29 }
30 return converted;
31}
32
33// Test function for a specific combination of witness/constant inputs
34void test_aes128_combination(bool key_as_witness, bool iv_as_witness, bool input_as_witness)
35{
37
38 uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
39 uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
40 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
41 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
42 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 };
43 uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
44 uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
45 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
46 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
47 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 };
48
50
51 // Create input blocks with specified witness/constant configuration
52 std::vector<field_pt> in_field;
53 for (size_t i = 0; i < 4; ++i) {
54 in_field.push_back(create_field_element(builder, convert_bytes_to_uint256(in + i * 16), input_as_witness));
55 }
56
57 // Create key and IV with specified witness/constant configuration
59 field_pt iv_field = create_field_element(builder, convert_bytes_to_uint256(iv), iv_as_witness);
60
61 // Expected results
62 std::vector<fr> expected{ convert_bytes_to_uint256(out),
65 convert_bytes_to_uint256(out + 48) };
66
67 // Run AES encryption
68 const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
69
70 // Verify results
71 for (size_t i = 0; i < 4; ++i) {
72 EXPECT_EQ(result[i].get_value(), expected[i])
73 << "Combination: key=" << (key_as_witness ? "witness" : "constant")
74 << ", iv=" << (iv_as_witness ? "witness" : "constant")
75 << ", input=" << (input_as_witness ? "witness" : "constant");
76 }
77
78 // Verify circuit is valid (only if there are witnesses)
79 if (key_as_witness || iv_as_witness || input_as_witness) {
80 bool proof_result = CircuitChecker::check(builder);
81 EXPECT_EQ(proof_result, true) << "Circuit check failed for combination: key="
82 << (key_as_witness ? "witness" : "constant")
83 << ", iv=" << (iv_as_witness ? "witness" : "constant")
84 << ", input=" << (input_as_witness ? "witness" : "constant");
85 }
86}
87
88// Test function for mixed input blocks (some constant, some witness)
89void test_aes128_mixed_input(bool key_as_witness, bool iv_as_witness, const std::vector<bool>& input_block_config)
90{
92
93 uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
94 uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
95 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
96 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
97 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 };
98 uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
99 uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
100 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
101 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
102 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 };
103
105
106 // Create input blocks with mixed witness/constant configuration
107 std::vector<field_pt> in_field;
108 for (size_t i = 0; i < input_block_config.size(); ++i) {
109 in_field.push_back(create_field_element(builder, convert_bytes_to_uint256(in + i * 16), input_block_config[i]));
110 }
111
112 // Create key and IV with specified witness/constant configuration
114 field_pt iv_field = create_field_element(builder, convert_bytes_to_uint256(iv), iv_as_witness);
115
116 // Expected results
117 std::vector<fr> expected;
118 for (size_t i = 0; i < input_block_config.size(); ++i) {
119 expected.push_back(convert_bytes_to_uint256(out + i * 16));
120 }
121
122 // Run AES encryption
123 const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
124
125 // Verify results
126 for (size_t i = 0; i < result.size(); ++i) {
127 EXPECT_EQ(result[i].get_value(), expected[i]) << "Mixed input test failed for block " << i;
128 }
129
130 // Verify circuit is valid (only if there are witnesses)
131 bool has_witness = key_as_witness || iv_as_witness;
132 for (bool is_witness : input_block_config) {
133 if (is_witness) {
134 has_witness = true;
135 break;
136 }
137 }
138
139 if (has_witness) {
140 bool proof_result = CircuitChecker::check(builder);
141 EXPECT_EQ(proof_result, true) << "Circuit check failed for mixed input test";
142 }
143}
144
145TEST(stdlib_aes128, encrypt_64_bytes_all_witness)
146{
147 test_aes128_combination(true, true, true);
148}
149
150TEST(stdlib_aes128, encrypt_64_bytes_all_constant)
151{
152 test_aes128_combination(false, false, false);
153}
154
155TEST(stdlib_aes128, encrypt_64_bytes_key_witness_iv_constant_input_constant)
156{
157 test_aes128_combination(true, false, false);
158}
159
160TEST(stdlib_aes128, encrypt_64_bytes_key_constant_iv_witness_input_constant)
161{
162 test_aes128_combination(false, true, false);
163}
164
165TEST(stdlib_aes128, encrypt_64_bytes_key_constant_iv_constant_input_witness)
166{
167 test_aes128_combination(false, false, true);
168}
169
170TEST(stdlib_aes128, encrypt_64_bytes_key_witness_iv_witness_input_constant)
171{
172 test_aes128_combination(true, true, false);
173}
174
175TEST(stdlib_aes128, encrypt_64_bytes_key_witness_iv_constant_input_witness)
176{
177 test_aes128_combination(true, false, true);
178}
179
180TEST(stdlib_aes128, encrypt_64_bytes_key_constant_iv_witness_input_witness)
181{
182 test_aes128_combination(false, true, true);
183}
184
185// Original test for backward compatibility
186TEST(stdlib_aes128, encrypt_64_bytes_original)
187{
190
191 uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
192 uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
193 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
194 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
195 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 };
196 uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
197 uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
198 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
199 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
200 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 };
201
202 const auto convert_bytes = [](uint8_t* data) {
203 uint256_t converted(0);
204 for (uint64_t i = 0; i < 16; ++i) {
205 uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8);
206 converted += to_add;
207 }
208 return converted;
209 };
210
212
213 std::vector<field_pt> in_field{
214 witness_pt(&builder, fr(convert_bytes(in))),
215 witness_pt(&builder, fr(convert_bytes(in + 16))),
216 witness_pt(&builder, fr(convert_bytes(in + 32))),
217 witness_pt(&builder, fr(convert_bytes(in + 48))),
218 };
219
220 field_pt key_field(witness_pt(&builder, fr(convert_bytes(key))));
221 field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv))));
222
223 std::vector<fr> expected{
224 convert_bytes(out), convert_bytes(out + 16), convert_bytes(out + 32), convert_bytes(out + 48)
225 };
226
227 const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
228
229 for (size_t i = 0; i < 4; ++i) {
230 EXPECT_EQ(result[i].get_value(), expected[i]);
231 }
232
233 std::cout << "num gates = " << builder.get_estimated_num_finalized_gates() << std::endl;
234
235 bool proof_result = CircuitChecker::check(builder);
236 EXPECT_EQ(proof_result, true);
237}
238
239// Mixed input tests - different combinations of constant/witness blocks
240TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_first_witness_rest_constant)
241{
242 test_aes128_mixed_input(false, false, { true, false, false, false });
243}
244
245TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_alternating_witness_constant)
246{
247 test_aes128_mixed_input(false, false, { true, false, true, false });
248}
249
250TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_first_constant_rest_witness)
251{
252 test_aes128_mixed_input(false, false, { false, true, true, true });
253}
254
255TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_key_witness_mixed_blocks)
256{
257 test_aes128_mixed_input(true, false, { true, false, true, false });
258}
259
260TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_iv_witness_mixed_blocks)
261{
262 test_aes128_mixed_input(false, true, { false, true, false, true });
263}
264
265TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_key_iv_witness_mixed_blocks)
266{
267 test_aes128_mixed_input(true, true, { true, false, true, false });
268}
269
270TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_all_witness_blocks)
271{
272 test_aes128_mixed_input(false, false, { true, true, true, true });
273}
274
275TEST(stdlib_aes128, encrypt_64_bytes_mixed_input_all_constant_blocks)
276{
277 test_aes128_mixed_input(false, false, { false, false, false, false });
278}
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
AluTraceBuilder builder
Definition alu.test.cpp:123
const std::vector< FF > data
stdlib::witness_t< bb::UltraCircuitBuilder > witness_pt
stdlib::field_t< UltraCircuitBuilder > field_pt
std::vector< field_t< Builder > > encrypt_buffer_cbc(const std::vector< field_t< Builder > > &input, const field_t< Builder > &iv, const field_t< Builder > &key)
Definition aes128.cpp:265
Entry point for Barretenberg command-line interface.
TEST(MegaCircuitBuilder, CopyConstructor)
field< Bn254FrParams > fr
Definition fr.hpp:174
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
void test_aes128_combination(bool key_as_witness, bool iv_as_witness, bool input_as_witness)
stdlib::field_t< UltraCircuitBuilder > create_field_element(UltraCircuitBuilder &builder, const uint256_t &value, bool as_witness)
uint256_t convert_bytes_to_uint256(const uint8_t *data)
void test_aes128_mixed_input(bool key_as_witness, bool iv_as_witness, const std::vector< bool > &input_block_config)