Skip to content

Commit cbcad0c

Browse files
committed
Merge branch 'main' of https://github.com/microsoft/crescent-credentials into in-mem-deserialize-constraints
2 parents a95bbe5 + 8c39402 commit cbcad0c

File tree

10 files changed

+92
-40
lines changed

10 files changed

+92
-40
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ and we can run each step as follows
7777
```bash
7878
cargo run --bin crescent --release --features print-trace zksetup --name rs256
7979
cargo run --bin crescent --release --features print-trace prove --name rs256
80-
cargo run --bin crescent --release --features print-trace show --name rs256
81-
cargo run --bin crescent --release --features print-trace verify --name rs256
80+
cargo run --bin crescent --release --features print-trace show --name rs256 [--presentation-message "..."]
81+
cargo run --bin crescent --release --features print-trace verify --name rs256 [--presentation-message "..."]
8282
```
8383

84-
The `--name` parameter, used in circuit setup and with the command-line tool, specifies which credential type is used, the two examples are `rs256`, a JWT signed with RSA256, and `mdl1` a sample mobile driver's license.
84+
The `--name` parameter, used in circuit setup and with the command-line tool, specifies which credential type is used, the two examples are `rs256`, a JWT signed with RSA256, and `mdl1` a sample mobile driver's license. An optional text presentation message can be passed to the `show` and `prove` steps to bind the presentation to some application data (e.g., a verifier challenge, some data to sign).
8585

8686
Note that the steps have to be run in order, but once the client state is created by `prove`, the `show` and `verify` steps can be run repeatedly.
8787

creds/benches/proof_benchmark.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,23 @@ pub fn show_bench(c: &mut Criterion) {
114114
);
115115

116116
let io_types = vec![PublicIOType::Hidden; client_state.inputs.len()];
117+
let pm = "some presentation message".as_bytes();
117118

118-
let showing = client_state.show_groth16(&io_types);
119+
let showing = client_state.show_groth16(Some(pm), &io_types);
119120
c.bench_function(&format!("Show with {} hidden inputs", NUM_INPUTS), |b| {
120121
b.iter(|| {
121-
client_state.show_groth16(&io_types);
122+
client_state.show_groth16(Some(pm), &io_types);
122123
})
123124
});
124125

