1use acir::{
2 AcirField,
3 circuit::opcodes::FunctionInput,
4 native_types::{Witness, WitnessMap},
5};
6use acvm_blackbox_solver::aes128_encrypt;
7
8use crate::{OpcodeResolutionError, pwg::insert_value};
9
10use super::utils::{to_u8_array, to_u8_vec};
11
12pub(super) fn solve_aes128_encryption_opcode<F: AcirField>(
13 initial_witness: &mut WitnessMap<F>,
14 inputs: &[FunctionInput<F>],
15 iv: &[FunctionInput<F>; 16],
16 key: &[FunctionInput<F>; 16],
17 outputs: &[Witness],
18) -> Result<(), OpcodeResolutionError<F>> {
19 let ciphertext = execute_aes128_encryption_opcode(initial_witness, inputs, iv, key)?;
20
21 assert_eq!(
22 outputs.len(),
23 ciphertext.len(),
24 "Number of outputs does not match number of ciphertext bytes"
25 );
26
27 for (output_witness, value) in outputs.iter().zip(ciphertext.into_iter()) {
29 insert_value(output_witness, F::from(u128::from(value)), initial_witness)?;
30 }
31
32 Ok(())
33}
34
35pub(crate) fn execute_aes128_encryption_opcode<F: AcirField>(
36 initial_witness: &WitnessMap<F>,
37 inputs: &[FunctionInput<F>],
38 iv: &[FunctionInput<F>; 16],
39 key: &[FunctionInput<F>; 16],
40) -> Result<Vec<u8>, OpcodeResolutionError<F>> {
41 let scalars = to_u8_vec(initial_witness, inputs)?;
42
43 let iv = to_u8_array(initial_witness, iv)?;
44 let key = to_u8_array(initial_witness, key)?;
45
46 let ciphertext = aes128_encrypt(&scalars, iv, key)?;
47
48 Ok(ciphertext)
49}
50
51#[cfg(test)]
52mod tests {
53 use crate::pwg::blackbox::solve_aes128_encryption_opcode;
54 use acir::{
55 FieldElement,
56 circuit::opcodes::FunctionInput,
57 native_types::{Witness, WitnessMap},
58 };
59 use std::collections::BTreeMap;
60
61 #[test]
62 #[allow(clippy::needless_range_loop)]
63 fn test_aes() {
64 let mut initial_witness = WitnessMap::from(BTreeMap::from_iter([
67 (Witness(1), FieldElement::from(0x2bu128)),
69 (Witness(2), FieldElement::from(0x7eu128)),
70 (Witness(3), FieldElement::from(0x15u128)),
71 (Witness(4), FieldElement::from(0x16u128)),
72 (Witness(5), FieldElement::from(0x28u128)),
73 (Witness(6), FieldElement::from(0xaeu128)),
74 (Witness(7), FieldElement::from(0xd2u128)),
75 (Witness(8), FieldElement::from(0xa6u128)),
76 (Witness(9), FieldElement::from(0xabu128)),
77 (Witness(10), FieldElement::from(0xf7u128)),
78 (Witness(11), FieldElement::from(0x15u128)),
79 (Witness(12), FieldElement::from(0x88u128)),
80 (Witness(13), FieldElement::from(0x09u128)),
81 (Witness(14), FieldElement::from(0xcfu128)),
82 (Witness(15), FieldElement::from(0x4fu128)),
83 (Witness(16), FieldElement::from(0x3cu128)),
84 (Witness(17), FieldElement::from(0x00u128)),
86 (Witness(18), FieldElement::from(0x01u128)),
87 (Witness(19), FieldElement::from(0x02u128)),
88 (Witness(20), FieldElement::from(0x03u128)),
89 (Witness(21), FieldElement::from(0x04u128)),
90 (Witness(22), FieldElement::from(0x05u128)),
91 (Witness(23), FieldElement::from(0x06u128)),
92 (Witness(24), FieldElement::from(0x07u128)),
93 (Witness(25), FieldElement::from(0x08u128)),
94 (Witness(26), FieldElement::from(0x09u128)),
95 (Witness(27), FieldElement::from(0x0au128)),
96 (Witness(28), FieldElement::from(0x0bu128)),
97 (Witness(29), FieldElement::from(0x0cu128)),
98 (Witness(30), FieldElement::from(0x0du128)),
99 (Witness(31), FieldElement::from(0x0eu128)),
100 (Witness(32), FieldElement::from(0x0fu128)),
101 (Witness(33), FieldElement::from(0x6bu128)),
106 (Witness(34), FieldElement::from(0xc1u128)),
107 (Witness(35), FieldElement::from(0xbeu128)),
108 (Witness(36), FieldElement::from(0xe2u128)),
109 (Witness(37), FieldElement::from(0x2eu128)),
110 (Witness(38), FieldElement::from(0x40u128)),
111 (Witness(39), FieldElement::from(0x9fu128)),
112 (Witness(40), FieldElement::from(0x96u128)),
113 (Witness(41), FieldElement::from(0xe9u128)),
114 (Witness(42), FieldElement::from(0x3du128)),
115 (Witness(43), FieldElement::from(0x7eu128)),
116 (Witness(44), FieldElement::from(0x11u128)),
117 (Witness(45), FieldElement::from(0x73u128)),
118 (Witness(46), FieldElement::from(0x93u128)),
119 (Witness(47), FieldElement::from(0x17u128)),
120 (Witness(48), FieldElement::from(0x2au128)),
121 (Witness(49), FieldElement::from(0xaeu128)),
122 (Witness(50), FieldElement::from(0x2du128)),
123 (Witness(51), FieldElement::from(0x8au128)),
124 (Witness(52), FieldElement::from(0x57u128)),
125 (Witness(53), FieldElement::from(0x1eu128)),
126 (Witness(54), FieldElement::from(0x03u128)),
127 (Witness(55), FieldElement::from(0xacu128)),
128 (Witness(56), FieldElement::from(0x9cu128)),
129 (Witness(57), FieldElement::from(0x9eu128)),
130 (Witness(58), FieldElement::from(0xb7u128)),
131 (Witness(59), FieldElement::from(0x6fu128)),
132 (Witness(60), FieldElement::from(0xacu128)),
133 (Witness(61), FieldElement::from(0x45u128)),
134 (Witness(62), FieldElement::from(0xafu128)),
135 (Witness(63), FieldElement::from(0x8eu128)),
136 (Witness(64), FieldElement::from(0x51u128)),
137 (Witness(65), FieldElement::from(0x30u128)),
138 (Witness(66), FieldElement::from(0xc8u128)),
139 (Witness(67), FieldElement::from(0x1cu128)),
140 (Witness(68), FieldElement::from(0x46u128)),
141 (Witness(69), FieldElement::from(0xa3u128)),
142 (Witness(70), FieldElement::from(0x5cu128)),
143 (Witness(71), FieldElement::from(0xe4u128)),
144 (Witness(72), FieldElement::from(0x11u128)),
145 (Witness(73), FieldElement::from(0xe5u128)),
146 (Witness(74), FieldElement::from(0xfbu128)),
147 (Witness(75), FieldElement::from(0xc1u128)),
148 (Witness(76), FieldElement::from(0x19u128)),
149 (Witness(77), FieldElement::from(0x1au128)),
150 (Witness(78), FieldElement::from(0x0au128)),
151 (Witness(79), FieldElement::from(0x52u128)),
152 (Witness(80), FieldElement::from(0xefu128)),
153 (Witness(81), FieldElement::from(0xf6u128)),
154 (Witness(82), FieldElement::from(0x9fu128)),
155 (Witness(83), FieldElement::from(0x24u128)),
156 (Witness(84), FieldElement::from(0x45u128)),
157 (Witness(85), FieldElement::from(0xdfu128)),
158 (Witness(86), FieldElement::from(0x4fu128)),
159 (Witness(87), FieldElement::from(0x9bu128)),
160 (Witness(88), FieldElement::from(0x17u128)),
161 (Witness(89), FieldElement::from(0xadu128)),
162 (Witness(90), FieldElement::from(0x2bu128)),
163 (Witness(91), FieldElement::from(0x41u128)),
164 (Witness(92), FieldElement::from(0x7bu128)),
165 (Witness(93), FieldElement::from(0xe6u128)),
166 (Witness(94), FieldElement::from(0x6cu128)),
167 (Witness(95), FieldElement::from(0x37u128)),
168 (Witness(96), FieldElement::from(0x10u128)),
169 ]));
170 const INPUT_LENGTH: usize = 64;
172
173 let mut inputs = [FunctionInput::Witness(Witness(0)); 64];
174 for i in 0..INPUT_LENGTH {
175 inputs[i] = FunctionInput::Witness(Witness(33 + i as u32));
176 }
177 let mut iv = [FunctionInput::Witness(Witness(0)); 16];
178 for i in 0..16 {
179 iv[i] = FunctionInput::Witness(Witness(17 + i as u32));
180 }
181 let mut key = [FunctionInput::Witness(Witness(0)); 16];
182 for i in 0..16 {
183 key[i] = FunctionInput::Witness(Witness(1 + i as u32));
184 }
185 const OUTPUT_LENGTH: usize = INPUT_LENGTH;
187 let mut outputs = vec![];
188 for i in 97..97 + OUTPUT_LENGTH {
189 outputs.push(Witness(i as u32));
190 }
191
192 solve_aes128_encryption_opcode(&mut initial_witness, &inputs, &iv, &key, &outputs).unwrap();
193 let expected_output: [u128; OUTPUT_LENGTH] = [
196 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9,
197 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a,
198 0x91, 0x76, 0x78, 0xb2, 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16,
199 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09,
200 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7,
201 ];
202 let expected_output = expected_output.map(FieldElement::from);
203 let expected_output: Vec<&FieldElement> = expected_output.iter().collect();
204 for i in 0..OUTPUT_LENGTH {
205 assert_eq!(initial_witness[&Witness(97 + i as u32)], *expected_output[i]);
206 }
207 }
208}