From 408beaeaa0954136b8be111232163161bc765083 Mon Sep 17 00:00:00 2001 From: Aaron Feickert <66188213+AaronFeickert@users.noreply.github.com> Date: Sat, 10 Aug 2024 16:29:51 -0500 Subject: [PATCH] Moves variable-time proving behind a feature gate --- Cargo.toml | 4 ++++ README.md | 5 +++-- src/lib.rs | 6 ++++-- src/parallel/proof.rs | 48 ++++++++++++++++++++----------------------- src/proof.rs | 38 ++++++++++++++++------------------ src/util.rs | 1 + 6 files changed, 52 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 509e8a8..71a7366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,8 @@ rand_chacha = { version = "0.3.1", default-features = false } default = ["rand", "std"] # Adds proof serialization and deserialization via [`borsh`](https://crates.io/crates/borsh) borsh = ["dep:borsh"] +# Adds variable-time prover functionality that should only be used if you absolutely know what you're doing +hazmat = [] # Adds additional prover functionality that supplies a cryptographically-secure random number generator rand = ["rand_core/getrandom"] # Adds proof serialization and deserialization via [`serde`](https://crates.io/crates/serde) @@ -41,10 +43,12 @@ std = ["blake3/std", "borsh?/std", "itertools/use_std", "merlin/std", "rand_core [[bench]] name = "triptych" harness = false +required-features = ["hazmat"] [[bench]] name = "parallel" harness = false +required-features = ["hazmat"] [[example]] name = "ringct" diff --git a/README.md b/README.md index 6106604..cba4645 100644 --- a/README.md +++ b/README.md @@ -37,13 +37,14 @@ There are several features available. | Feature | Default? | Description | | :--- | :---: | :--- | | `borsh` | | Adds proof serialization and deserialization via [`borsh`](https://crates.io/crates/borsh) | -| `serde` | | Adds proof serialization and deserialization via [`serde`](https://crates.io/crates/serde) | +| `hazmat` | | Adds variable-time prover functionality that should only be used if you absolutely know what you're doing | | `rand` | ✓ | Adds additional prover functionality that supplies a cryptographically-secure random number generator | +| `serde` | | Adds proof serialization and deserialization via [`serde`](https://crates.io/crates/serde) | | `std` | ✓ | Adds corresponding dependency features | The underlying [curve library](https://crates.io/crates/curve25519-dalek) chooses an arithmetic backend based on CPU feature detection. Using a nightly compiler broadens the backend set, and may provide better performance. -You can examine performance using the benchmarks: either `cargo bench` or `cargo +nightly bench`. +You can examine performance using the benchmarks: either `cargo bench --all-features` or `cargo +nightly bench --all-features`. Proofs support a custom serialization format designed to be efficient and canonical. This is used for `borsh` serialization and deserialization, or can be accessed directly. diff --git a/src/lib.rs b/src/lib.rs index cee6183..a90edda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,13 +41,15 @@ //! | Feature | Default? | Description | //! | :--- | :---: | :--- | //! | `borsh` | | Adds proof serialization and deserialization via [`borsh`](https://crates.io/crates/borsh) | -//! | `serde` | | Adds proof serialization and deserialization via [`serde`](https://crates.io/crates/serde) | +//! | `hazmat` | | Adds variable-time prover functionality that should only be used if you absolutely know what you're doing | //! | `rand` | ✓ | Adds additional prover functionality that supplies a cryptographically-secure random number generator | +//! | `serde` | | Adds proof serialization and deserialization via [`serde`](https://crates.io/crates/serde) | //! | `std` | ✓ | Adds corresponding dependency features | //! //! The underlying [curve library](https://crates.io/crates/curve25519-dalek) chooses an arithmetic backend based on CPU feature detection. //! Using a nightly compiler broadens the backend set, and may provide better performance. -//! You can examine performance using the benchmarks: either `cargo bench` or `cargo +nightly bench`. +//! You can examine performance using the benchmarks: either `cargo bench --all-features` or `cargo +nightly bench +//! --all-features`. //! //! Proofs support a custom serialization format designed to be efficient and canonical. //! This is used for `borsh` serialization and deserialization, or can be accessed directly. diff --git a/src/parallel/proof.rs b/src/parallel/proof.rs index 9b7da69..78e451a 100644 --- a/src/parallel/proof.rs +++ b/src/parallel/proof.rs @@ -93,7 +93,7 @@ impl TriptychProof { /// You must also supply a [`Transcript`] `transcript`. /// /// This function specifically avoids constant-time operations for efficiency. - #[cfg(feature = "rand")] + #[cfg(all(feature = "rand", feature = "hazmat"))] pub fn prove_vartime( witness: &TriptychWitness, statement: &TriptychStatement, @@ -113,6 +113,7 @@ impl TriptychProof { /// You must also supply a [`CryptoRngCore`] random number generator `rng` and a [`Transcript`] `transcript`. /// /// This function specifically avoids constant-time operations for efficiency. + #[cfg(feature = "hazmat")] pub fn prove_with_rng_vartime( witness: &TriptychWitness, statement: &TriptychStatement, @@ -1143,7 +1144,7 @@ mod test { } #[test] - #[cfg(feature = "rand")] + #[cfg(all(feature = "rand", feature = "hazmat"))] #[allow(non_snake_case, non_upper_case_globals)] fn test_prove_verify_vartime() { // Generate data @@ -1158,6 +1159,7 @@ mod test { } #[test] + #[cfg(feature = "hazmat")] #[allow(non_snake_case, non_upper_case_globals)] fn test_prove_verify_vartime_with_rng() { // Generate data @@ -1183,9 +1185,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate and verify a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); assert!(proof.verify(&statements[0], &mut transcripts[0]).is_ok()); // Serialize the proof @@ -1207,9 +1208,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate and verify a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); assert!(proof.verify(&statements[0], &mut transcripts[0]).is_ok()); // Serialize the proof @@ -1232,7 +1232,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Verify the batch with and without blame @@ -1261,7 +1261,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Manipulate a transcript so the corresponding proof is invalid @@ -1285,7 +1285,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Iteratively manipulate each transcript to make the corresponding proof invalid @@ -1319,7 +1319,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Manipulate some of the transcripts to make the corresponding proofs invalid @@ -1346,8 +1346,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0]) - .unwrap(); + let proof = + TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0]).unwrap(); // Generate a modified transcript let mut evil_transcript = Transcript::new(b"Evil transcript"); @@ -1366,9 +1366,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); // Generate a statement with a modified input set let mut M = statements[0].get_input_set().get_keys().to_vec(); @@ -1398,9 +1397,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); // Generate a statement with a modified input set let M = statements[0].get_input_set().get_keys().to_vec(); @@ -1430,9 +1428,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); // Generate a statement with a modified linking tag let evil_statement = TriptychStatement::new( @@ -1457,9 +1454,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); // Generate a statement with a modified offset let evil_statement = TriptychStatement::new( diff --git a/src/proof.rs b/src/proof.rs index be7e01f..adaad8a 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -93,7 +93,7 @@ impl TriptychProof { /// You must also supply a [`Transcript`] `transcript`. /// /// This function specifically avoids constant-time operations for efficiency. - #[cfg(feature = "rand")] + #[cfg(all(feature = "rand", feature = "hazmat"))] pub fn prove_vartime( witness: &TriptychWitness, statement: &TriptychStatement, @@ -113,6 +113,7 @@ impl TriptychProof { /// You must also supply a [`CryptoRngCore`] random number generator `rng` and a [`Transcript`] `transcript`. /// /// This function specifically avoids constant-time operations for efficiency. + #[cfg(feature = "hazmat")] pub fn prove_with_rng_vartime( witness: &TriptychWitness, statement: &TriptychStatement, @@ -1051,7 +1052,7 @@ mod test { } #[test] - #[cfg(feature = "rand")] + #[cfg(all(feature = "rand", feature = "hazmat"))] #[allow(non_snake_case, non_upper_case_globals)] fn test_prove_verify_vartime() { // Generate data @@ -1066,6 +1067,7 @@ mod test { } #[test] + #[cfg(feature = "hazmat")] #[allow(non_snake_case, non_upper_case_globals)] fn test_prove_verify_vartime_with_rng() { // Generate data @@ -1091,9 +1093,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate and verify a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); assert!(proof.verify(&statements[0], &mut transcripts[0]).is_ok()); // Serialize the proof @@ -1115,9 +1116,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate and verify a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); assert!(proof.verify(&statements[0], &mut transcripts[0]).is_ok()); // Serialize the proof @@ -1140,7 +1140,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Verify the batch with and without blame @@ -1169,7 +1169,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Manipulate a transcript so the corresponding proof is invalid @@ -1193,7 +1193,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Iteratively manipulate each transcript to make the corresponding proof invalid @@ -1227,7 +1227,7 @@ mod test { // Generate the proofs let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut()) - .map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap()) + .map(|(w, s, t)| TriptychProof::prove_with_rng(w, s, &mut rng, t).unwrap()) .collect::>(); // Manipulate some of the transcripts to make the corresponding proofs invalid @@ -1254,8 +1254,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0]) - .unwrap(); + let proof = + TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0]).unwrap(); // Generate a modified transcript let mut evil_transcript = Transcript::new(b"Evil transcript"); @@ -1274,9 +1274,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); // Generate a statement with a modified input set let mut M = statements[0].get_input_set().get_keys().to_vec(); @@ -1300,9 +1299,8 @@ mod test { let (witnesses, statements, mut transcripts) = generate_data(n, m, 1, &mut rng); // Generate a proof - let proof = - TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) - .unwrap(); + let proof = TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone()) + .unwrap(); // Generate a statement with a modified linking tag let evil_statement = TriptychStatement::new( diff --git a/src/util.rs b/src/util.rs index 95ffbbf..d6d28d2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -12,6 +12,7 @@ use zeroize::Zeroize; /// Options for constant- or variable-time operations. #[derive(Clone, Copy)] +#[allow(dead_code)] pub(crate) enum OperationTiming { /// The operation should attempt to run in constant time Constant,