125-
showing.verify(&vk, &pvk, &io_types, &vec![]);
126+
showing.verify(&vk, &pvk, Some(pm), &io_types, &vec![]);
126127
c.bench_function(&format!("Verify with {} hidden inputs", NUM_INPUTS), |b| {
127128
b.iter(|| {
128129
ShowGroth16::<Bn254>::verify(
129130
black_box(&showing),
130131
black_box(&vk),
131132
black_box(&pvk),
133+
Some(pm),
132134
&io_types,
133135
&vec![],
134136
);

creds/src/dlog.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ pub struct PedersenOpening<G: CurveGroup> {
3131
impl<G: Group> DLogPoK<G> {
3232
/// proves knowledge of the representations of y1, y2, ... y_n
3333
/// in their respective bases -- bases[1], bases[2], ... bases[n]
34+
/// binding the proof to a presentation message pm
3435
/// optionally, specify a set of positions to assert equality of in the form {(i1,j1), (i2,j2), ...}
3536
/// TODO (perf): shrink the proof size by compressing the responses since they're the same for all the equal positions
3637
pub fn prove(
38+
pm: Option<&[u8]>,
3739
y: &[G],
3840
bases: &[Vec<G>],
3941
scalars: &[Vec<G::ScalarField>],
@@ -50,6 +52,8 @@ impl<G: Group> DLogPoK<G> {
5052
let mut r = Vec::new();
5153

5254
let mut ts: Transcript = Transcript::new(&[0u8]);
55+
let pm = pm.unwrap_or(b"");
56+
add_to_transcript(&mut ts, b"presentation_message", &pm);
5357

5458
for i in 0..y.len() {
5559
let mut ri = Vec::new();
@@ -112,6 +116,7 @@ impl<G: Group> DLogPoK<G> {
112116

113117
pub fn verify(
114118
&self,
119+
pm: Option<&[u8]>,
115120
bases: &[Vec<G>],
116121
y: &[G],
117122
eq_pos: Option<Vec<(usize, usize)>>,
@@ -123,6 +128,8 @@ impl<G: Group> DLogPoK<G> {
123128
// serialize and hash the bases, k and y
124129
let dl_verify_timer = start_timer!(|| format!("DlogPoK verify y.len = {}", y.len()));
125130
let mut ts: Transcript = Transcript::new(&[0u8]);
131+
let pm = pm.unwrap_or(b"");
132+
add_to_transcript(&mut ts, b"presentation_message", &pm);
126133

127134
let mut recomputed_k = Vec::new();
128135
for i in 0..y.len() {
@@ -227,20 +234,45 @@ mod tests {
227234
scalars[i] = F::rand(rng);
228235
y += bases[i] * scalars[i];
229236
}
237+
238+
let pm = "some presentation message".as_bytes();
239+
230240
let pok = DLogPoK::<G1>::prove(
241+
Some(pm),
231242
&[y, y],
232243
&[bases.clone(), bases.clone()],
233244
&[scalars.clone(), scalars.clone()],
234245
Some(vec![(0, 1), (1, 1)]),
235246
);
236247

248+
// verify with the wrong bases
249+
let wrong_bases = vec![G1::zero(); num_terms];
250+
let wrong_bases_result = pok.verify(
251+
Some(pm),
252+
&[wrong_bases.clone(), wrong_bases.clone()],
253+
&[y, y],
254+
Some(vec![(0, 1), (1, 1)]),
255+
);
256+
assert!(!wrong_bases_result, "Verification should fail with the wrong bases");
257+
258+
// verify with the wrong pm
259+
let wrong_pm = "wrong presentation message".as_bytes();
260+
let wrong_pm_result = pok.verify(
261+
Some(wrong_pm),
262+
&[bases.clone(), bases.clone()],
263+
&[y, y],
264+
Some(vec![(0, 1), (1, 1)]),
265+
);
266+
assert!(!wrong_pm_result, "Verification should fail with the wrong presentation message");
267+
268+
// successful verification
237269
let result = pok.verify(
270+
Some(pm),
238271
&[bases.clone(), bases.clone()],
239272
&[y, y],
240273
Some(vec![(0, 1), (1, 1)]),
241274
);
242275

243276
assert!(result);
244277
}
245-
246278
}

creds/src/groth16rand.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl<E: Pairing> ClientState<E> {
9393
self.serialize_uncompressed(buf_writer).unwrap();
9494
}
9595

96-
pub fn show_groth16(&mut self, io_types: &[PublicIOType]) -> ShowGroth16<E>
96+
pub fn show_groth16(&mut self, pm: Option<&[u8]>, io_types: &[PublicIOType]) -> ShowGroth16<E>
9797
where
9898
<E as Pairing>::G1: CurveGroup + VariableBaseMSM,
9999
{
@@ -167,7 +167,7 @@ impl<E: Pairing> ClientState<E> {
167167
// com_l = l1^input1 l2^input2 ... ln^input_n g^z
168168
// optimized to ignore public inputs
169169

170-
let pok_inputs = DLogPoK::<E::G1>::prove(&y, &bases, &scalars, None);
170+
let pok_inputs = DLogPoK::<E::G1>::prove(pm, &y, &bases, &scalars, None);
171171

172172
end_timer!(groth16_timer);
173173

@@ -222,6 +222,7 @@ impl<E: Pairing> ShowGroth16<E> {
222222
&self,
223223
vk: &VerifyingKey<E>,
224224
pvk: &PreparedVerifyingKey<E>,
225+
pm: Option<&[u8]>,
225226
io_types: &[PublicIOType],
226227
public_inputs: &[E::ScalarField],
227228
) -> bool
@@ -284,7 +285,7 @@ impl<E: Pairing> ShowGroth16<E> {
284285
};
285286
end_timer!(t);
286287

287-
let dlog_pok_valid = self.pok_inputs.verify(&bases, &y, None);
288+
let dlog_pok_valid = self.pok_inputs.verify(pm, &bases, &y, None);
288289

289290
end_timer!(groth16_timer);
290291

creds/src/lib.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ pub fn create_client_state(paths : &CachePaths, prover_inputs: &GenericInputsJSO
247247
Ok(client_state)
248248
}
249249

250-
pub fn create_show_proof(client_state: &mut ClientState<ECPairing>, range_pk : &RangeProofPK<ECPairing>, io_locations: &IOLocations) -> ShowProof<ECPairing>
250+
pub fn create_show_proof(client_state: &mut ClientState<ECPairing>, range_pk : &RangeProofPK<ECPairing>, pm: Option<&[u8]>, io_locations: &IOLocations) -> ShowProof<ECPairing>
251251
{
252252
// Create Groth16 rerandomized proof for showing
253253
let exp_value_pos = io_locations.get_io_location("exp_value").unwrap();
@@ -259,7 +259,7 @@ pub fn create_show_proof(client_state: &mut ClientState<ECPairing>, range_pk : &
259259

260260
let revealed_inputs = vec![client_state.inputs[email_value_pos-1]];
261261

262-
let show_groth16 = client_state.show_groth16(&io_types);
262+
let show_groth16 = client_state.show_groth16(pm, &io_types);
263263

264264
// Create fresh range proof
265265
let time_sec = SystemTime::now()
@@ -279,7 +279,7 @@ pub fn create_show_proof(client_state: &mut ClientState<ECPairing>, range_pk : &
279279
ShowProof{ show_groth16, show_range, show_range2: None, revealed_inputs, inputs_len: client_state.inputs.len(), cur_time: time_sec}
280280
}
281281

282-
pub fn create_show_proof_mdl(client_state: &mut ClientState<ECPairing>, range_pk : &RangeProofPK<ECPairing>, io_locations: &IOLocations, age: usize) -> ShowProof<ECPairing>
282+
pub fn create_show_proof_mdl(client_state: &mut ClientState<ECPairing>, range_pk : &RangeProofPK<ECPairing>, pm: Option<&[u8]>, io_locations: &IOLocations, age: usize) -> ShowProof<ECPairing>
283283
{
284284
// Create Groth16 rerandomized proof for showing
285285
let valid_until_value_pos = io_locations.get_io_location("valid_until_value").unwrap();
@@ -291,7 +291,7 @@ pub fn create_show_proof_mdl(client_state: &mut ClientState<ECPairing>, range_pk
291291

292292
let revealed_inputs : Vec<<ECPairing as Pairing>::ScalarField> = vec![];
293293

294-
let show_groth16 = client_state.show_groth16(&io_types);
294+
let show_groth16 = client_state.show_groth16(pm, &io_types);
295295

296296
// Create fresh range proof for validUntil
297297
let time_sec = SystemTime::now()
@@ -316,7 +316,7 @@ pub fn create_show_proof_mdl(client_state: &mut ClientState<ECPairing>, range_pk
316316
ShowProof{ show_groth16, show_range, show_range2: Some(show_range2), revealed_inputs, inputs_len: client_state.inputs.len(), cur_time: time_sec}
317317
}
318318

319-
pub fn verify_show(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<ECPairing>) -> (bool, String)
319+
pub fn verify_show(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<ECPairing>, pm: Option<&[u8]>) -> (bool, String)
320320
{
321321
let io_locations = IOLocations::new_from_str(&vp.io_locations_str);
322322
let exp_value_pos = io_locations.get_io_location("exp_value").unwrap();
@@ -341,7 +341,7 @@ pub fn verify_show(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<ECPai
341341
// }
342342

343343
let verify_timer = std::time::Instant::now();
344-
let ret = show_proof.show_groth16.verify(&vp.vk, &vp.pvk, &io_types, &inputs);
344+
let ret = show_proof.show_groth16.verify(&vp.vk, &vp.pvk, pm, &io_types, &inputs);
345345
if !ret {
346346
println!("show_groth16.verify failed");
347347
return (false, "".to_string());
@@ -392,7 +392,7 @@ pub fn verify_show(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<ECPai
392392
(true, domain)
393393
}
394394

395-
pub fn verify_show_mdl(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<ECPairing>, age: usize) -> (bool, String)
395+
pub fn verify_show_mdl(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<ECPairing>, pm: Option<&[u8]>, age: usize) -> (bool, String)
396396
{
397397
let io_locations = IOLocations::new_from_str(&vp.io_locations_str);
398398
let valid_until_value_pos = io_locations.get_io_location("valid_until_value").unwrap();
@@ -418,7 +418,12 @@ pub fn verify_show_mdl(vp : &VerifierParams<ECPairing>, show_proof: &ShowProof<E
418418
// }
419419

420420
let verify_timer = std::time::Instant::now();
421-
show_proof.show_groth16.verify(&vp.vk, &vp.pvk, &io_types, &inputs);
421+
show_proof.show_groth16.verify(&vp.vk, &vp.pvk, pm, &io_types, &inputs);
422+
let ret = show_proof.show_groth16.verify(&vp.vk, &vp.pvk, pm, &io_types, &inputs);
423+
if !ret {
424+
println!("show_groth16.verify failed");
425+
return (false, "".to_string());
426+
}
422427
let cur_time = Fr::from(show_proof.cur_time);
423428
let now_seconds = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
424429
let delta =
@@ -533,12 +538,13 @@ mod tests {
533538
let mut client_state: ClientState<CrescentPairing> = read_from_file(&paths.client_state).unwrap();
534539

535540
println!("Running show");
541+
let pm = "some presentation message".as_bytes();
536542
let io_locations = IOLocations::new(&paths.io_locations);
537543
let range_pk : RangeProofPK<CrescentPairing> = read_from_file(&paths.range_pk).unwrap();
538544
let show_proof = if client_state.credtype == "mdl" {
539-
create_show_proof_mdl(&mut client_state, &range_pk, &io_locations, MDL_AGE_GT)
545+
create_show_proof_mdl(&mut client_state, &range_pk, Some(pm), &io_locations, MDL_AGE_GT)
540546
} else {
541-
create_show_proof(&mut client_state, &range_pk, &io_locations)
547+
create_show_proof(&mut client_state, &range_pk, Some(pm), &io_locations)
542548
};
543549

544550
write_to_file(&show_proof, &paths.show_proof);
@@ -554,9 +560,9 @@ mod tests {
554560
let vp = VerifierParams{vk, pvk, range_vk, io_locations_str, issuer_pem};
555561

556562
let (verify_result, _data) = if show_proof.show_range2.is_some() {
557-
verify_show_mdl(&vp, &show_proof, MDL_AGE_GT)
563+
verify_show_mdl(&vp, &show_proof, Some(pm), MDL_AGE_GT)
558564
} else {
559-
verify_show(&vp, &show_proof)
565+
verify_show(&vp, &show_proof, Some(pm))
560566
};
561567
assert!(verify_result);
562568
}

creds/src/main.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ fn main() {
3535
let base_path = root.join(name_path);
3636
run_prover(base_path);
3737
}
38-
Command::Show { name } => {
38+
Command::Show { name, presentation_message } => {
3939
let name_path = format!("test-vectors/{}", name);
4040
let base_path = root.join(name_path);
41-
run_show(base_path);
41+
run_show(base_path, presentation_message);
4242
}
43-
Command::Verify { name } => {
43+
Command::Verify { name, presentation_message } => {
4444
let name_path = format!("test-vectors/{}", name);
4545
let base_path = root.join(name_path);
46-
run_verifier(base_path);
46+
run_verifier(base_path, presentation_message);
4747
}
4848
}
4949
}
@@ -73,12 +73,16 @@ pub enum Command {
7373
Show {
7474
#[structopt(long)]
7575
name: String,
76+
#[structopt(long, about = "Optional presentation message to include in the proof.")]
77+
presentation_message: Option<String>,
7678
},
7779

7880
#[structopt(about = "Verifier a presentation proof.")]
7981
Verify {
8082
#[structopt(long)]
8183
name: String,
84+
#[structopt(long, about = "Optional presentation message to include in the proof.")]
85+
presentation_message: Option<String>,
8286
},
8387
}
8488

@@ -152,28 +156,29 @@ fn show_proof_size(show_proof: &ShowProof<CrescentPairing>) -> usize {
152156
}
153157

154158
pub fn run_show(
155-
base_path: PathBuf
159+
base_path: PathBuf,
160+
presentation_message: Option<String>
156161
) {
157162
let proof_timer = std::time::Instant::now();
158163
let paths = CachePaths::new(base_path);
159164
let io_locations = IOLocations::new(&paths.io_locations);
160165
let mut client_state: ClientState<CrescentPairing> = read_from_file(&paths.client_state).unwrap();
161166
let range_pk : RangeProofPK<CrescentPairing> = read_from_file(&paths.range_pk).unwrap();
162-
167+
let pm = presentation_message.as_deref().map(|s| s.as_bytes());
168+
163169
let show_proof = if client_state.credtype == "mdl" {
164-
create_show_proof_mdl(&mut client_state, &range_pk, &io_locations, MDL_AGE_GREATER_THAN)
170+
create_show_proof_mdl(&mut client_state, &range_pk, pm, &io_locations, MDL_AGE_GREATER_THAN)
165171
} else {
166-
create_show_proof(&mut client_state, &range_pk, &io_locations)
172+
create_show_proof(&mut client_state, &range_pk, pm, &io_locations)
167173
};
168174
println!("Proving time: {:?}", proof_timer.elapsed());
169175

170-
//let _ = _show_groth16_proof_size(&show_proof.show_groth16);
171176
let _ = show_proof_size(&show_proof);
172177

173178
write_to_file(&show_proof, &paths.show_proof);
174179
}
175180

176-
pub fn run_verifier(base_path: PathBuf) {
181+
pub fn run_verifier(base_path: PathBuf, presentation_message: Option<String>) {
177182
let paths = CachePaths::new(base_path);
178183
let show_proof : ShowProof<CrescentPairing> = read_from_file(&paths.show_proof).unwrap();
179184
let pvk : PreparedVerifyingKey<CrescentPairing> = read_from_file(&paths.groth16_pvk).unwrap();
@@ -183,11 +188,12 @@ pub fn run_verifier(base_path: PathBuf) {
183188
let issuer_pem = std::fs::read_to_string(&paths.issuer_pem).unwrap();
184189

185190
let vp = VerifierParams{vk, pvk, range_vk, io_locations_str, issuer_pem};
191+
let pm = presentation_message.as_deref().map(|s| s.as_bytes());
186192

187193
let (verify_result, data) = if show_proof.show_range2.is_some() {
188-
verify_show_mdl(&vp, &show_proof, MDL_AGE_GREATER_THAN)
194+
verify_show_mdl(&vp, &show_proof, pm, MDL_AGE_GREATER_THAN)
189195
} else {
190-
verify_show(&vp, &show_proof)
196+
verify_show(&vp, &show_proof, pm)
191197
};
192198

193199
if verify_result {

creds/src/rangeproof.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ impl<E: Pairing> RangeProof<E> {
230230

231231
// Link com_f to ped_open via a DLEQ proof
232232
let dleq_proof = DLogPoK::<E::G1>::prove(
233+
None, // TODO: should we add a presentation message here? (use the c from the dlog proof?)
233234
&[ped_open.c, com_f.0.into()],
234235
&[
235236
ped_open
@@ -415,6 +416,7 @@ impl<E: Pairing> RangeProof<E> {
415416
self
416417
.dleq_proof
417418
.verify(
419+
None, // TODO: should we add a presentation message here?
418420
&[bases.to_vec(), vk.com_f_basis.to_vec(),],
419421
&[*ped_com, self.com_f.0.into()],
420422
Some(vec![(0, 0), (1, 3)]),
@@ -517,8 +519,9 @@ mod tests {
517519
io_types[0] = PublicIOType::Revealed;
518520
io_types[1] = PublicIOType::Committed;
519521

520-
let showing = client_state.show_groth16(&io_types);
521-
showing.verify(&vk, &pvk, &io_types, &[inputs[0]]);
522+
let pm = "some presentation message".as_bytes();
523+
let showing = client_state.show_groth16(Some(pm), &io_types);
524+
showing.verify(&vk, &pvk, Some(pm), &io_types, &[inputs[0]]);
522525

523526
println!(
524527
"Committed to input: {}",

forks/circom-compat/src/circom/qap.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(unexpected_cfgs)] // Disable warnings emitted by use of cfg_iter*
2+
13
use ark_ff::PrimeField;
24
use ark_groth16::r1cs_to_qap::{evaluate_constraint, LibsnarkReduction, R1CSToQAP};
35
use ark_poly::EvaluationDomain;

0 commit comments

Comments
 (0)