From e1621a0e79ee21198072e01cc4e6de8ba3e052de Mon Sep 17 00:00:00 2001 From: "Omar S. Navarro Leija" Date: Tue, 18 Jul 2023 16:37:38 -0700 Subject: [PATCH] Relax Ownership Requirements for piprm. --- src/auxinfo/auxinfo_commit.rs | 6 +- src/auxinfo/info.rs | 4 +- src/auxinfo/participant.rs | 2 +- src/ring_pedersen.rs | 12 ++-- src/zkp/piprm.rs | 112 +++++++++++++++------------------- 5 files changed, 64 insertions(+), 72 deletions(-) diff --git a/src/auxinfo/auxinfo_commit.rs b/src/auxinfo/auxinfo_commit.rs index c1e76cbc..a751ee3e 100644 --- a/src/auxinfo/auxinfo_commit.rs +++ b/src/auxinfo/auxinfo_commit.rs @@ -93,7 +93,9 @@ impl CommitmentScheme { rng.fill_bytes(rid.as_mut_slice()); rng.fill_bytes(u_i.as_mut_slice()); - public_key.verify(&auxinfo_participant.retrieve_context())?; + public_key + .clone() + .verify(&auxinfo_participant.retrieve_context())?; if auxinfo_participant.id() != public_key.participant() { error!("Created auxinfo commitment scheme with different participant IDs in the sender and public_key fields"); return Err(InternalError::InternalInvariantFailed); @@ -119,7 +121,7 @@ impl CommitmentScheme { let scheme: CommitmentScheme = deserialize!(&message.unverified_bytes)?; // Public parameters in this decommit must be consistent with each other - scheme.public_key.verify(context)?; + scheme.clone().public_key.verify(context)?; // Owner must be consistent across message, public keys, and decommit if scheme.public_key.participant() != scheme.pid { diff --git a/src/auxinfo/info.rs b/src/auxinfo/info.rs index 97b9b5a7..c061d597 100644 --- a/src/auxinfo/info.rs +++ b/src/auxinfo/info.rs @@ -165,7 +165,7 @@ impl AuxInfoPublic { pk: encryption_key, params, }; - public.verify(context)?; + public.clone().verify(context)?; Ok(public) } @@ -184,7 +184,7 @@ impl AuxInfoPublic { /// Verifies that the public key's modulus matches the ZKSetupParameters /// modulus N, and that the parameters have appropriate s and t values. #[instrument(skip_all, err(Debug))] - pub(crate) fn verify(&self, context: &impl ProofContext) -> Result<()> { + pub(crate) fn verify(self, context: &impl ProofContext) -> Result<()> { if self.pk.modulus() != self.params.scheme().modulus() { error!("Mismatch between public key modulus and setup parameters modulus"); return Err(InternalError::Serialization); diff --git a/src/auxinfo/participant.rs b/src/auxinfo/participant.rs index 3b69efd2..c77bde7e 100644 --- a/src/auxinfo/participant.rs +++ b/src/auxinfo/participant.rs @@ -806,7 +806,7 @@ mod tests { let public_key = output.find_public(pid); assert!(public_key.is_some()); // Check that it's valid while we're here. - assert!(public_key.unwrap().verify(&context).is_ok()); + assert!(public_key.unwrap().clone().verify(&context).is_ok()); publics_for_pid.push(public_key.unwrap()); } diff --git a/src/ring_pedersen.rs b/src/ring_pedersen.rs index 95601177..cbaabd73 100644 --- a/src/ring_pedersen.rs +++ b/src/ring_pedersen.rs @@ -17,7 +17,7 @@ use crate::{ utils::{modpow, random_plusminus_scaled, random_positive_bn}, zkp::{ piprm::{PiPrmProof, PiPrmSecret}, - Proof, ProofContext, + Proof2, ProofContext, }, }; use bytemuck::TransparentWrapper; @@ -155,17 +155,19 @@ impl VerifiedRingPedersen { rng: &mut (impl RngCore + CryptoRng), ) -> Result { let (scheme, lambda, totient) = RingPedersen::extract(sk, rng)?; - let secrets = PiPrmSecret::new(lambda, totient); + let secrets = PiPrmSecret::new(&lambda, &totient); let mut transcript = Transcript::new(b"PiPrmProof"); - let proof = PiPrmProof::prove(&scheme, &secrets, context, &mut transcript, rng)?; + let proof = PiPrmProof::prove(&scheme, secrets, context, &mut transcript, rng)?; Ok(Self { scheme, proof }) } /// Verifies that the underlying [`RingPedersen`] commitment scheme was /// constructed correctly according to the associated [`PiPrmProof`]. - pub(crate) fn verify(&self, context: &impl ProofContext) -> Result<()> { + pub(crate) fn verify(self, context: &impl ProofContext) -> Result<()> { let mut transcript = Transcript::new(b"PiPrmProof"); - self.proof.verify(self.scheme(), context, &mut transcript) + // Note we directly borrow the `self.scheme` field instead of using the + // `.scheme()` method to avoid Rust lifetime issues. + self.proof.verify(&self.scheme, context, &mut transcript) } /// Returns the underlying [`RingPedersen`] commitment scheme associated diff --git a/src/zkp/piprm.rs b/src/zkp/piprm.rs index 1189c24a..8da992d2 100644 --- a/src/zkp/piprm.rs +++ b/src/zkp/piprm.rs @@ -26,7 +26,7 @@ use crate::{ errors::*, ring_pedersen::RingPedersen, utils::*, - zkp::{Proof, ProofContext}, + zkp::{Proof2, ProofContext}, }; use libpaillier::unknown_order::BigNumber; use merlin::Transcript; @@ -34,7 +34,6 @@ use rand::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; use tracing::error; -use zeroize::ZeroizeOnDrop; // Soundness parameter. const SOUNDNESS: usize = crate::parameters::SOUNDNESS_PARAMETER; @@ -56,16 +55,15 @@ pub(crate) struct PiPrmProof { /// This is comprised of two components: /// 1. The secret exponent used when generating the [`RingPedersen`] parameters. /// 2. Euler's totient of [`RingPedersen::modulus`]. -#[derive(ZeroizeOnDrop)] -pub(crate) struct PiPrmSecret { +pub(crate) struct PiPrmSecret<'a> { /// The secret exponent that correlates [`RingPedersen`] parameters /// [`s`](RingPedersen::s) and [`t`](RingPedersen::t). - exponent: BigNumber, + exponent: &'a BigNumber, /// Euler's totient of [`RingPedersen::modulus`]. - totient: BigNumber, + totient: &'a BigNumber, } -impl Debug for PiPrmSecret { +impl<'a> Debug for PiPrmSecret<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("piprm::PiPrmSecret") .field("exponent", &"[redacted]") @@ -74,9 +72,9 @@ impl Debug for PiPrmSecret { } } -impl PiPrmSecret { +impl<'a> PiPrmSecret<'a> { /// Collect the secret knowledge for proving [`PiPrmProof`]. - pub(crate) fn new(exponent: BigNumber, totient: BigNumber) -> Self { + pub(crate) fn new(exponent: &'a BigNumber, totient: &'a BigNumber) -> Self { Self { exponent, totient } } } @@ -98,20 +96,20 @@ fn generate_challenge_bytes( Ok(challenges.into()) } -impl Proof for PiPrmProof { - type CommonInput = RingPedersen; - type ProverSecret = PiPrmSecret; +impl Proof2 for PiPrmProof { + type CommonInput<'a> = &'a RingPedersen; + type ProverSecret<'a> = PiPrmSecret<'a>; #[cfg_attr(feature = "flame_it", flame("PiPrmProof"))] fn prove( - input: &Self::CommonInput, - secret: &Self::ProverSecret, + input: Self::CommonInput<'_>, + secret: Self::ProverSecret<'_>, context: &impl ProofContext, transcript: &mut Transcript, rng: &mut R, ) -> Result { // Sample secret exponents `a_i ← Z[ɸ(N)]`. let secret_exponents: Vec<_> = - std::iter::repeat_with(|| random_positive_bn(rng, &secret.totient)) + std::iter::repeat_with(|| random_positive_bn(rng, secret.totient)) .take(SOUNDNESS) .collect(); // Compute commitments values `A_i = t^{a_i} mod N`. @@ -126,7 +124,7 @@ impl Proof for PiPrmProof { .zip(secret_exponents) .map(|(e, a)| { if e % 2 == 1 { - a.modadd(&secret.exponent, &secret.totient) + a.modadd(secret.exponent, secret.totient) } else { a } @@ -142,8 +140,8 @@ impl Proof for PiPrmProof { #[cfg_attr(feature = "flame_it", flame("PiPrmProof"))] fn verify( - &self, - input: &Self::CommonInput, + self, + input: Self::CommonInput<'_>, context: &impl ProofContext, transcript: &mut Transcript, ) -> Result<()> { @@ -193,15 +191,19 @@ mod tests { use crate::{paillier::DecryptionKey, utils::testing::init_testing, zkp::BadContext}; use rand::Rng; + /// Make a transcript for PiPrmProof. + fn transcript() -> Transcript { + Transcript::new(b"PiPrmProof") + } + fn random_ring_pedersen_proof( rng: &mut R, ) -> Result<(RingPedersen, PiPrmProof, BigNumber, BigNumber)> { let (sk, _, _) = DecryptionKey::new(rng).unwrap(); let (scheme, lambda, totient) = RingPedersen::extract(&sk, rng)?; - let secrets = PiPrmSecret::new(lambda.clone(), totient.clone()); - let mut transcript = Transcript::new(b"PiPrmProof"); + let secrets = PiPrmSecret::new(&lambda, &totient); - let proof = PiPrmProof::prove(&scheme, &secrets, &(), &mut transcript, rng)?; + let proof = PiPrmProof::prove(&scheme, secrets, &(), &mut transcript(), rng)?; Ok((scheme, proof, lambda, totient)) } @@ -209,9 +211,7 @@ mod tests { fn piprm_proof_verifies() -> Result<()> { let mut rng = init_testing(); let (input, proof, _, _) = random_ring_pedersen_proof(&mut rng)?; - let mut transcript = Transcript::new(b"PiPrmProof"); - - proof.verify(&input, &(), &mut transcript) + proof.verify(&input, &(), &mut transcript()) } #[test] @@ -219,9 +219,8 @@ mod tests { let context = BadContext {}; let mut rng = init_testing(); let (input, proof, _, _) = random_ring_pedersen_proof(&mut rng)?; - let mut transcript = Transcript::new(b"PiPrmProof"); - let result = proof.verify(&input, &context, &mut transcript); + let result = proof.verify(&input, &context, &mut transcript()); assert!(result.is_err()); Ok(()) } @@ -232,9 +231,8 @@ mod tests { let serialized = bincode::serialize(&proof).unwrap(); let deserialized: PiPrmProof = bincode::deserialize(&serialized).unwrap(); assert_eq!(serialized, bincode::serialize(&deserialized).unwrap()); - let mut transcript = Transcript::new(b"PiPrmProof"); - deserialized.verify(&input, &(), &mut transcript) + deserialized.verify(&input, &(), &mut transcript()) } #[test] @@ -242,9 +240,7 @@ mod tests { let mut rng = init_testing(); let (input, proof, _, _) = random_ring_pedersen_proof(&mut rng)?; // Validate that the proof is okay. - let mut transcript = Transcript::new(b"PiPrmProof"); - - assert!(proof.verify(&input, &(), &mut transcript).is_ok()); + assert!(proof.clone().verify(&input, &(), &mut transcript()).is_ok()); // Test that too short vectors fail. { let mut bad_proof = proof.clone(); @@ -253,8 +249,7 @@ mod tests { .into_iter() .take(SOUNDNESS - 1) .collect(); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } { let mut bad_proof = proof.clone(); @@ -263,8 +258,7 @@ mod tests { .into_iter() .take(SOUNDNESS - 1) .collect(); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } { let mut bad_proof = proof.clone(); @@ -273,8 +267,7 @@ mod tests { .into_iter() .take(SOUNDNESS - 1) .collect(); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } // Test that too long vectors fail. { @@ -282,22 +275,19 @@ mod tests { bad_proof .commitments .push(random_positive_bn(&mut rng, input.modulus())); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } { let mut bad_proof = proof.clone(); bad_proof.challenge_bytes.push(rng.gen::()); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } { let mut bad_proof = proof; bad_proof .responses .push(random_positive_bn(&mut rng, input.modulus())); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } Ok(()) } @@ -307,15 +297,13 @@ mod tests { let mut rng = init_testing(); let (input, proof, _, totient) = random_ring_pedersen_proof(&mut rng)?; let bad_lambda = random_positive_bn(&mut rng, &totient); - let secrets = PiPrmSecret::new(bad_lambda, totient); - let mut transcript = Transcript::new(b"PiPrmProof"); + let secrets = PiPrmSecret::new(&bad_lambda, &totient); + + let bad_proof = PiPrmProof::prove(&input, secrets, &(), &mut transcript(), &mut rng)?; + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); - let bad_proof = PiPrmProof::prove(&input, &secrets, &(), &mut transcript, &mut rng)?; - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); // Validate that the original proof is okay. - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(proof.verify(&input, &(), &mut transcript).is_ok()); + assert!(proof.verify(&input, &(), &mut transcript()).is_ok()); Ok(()) } @@ -326,12 +314,14 @@ mod tests { let (input, proof, _, _) = random_ring_pedersen_proof(&mut rng)?; let (bad_input, _, _, _) = random_ring_pedersen_proof(&mut rng)?; - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(proof.verify(&bad_input, &(), &mut transcript).is_err()); + assert!(proof + .clone() + .verify(&bad_input, &(), &mut transcript()) + .is_err()); + // Validate that the original proof is okay. - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(proof.verify(&input, &(), &mut transcript).is_ok()); + assert!(proof.verify(&input, &(), &mut transcript()).is_ok()); Ok(()) } @@ -344,8 +334,7 @@ mod tests { for i in 0..SOUNDNESS { let mut bad_proof = proof.clone(); bad_proof.commitments[i] = random_positive_bn(&mut rng, input.modulus()); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } for i in 0..SOUNDNESS { let mut bad_proof = proof.clone(); @@ -353,18 +342,17 @@ mod tests { while bad_proof.challenge_bytes[i] == valid { bad_proof.challenge_bytes[i] = rng.gen::(); } - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } for i in 0..SOUNDNESS { let mut bad_proof = proof.clone(); bad_proof.responses[i] = random_positive_bn(&mut rng, input.modulus()); - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(bad_proof.verify(&input, &(), &mut transcript).is_err()); + + assert!(bad_proof.verify(&input, &(), &mut transcript()).is_err()); } // Validate that the original proof is okay. - let mut transcript = Transcript::new(b"PiPrmProof"); - assert!(proof.verify(&input, &(), &mut transcript).is_ok()); + assert!(proof.verify(&input, &(), &mut transcript()).is_ok()); Ok(()) }