Skip to content

Commit

Permalink
Merge pull request anon-aadhaar#5 from anon-aadhaar/data
Browse files Browse the repository at this point in the history
Circuits With Actual Data
  • Loading branch information
hridambasu authored Jul 28, 2024
2 parents 5995da0 + 8884881 commit be8eb31
Show file tree
Hide file tree
Showing 12 changed files with 3,139 additions and 80 deletions.
188 changes: 188 additions & 0 deletions src/aadhaar_verifier_circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@

pub use big_uint::*;
use crate::{big_uint, TestRSASignatureWithHashCircuit1, TestRSASignatureWithHashConfig1};
use halo2_base::halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner}, plonk::{Circuit, ConstraintSystem, Error}
};
use halo2_base::utils::PrimeField;
use num_bigint::BigUint;

use crate::timestamp::{TimestampCircuit, TimestampConfig};
use crate::conditional_secrets::{IdentityCircuit, IdentityConfig};
use crate::signal::{SquareCircuit, SquareConfig};
//use std::sync::Arc;

#[derive(Clone)]
struct AadhaarQRVerifierCircuit<F: PrimeField> {
//extractor: ExtractAndPackAsIntCircuit,
hash_and_sign: TestRSASignatureWithHashCircuit1<F>,
cond_secrets: IdentityCircuit,
timestamp: TimestampCircuit<F>,
signal: SquareCircuit<F>,
//layouter: impl Layouter<F>
}

impl<F: PrimeField> AadhaarQRVerifierCircuit<F> {
pub fn new(
hash_and_sign: TestRSASignatureWithHashCircuit1<F>,
cond_secrets: IdentityCircuit,
timestamp: TimestampCircuit<F>,
signal: SquareCircuit<F>,
) -> Self {
Self {
hash_and_sign,
cond_secrets,
timestamp,
signal,
}
}
}

