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