plonky2-crypto-gadgets/aes-gcm/examples/aes_gcm_128.rs
aes-gcm/examples/aes_gcm_128.rsRaw
1//! Run: `cargo run --release --example aes_gcm_128`
2#![allow(incomplete_features)]
3#![feature(generic_const_exprs)]
4
5use anyhow::Result;
6use plonky2::{
7 field::goldilocks_field::GoldilocksField as F,
8 iop::witness::PartialWitness,
9 plonk::{
10 circuit_builder::CircuitBuilder, circuit_data::CircuitConfig,
11 config::PoseidonGoldilocksConfig,
12 },
13};
14use plonky2_aes::{AesGcm128Target, D, KEY_LEN_128};
15
16fn main() -> Result<()> {
17 // max size (bytes) of plaintext supported by the instantiation of the circuit
18 const L: usize = 42;
19
20 let key: &[u8; KEY_LEN_128] = &[123; KEY_LEN_128];
21 let nonce: &[u8; 12] = &[111; 12];
22 let pt: &[u8; L] = &[231u8; L]; // plaintext
23
24 // use external rust library to compute the ciphertext & tag
25 let nonce_ext = aes_gcm::Nonce::from_slice(nonce);
26 use aes_gcm::{KeyInit, aead::Aead}; // needed traits
27 let cipher = aes_gcm::Aes128Gcm::new_from_slice(key.as_slice()).unwrap();
28 let encrypt_res = cipher.encrypt(nonce_ext, pt.as_ref()).unwrap();
29 let ct = &encrypt_res[..L]; // ciphertext
30 let tag = &encrypt_res[L..];
31
32 // alternatively we could use this repo's rust implementation (only for tests)
33 // let (ct, tag) = plonky2_aes::native_gcm::encrypt::<4, 4, 10>(key, nonce, pt);
34
35 // circuit declaration
36 let config = CircuitConfig::standard_recursion_zk_config();
37 let mut builder = CircuitBuilder::<F, D>::new(config);
38 let aes_targets = AesGcm128Target::<L>::new_virtual(&mut builder);
39 aes_targets.build_circuit(&mut builder);
40
41 println!(
42 "AES-GCM-128 circuit (L:{}) num_gates: {}",
43 L,
44 builder.num_gates()
45 );
46
47 let data = builder.build::<PoseidonGoldilocksConfig>();
48
49 // set values to circuit
50 let mut pw = PartialWitness::<F>::new();
51 aes_targets.set_targets(&mut pw, key, nonce, pt, ct, tag)?;
52
53 let proof = data.prove(pw)?;
54 data.verify(proof)
55}