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