Skip to content

Commit b8b8884

Browse files
authored
feat(garble-core): randomize gate id and cipher key (#348)
1 parent ec2e51d commit b8b8884

File tree

13 files changed

+695
-172
lines changed

13 files changed

+695
-172
lines changed

crates/garble-core/benches/evaluate.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ fn bench_evaluate(c: &mut Criterion) {
2020

2121
let mut rng = StdRng::seed_from_u64(0);
2222
let delta = Delta::random(&mut rng);
23+
let seed: [u8; 16] = rng.random();
2324

2425
// Prepare inputs
2526
let inputs: Vec<Key> = (0..256).map(|_| rng.random()).collect();
@@ -37,10 +38,12 @@ fn bench_evaluate(c: &mut Criterion) {
3738
let actual_gates = iterations as u64 * gates_per_circuit;
3839

3940
// Pre-generate garbled circuits (single gates)
40-
let mut gb = Garbler::default();
41+
let mut gb = Garbler::new(seed, delta);
42+
let setup = gb.setup().unwrap();
4143
let all_gates: Vec<Vec<_>> = (0..iterations)
4244
.map(|_| {
43-
let mut iter = gb.generate(circuit, delta, &inputs).unwrap();
45+
let worker = gb.alloc_worker(circuit.and_count()).unwrap();
46+
let mut iter = worker.generate(circuit, &inputs).unwrap();
4447
let gates: Vec<_> = iter.by_ref().collect();
4548
let _ = iter.finish().unwrap();
4649
gates
@@ -52,9 +55,11 @@ fn bench_evaluate(c: &mut Criterion) {
5255
// Iterator-based (one gate at a time)
5356
group.bench_function(BenchmarkId::new("iter", name), |b| {
5457
let mut ev = Evaluator::default();
58+
ev.setup(setup.clone()).unwrap();
5559
b.iter(|| {
5660
for gates in &all_gates {
57-
let mut consumer = ev.evaluate(circuit, &eval_inputs).unwrap();
61+
let worker = ev.alloc_worker(circuit.and_count()).unwrap();
62+
let mut consumer = worker.evaluate(circuit, &eval_inputs).unwrap();
5863
for gate in gates {
5964
consumer.next(*gate);
6065
}
@@ -68,15 +73,19 @@ fn bench_evaluate(c: &mut Criterion) {
6873
// iteration
6974
group.bench_function(BenchmarkId::new("batched", name), |b| {
7075
let mut ev = Evaluator::default();
71-
let mut gb = Garbler::default();
76+
ev.setup(setup.clone()).unwrap();
77+
let mut gb = Garbler::new(seed, delta);
78+
let _ = gb.setup().unwrap();
7279
b.iter(|| {
7380
for _ in 0..iterations {
7481
// Regenerate batches (not timed separately, but included in measurement)
75-
let mut iter = gb.generate_batched(circuit, delta, &inputs).unwrap();
82+
let worker = gb.alloc_worker(circuit.and_count()).unwrap();
83+
let mut iter = worker.generate_batched(circuit, &inputs).unwrap();
7684
let batches: Vec<_> = iter.by_ref().collect();
7785
let _ = iter.finish().unwrap();
7886

79-
let mut consumer = ev.evaluate_batched(circuit, &eval_inputs).unwrap();
87+
let ev_worker = ev.alloc_worker(circuit.and_count()).unwrap();
88+
let mut consumer = ev_worker.evaluate_batched(circuit, &eval_inputs).unwrap();
8089
for batch in batches {
8190
consumer.next(batch);
8291
}
@@ -96,6 +105,7 @@ fn bench_evaluate_parallel(c: &mut Criterion) {
96105

97106
let mut rng = StdRng::seed_from_u64(0);
98107
let delta = Delta::random(&mut rng);
108+
let seed: [u8; 16] = rng.random();
99109

100110
// Prepare inputs
101111
let inputs: Vec<Key> = (0..256).map(|_| rng.random()).collect();
@@ -113,10 +123,12 @@ fn bench_evaluate_parallel(c: &mut Criterion) {
113123
let actual_gates = circuit_count as u64 * gates_per_circuit;
114124

115125
// Pre-garble circuits
116-
let mut gb = Garbler::default();
126+
let mut gb = Garbler::new(seed, delta);
127+
let setup = gb.setup().unwrap();
117128
let garbled_circuits: Vec<GarbledCircuit> = (0..circuit_count)
118129
.map(|_| {
119-
let mut iter = gb.generate(&circuit, delta, &inputs).unwrap();
130+
let worker = gb.alloc_worker(circuit.and_count()).unwrap();
131+
let mut iter = worker.generate(&circuit, &inputs).unwrap();
120132
let gates: Vec<_> = iter.by_ref().collect();
121133
let _ = iter.finish().unwrap();
122134
GarbledCircuit { gates }
@@ -127,12 +139,17 @@ fn bench_evaluate_parallel(c: &mut Criterion) {
127139

128140
// Parallel evaluation using evaluate_garbled_circuits (uses rayon par_iter)
129141
group.bench_function(BenchmarkId::new("rayon", name), |b| {
142+
let mut ev = Evaluator::default();
143+
ev.setup(setup.clone()).unwrap();
130144
b.iter(|| {
131145
let circs: Vec<_> = garbled_circuits
132146
.iter()
133147
.map(|gc| (circuit.clone(), eval_inputs.clone(), gc.clone()))
134148
.collect();
135-
black_box(evaluate_garbled_circuits(circs).unwrap())
149+
let workers: Vec<_> = (0..circuit_count)
150+
.map(|_| ev.alloc_worker(circuit.and_count()).unwrap())
151+
.collect();
152+
black_box(evaluate_garbled_circuits(circs, workers).unwrap())
136153
})
137154
});
138155
}

crates/garble-core/benches/garble.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main};
66
use mpz_circuits::AES128;
7-
use mpz_garble_core::{Garbler, Key};
7+
use mpz_garble_core::{Evaluator, Garbler, Key};
88
use mpz_memory_core::correlated::Delta;
99
use rand::{Rng, SeedableRng, rngs::StdRng};
1010

@@ -19,6 +19,7 @@ fn bench_garble(c: &mut Criterion) {
1919
let mut rng = StdRng::seed_from_u64(0);
2020
let delta = Delta::random(&mut rng);
2121
let inputs: Vec<Key> = (0..256).map(|_| rng.random()).collect();
22+
let seed: [u8; 16] = rng.random();
2223

2324
let gates_per_circuit = circuit.and_count() as u64;
2425

@@ -30,10 +31,11 @@ fn bench_garble(c: &mut Criterion) {
3031

3132
// Iterator-based (one gate at a time)
3233
group.bench_function(BenchmarkId::new("iter", name), |b| {
33-
let mut gb = Garbler::default();
3434
b.iter(|| {
3535
for _ in 0..iterations {
36-
let mut iter = gb.generate(circuit, delta, &inputs).unwrap();
36+
let mut gb = Garbler::new(seed, delta);
37+
let _ = gb.setup().unwrap();
38+
let mut iter = gb.generate(circuit, &inputs).unwrap();
3739
let _: Vec<_> = iter.by_ref().collect();
3840
black_box(iter.finish().unwrap());
3941
}
@@ -42,10 +44,11 @@ fn bench_garble(c: &mut Criterion) {
4244

4345
// Batched (multiple gates at a time)
4446
group.bench_function(BenchmarkId::new("batched", name), |b| {
45-
let mut gb = Garbler::default();
4647
b.iter(|| {
4748
for _ in 0..iterations {
48-
let mut iter = gb.generate_batched(circuit, delta, &inputs).unwrap();
49+
let mut gb = Garbler::new(seed, delta);
50+
let _ = gb.setup().unwrap();
51+
let mut iter = gb.generate_batched(circuit, &inputs).unwrap();
4952
let _: Vec<_> = iter.by_ref().collect();
5053
black_box(iter.finish().unwrap());
5154
}
@@ -54,6 +57,38 @@ fn bench_garble(c: &mut Criterion) {
5457
}
5558

5659
group.finish();
60+
61+
// Evaluator benchmarks
62+
let mut ev_group = c.benchmark_group("evaluate");
63+
64+
ev_group.bench_function("aes128", |b| {
65+
let mut gb = Garbler::new(seed, delta);
66+
let setup = gb.setup().unwrap();
67+
let mut gb_iter = gb.generate(&AES128, &inputs).unwrap();
68+
let gates: Vec<_> = gb_iter.by_ref().collect();
69+
70+
let choices: Vec<bool> = (0..256).map(|_| rng.random()).collect();
71+
let inputs: Vec<_> = inputs
72+
.iter()
73+
.zip(choices)
74+
.map(|(input, choice)| input.auth(choice, &delta))
75+
.collect();
76+
77+
b.iter(|| {
78+
let setup = setup.clone();
79+
let mut ev = Evaluator::default();
80+
ev.setup(setup).unwrap();
81+
let mut ev_consumer = ev.evaluate(&AES128, &inputs).unwrap();
82+
83+
for gate in &gates {
84+
ev_consumer.next(*gate);
85+
}
86+
87+
black_box(ev_consumer.finish().unwrap());
88+
})
89+
});
90+
91+
ev_group.finish();
5792
}
5893

5994
criterion_group!(benches, bench_garble);

0 commit comments

Comments
 (0)