impl<F:PrimeField> Circuit<F> for AadhaarQRVerifierCircuit<F> {
type Config = (TestRSASignatureWithHashConfig1<F>,
IdentityConfig,
TimestampConfig,
SquareConfig);
type FloorPlanner = SimpleFloorPlanner;

fn without_witnesses(&self) -> Self {
unimplemented!()
}

fn configure(cs: &mut ConstraintSystem<F>) -> Self::Config {
//let extractor = ExtractAndPackAsIntCircuit::configure(cs);
let hash_and_sign = TestRSASignatureWithHashCircuit1::<F>::configure(cs);
let cond_secrets = IdentityCircuit::configure(cs);
let timestamp = TimestampCircuit::configure(cs);
let signal = SquareCircuit::configure(cs);

(hash_and_sign, cond_secrets, timestamp, signal)
}

fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<F>,
) -> Result<(), Error> {
//self.extractor.synthesize(cs, extractor_config)?;
self.hash_and_sign.synthesize(config.0, layouter)?;
self.cond_secrets.synthesize(config.1, layouter)?;
self.timestamp.synthesize(config.2, layouter)?;
self.signal.synthesize(config.3, layouter)?;

Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::big_uint::decompose_biguint;
use rand::{thread_rng, Rng};
use rsa::{traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey};
use sha2::{Digest, Sha256};
use halo2_base::halo2_proofs::{dev::MockProver, halo2curves::{pasta::Fp, bn256::Fr}};
use crate::TestRSASignatureWithHashCircuit1;

#[test]
fn test_aadhaar_qr_verifier_circuit() {
fn run<F: PrimeField>() {
// Extractor Subcircuit
/*let n_delimited_data = vec![Some(5), Some(10), Some(15), Some(255), Some(1), Some(2)];
let delimiter_indices = vec![Some(1), Some(2), Some(3)];
let extractor_circuit = ExtractAndPackAsIntCircuit {
n_delimited_data: n_delimited_data.iter().map(|&v| Value::known(F::from(v.unwrap()))).collect(),
delimiter_indices: delimiter_indices.iter().map(|&v| Value::known(F::from(v.unwrap()))).collect(),
extract_position: 1, // Example value
extract_max_length: 31, // Example value
_marker: PhantomData,
};*/

// RSA-SHA256 Subcircuit
let mut rng = thread_rng();
let private_key = RsaPrivateKey::new(&mut rng, TestRSASignatureWithHashCircuit1::<F>::BITS_LEN)
.expect("failed to generate a key");
let public_key = RsaPublicKey::from(&private_key);
let n = BigUint::from_radix_le(&public_key.n().to_radix_le(16), 16).unwrap();
let mut msg: [u8; 128] = [0; 128];
for i in 0..128 {
msg[i] = rng.gen();
}
let hashed_msg = Sha256::digest(&msg);
let hash_and_sign_circuit = TestRSASignatureWithHashCircuit1::<F>::new(
private_key,
public_key,
msg.to_vec(),
//_f: PhantomData,
);

// Conditional Secrets Subcircuit
let cond_secrets_circuit = IdentityCircuit::new(
Some(true),
Some(1),
Some(1),
Some(true),
Some(1),
Some(1),
Some(true),
Some(123456),
Some(123456),
Some(true),
Some(1),
Some(1));

// Timestamp Subcircuit
let timestamp_circuit = TimestampCircuit::<F>::new(Some(F::from(2023u64)),
Some(F::from(7u64)),
Some(F::from(8u64)),
Some(F::from(12u64)),
Some(F::from(34u64)),
Some(F::from(56u64)));

// Signal Hash Subcircuit
let signal_hash = 5;
let signal_circuit = SquareCircuit::<F>::new(F::from(signal_hash));

// Entire Aadhaar QR Verifier Circuit
let _circuit = AadhaarQRVerifierCircuit::<F>::new(
//extractor: extractor_circuit,
hash_and_sign_circuit.clone(),
cond_secrets_circuit.clone(),
timestamp_circuit.clone(),
signal_circuit.clone(),
);

// Verifying the RSA-SHA256 subcircuit
let num_limbs = 2048 / 64;
let limb_bits = 64;
let n_fes = decompose_biguint::<F>(&n, num_limbs, limb_bits);
let hash_fes = hashed_msg
.iter()
.map(|byte| F::from(*byte as u64))
.collect::<Vec<F>>();
let public_inputs = vec![n_fes, hash_fes];
let k = 15;
let prover = match MockProver::run(k, &hash_and_sign_circuit.clone(), public_inputs) {
Ok(prover) => prover,
Err(e) => panic!("{:#?}", e),
};
prover.verify().unwrap();

// Verifying the conditional secrets subcircuit
let prover: MockProver<Fp> = MockProver::run(k, &cond_secrets_circuit.clone(), vec![]).unwrap();
assert!(prover.verify().is_ok());

// Verifying the timestamp subcircuit
let public_inputs = vec![];
let prover = MockProver::run(k, &timestamp_circuit.clone(), public_inputs).unwrap();
assert_eq!(prover.verify(), Ok(()));

// Verifying the signal hash subcircuit
let public_inputs = vec![F::from(signal_hash * signal_hash)];
let prover = MockProver::run(k, &signal_circuit.clone(), vec![public_inputs]).unwrap();
prover.assert_satisfied();

}
run::<Fr>();
}
}
130 changes: 95 additions & 35 deletions src/conditional_secrets.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
use halo2_base::halo2_proofs::arithmetic::FieldExt;
use halo2_base::halo2_proofs::plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Selector, Expression};
use halo2_base::halo2_proofs::poly::Rotation;
use halo2_base::halo2_proofs::circuit::{Layouter, SimpleFloorPlanner, Value};
use halo2_base::utils::PrimeField;
//use std::sync::Arc;

#[derive(Default)]
struct IdentityCircuit {
#[derive(Default, Clone)]
pub struct IdentityCircuit {
reveal_age_above_18: Option<bool>,
age_above_18: Option<u8>,
qr_data_age_above_18: Option<u8>,
age_above_18: Option<u64>,
qr_data_age_above_18: Option<u64>,
reveal_gender: Option<bool>,
gender: Option<u8>,
qr_data_gender: Option<u8>,
reveal_pincode: Option<bool>,
pincode: Option<u32>,
qr_data_pincode: Option<u32>,
reveal_state: Option<bool>,
state: Option<u8>,
qr_data_state: Option<u8>,
state: Option<Vec<u8>>,
qr_data_state: Option<Vec<u8>>,
}

#[derive(Clone)]
struct IdentityConfig {
pub struct IdentityConfig {
reveal_age_above_18: Column<Advice>,
age_above_18: Column<Advice>,
qr_data_age_above_18: Column<Advice>,
Expand All @@ -31,12 +32,44 @@ struct IdentityConfig {
pincode: Column<Advice>,
qr_data_pincode: Column<Advice>,
reveal_state: Column<Advice>,
state: Column<Advice>,
qr_data_state: Column<Advice>,
state: Vec<Column<Advice>>,
qr_data_state: Vec<Column<Advice>>,
s: Selector,
}

impl<F: FieldExt> Circuit<F> for IdentityCircuit {
impl IdentityCircuit {
pub fn new(
reveal_age_above_18: Option<bool>,
age_above_18: Option<u64>,
qr_data_age_above_18: Option<u64>,
reveal_gender: Option<bool>,
gender: Option<u8>,
qr_data_gender: Option<u8>,
reveal_pincode: Option<bool>,
pincode: Option<u32>,
qr_data_pincode: Option<u32>,
reveal_state: Option<bool>,
state: Option<Vec<u8>>,
qr_data_state: Option<Vec<u8>>,
) -> Self {
Self {
reveal_age_above_18,
age_above_18,
qr_data_age_above_18,
reveal_gender,
gender,
qr_data_gender,
reveal_pincode,
pincode,
qr_data_pincode,
reveal_state,
state,
qr_data_state,
}
}
}

impl<F: PrimeField> Circuit<F> for IdentityCircuit {
type Config = IdentityConfig;
type FloorPlanner = SimpleFloorPlanner;

Expand All @@ -55,8 +88,14 @@ impl<F: FieldExt> Circuit<F> for IdentityCircuit {
let pincode = meta.advice_column();
let qr_data_pincode = meta.advice_column();
let reveal_state = meta.advice_column();
let state = meta.advice_column();
let qr_data_state = meta.advice_column();
let mut state = vec![];
for _i in 0..5 {
state.push(meta.advice_column());
}
let mut qr_data_state = vec![];
for _i in 0..5 {
qr_data_state.push(meta.advice_column());
}
let s = meta.selector();

meta.create_gate("revealAgeAbove18 constraint", |meta| {
Expand Down Expand Up @@ -113,13 +152,26 @@ impl<F: FieldExt> Circuit<F> for IdentityCircuit {

meta.create_gate("state assignment", |meta| {
let s = meta.query_selector(s);
let state = meta.query_advice(state, Rotation::cur());
let qr_data_state = meta.query_advice(qr_data_state, Rotation::cur());
vec![
s * (state - qr_data_state)
]
let mut constraints = Vec::with_capacity(5);
let mut states = Vec::with_capacity(5);
let mut qr_states = Vec::with_capacity(5);
for i in 0..5 {
states.push(meta.query_advice(state.clone()[i], Rotation::cur()));
}
for i in 0..5 {
qr_states.push(meta.query_advice(qr_data_state.clone()[i], Rotation::cur()));
}
let st = states.clone();
let qrs = qr_states.clone();
for i in 0..5 {
let a = st.get(i).unwrap().clone();
let b = qrs.get(i).unwrap().clone();
constraints.push(s.clone() * (a - b));
}
constraints
});


IdentityConfig {
reveal_age_above_18,
age_above_18,
Expand Down Expand Up @@ -213,19 +265,27 @@ impl<F: FieldExt> Circuit<F> for IdentityCircuit {
|| Value::known(F::from(self.reveal_state.unwrap_or(false) as u64))
)?;

region.assign_advice(
|| "state",
config.state,
0,
|| Value::known(F::from(self.state.unwrap_or(0) as u64))
)?;

region.assign_advice(
|| "qr_data_state",
config.qr_data_state,
0,
|| Value::known(F::from(self.qr_data_state.unwrap_or(0) as u64))
)?;
if let Some(state) = &self.state {
for (i, &byte) in state.iter().enumerate() {
region.assign_advice(
|| format!("state_{}", i),
config.state[i],
0,
|| Value::known(F::from(byte as u64))
)?;
}
}

if let Some(qr_data_state) = &self.qr_data_state {
for (i, &byte) in qr_data_state.iter().enumerate() {
region.assign_advice(
|| format!("qr_data_state_{}", i),
config.qr_data_state[i],
0,
|| Value::known(F::from(byte as u64))
)?;
}
}

Ok(())
}
Expand Down Expand Up @@ -254,15 +314,15 @@ mod tests {
pincode: Some(123456),
qr_data_pincode: Some(123456),
reveal_state: Some(true),
state: Some(1),
qr_data_state: Some(1),
state: Some(vec![10, 11, 12, 13, 14]),
qr_data_state: Some(vec![10, 11, 12, 13, 14]),
};

let prover: MockProver<Fp> = MockProver::run(k, &circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()));

// Test case where reveal_age_above_18 is false
let circuit = IdentityCircuit {
/*let circuit = IdentityCircuit {
reveal_age_above_18: Some(false),
age_above_18: Some(0),
qr_data_age_above_18: Some(1),
Expand Down Expand Up @@ -411,7 +471,7 @@ mod tests {
};
let prover: MockProver<Fp> = MockProver::run(k, &circuit, vec![]).unwrap();
assert!(prover.verify().is_ok());
assert!(prover.verify().is_ok());*/
}
}

Loading

0 comments on commit be8eb31

Please sign in to comment.