From 5a75b83453c5575a82b78b3f8f05d3ec0cd2cb04 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Fri, 7 Feb 2025 14:18:19 -0700 Subject: [PATCH] Require using Schnorr proofs from signature proof for predicates (#42) * require using schnorr proofs from signature proof for predicates Signed-off-by: Michael Lodder * minor nits Signed-off-by: Michael Lodder --------- Signed-off-by: Michael Lodder --- src/knox/accumulator/vb20/proof.rs | 16 ++-- src/knox/bbs/pok_signature.rs | 47 +++++------ src/knox/bbs/pok_signature_proof.rs | 83 +++++++++---------- src/knox/bbs/scheme.rs | 2 +- src/knox/ps/pok_signature_proof.rs | 11 ++- src/knox/ps/scheme.rs | 2 +- .../proof_committed_builder.rs | 8 +- .../short_group_traits.rs | 3 +- src/presentation/commitment.rs | 7 -- src/presentation/verifiable_encryption.rs | 6 -- src/presentation/verify.rs | 76 ++++++++++++++++- src/verifier/commitment.rs | 3 +- src/verifier/membership.rs | 7 ++ src/verifier/revocation.rs | 7 ++ src/verifier/signature.rs | 5 +- src/verifier/verifiable_encryption.rs | 3 +- tests/range.rs | 6 ++ 17 files changed, 184 insertions(+), 108 deletions(-) diff --git a/src/knox/accumulator/vb20/proof.rs b/src/knox/accumulator/vb20/proof.rs index e27da79..edeffdb 100644 --- a/src/knox/accumulator/vb20/proof.rs +++ b/src/knox/accumulator/vb20/proof.rs @@ -232,14 +232,14 @@ impl MembershipProofCommitting { /// A ZKP membership proof #[derive(Debug, Default, Copy, Clone, Deserialize, Serialize)] pub struct MembershipProof { - e_c: G1Projective, - t_sigma: G1Projective, - t_rho: G1Projective, - s_sigma: Scalar, - s_rho: Scalar, - s_delta_sigma: Scalar, - s_delta_rho: Scalar, - s_y: Scalar, + pub(crate) e_c: G1Projective, + pub(crate) t_sigma: G1Projective, + pub(crate) t_rho: G1Projective, + pub(crate) s_sigma: Scalar, + pub(crate) s_rho: Scalar, + pub(crate) s_delta_sigma: Scalar, + pub(crate) s_delta_rho: Scalar, + pub(crate) s_y: Scalar, } impl core::fmt::Display for MembershipProof { diff --git a/src/knox/bbs/pok_signature.rs b/src/knox/bbs/pok_signature.rs index 84c7fcb..9de0de3 100644 --- a/src/knox/bbs/pok_signature.rs +++ b/src/knox/bbs/pok_signature.rs @@ -1,10 +1,11 @@ +use crate::error::Error; use crate::knox::bbs::{PokSignatureProof, PublicKey, Signature}; use crate::knox::short_group_sig_core::{ short_group_traits::ProofOfSignatureKnowledgeContribution, *, }; use crate::CredxResult; use blsful::inner_types::{G1Affine, G1Projective, Scalar}; -use elliptic_curve::{group::Curve, Field}; +use elliptic_curve::Field; use merlin::Transcript; use rand_core::*; @@ -14,7 +15,6 @@ pub struct PokSignature { proof: ProofCommittedBuilder, a_bar: G1Projective, b_bar: G1Projective, - commitment: G1Projective, hidden_messages: Vec, } @@ -31,57 +31,48 @@ impl ProofOfSignatureKnowledgeContribution for PokSignature { ) -> CredxResult { let msgs = messages.iter().map(|m| m.get_message()).collect::>(); - let signature_randomizer = Scalar::random(&mut rng); + let r = Scalar::random(&mut rng); + let r_inv = Option::from((-r).invert()).ok_or(Error::InvalidPresentationData)?; + let r_inv_e = r_inv * signature.e; + let b = G1Projective::GENERATOR + G1Projective::sum_of_products(&public_key.y, &msgs); - let a_bar = signature.a * signature_randomizer; - let b_bar = b * signature_randomizer - a_bar * signature.e; + let a_bar = signature.a * r; + let b_bar = b * r - a_bar * signature.e; let mut proof = ProofCommittedBuilder::new(G1Projective::sum_of_products); - let mut points = Vec::with_capacity(msgs.len()); - let mut hidden_messages = Vec::with_capacity(msgs.len()); - let mut revealed_messages = Vec::with_capacity(msgs.len()); + let mut hidden_messages = Vec::with_capacity(msgs.len() + 2); for (i, m) in messages.iter().enumerate() { match m { ProofMessage::Hidden(HiddenMessage::ProofSpecificBlinding(msg)) => { proof.commit_random(public_key.y[i], &mut rng); - hidden_messages.push(*msg * signature_randomizer); + hidden_messages.push(*msg); } ProofMessage::Hidden(HiddenMessage::ExternalBlinding(msg, n)) => { proof.commit(public_key.y[i], *n); - hidden_messages.push(*msg * signature_randomizer); - } - ProofMessage::Revealed(msg) => { - points.push(public_key.y[i]); - revealed_messages.push(*msg); + hidden_messages.push(*msg); } + ProofMessage::Revealed(_) => {} } } - let commitment = - G1Projective::GENERATOR + G1Projective::sum_of_products(&points, &revealed_messages); - proof.commit_random(commitment, &mut rng); - hidden_messages.push(signature_randomizer); proof.commit_random(a_bar, &mut rng); - hidden_messages.push(-signature.e); + hidden_messages.push(r_inv_e); + proof.commit_random(b_bar, &mut rng); + hidden_messages.push(r_inv); Ok(Self { proof, a_bar, b_bar, - commitment, hidden_messages, }) } fn add_proof_contribution(&self, transcript: &mut Transcript) { - transcript.append_message(b"a_bar", self.a_bar.to_affine().to_compressed().as_ref()); - transcript.append_message(b"b_bar", self.b_bar.to_affine().to_compressed().as_ref()); - transcript.append_message( - b"random commitment", - self.commitment.to_affine().to_compressed().as_ref(), - ); + transcript.append_message(b"a_bar", self.a_bar.to_compressed().as_ref()); + transcript.append_message(b"b_bar", self.b_bar.to_compressed().as_ref()); self.proof - .add_challenge_contribution(b"blind commitment", transcript); + .add_challenge_contribution(b"commitment", transcript); } fn generate_proof(self, challenge: Scalar) -> CredxResult { @@ -91,7 +82,7 @@ impl ProofOfSignatureKnowledgeContribution for PokSignature { Ok(PokSignatureProof { a_bar: self.a_bar, b_bar: self.b_bar, - commitment: self.commitment, + t: self.proof.commitment(), proof, }) } diff --git a/src/knox/bbs/pok_signature_proof.rs b/src/knox/bbs/pok_signature_proof.rs index 3247010..c999416 100644 --- a/src/knox/bbs/pok_signature_proof.rs +++ b/src/knox/bbs/pok_signature_proof.rs @@ -17,7 +17,7 @@ use std::collections::{BTreeMap, BTreeSet}; pub struct PokSignatureProof { pub(crate) a_bar: G1Projective, pub(crate) b_bar: G1Projective, - pub(crate) commitment: G1Projective, + pub(crate) t: G1Projective, pub(crate) proof: Vec, } @@ -26,64 +26,58 @@ impl ProofOfSignatureKnowledge for PokSignatureProof { fn add_proof_contribution( &self, - public_key: &Self::PublicKey, - revealed_messages: &[(usize, Scalar)], - challenge: Scalar, + _public_key: &Self::PublicKey, + _revealed_messages: &[(usize, Scalar)], + _challenge: Scalar, transcript: &mut Transcript, ) { - transcript.append_message(b"a_bar", self.a_bar.to_affine().to_compressed().as_ref()); - transcript.append_message(b"b_bar", self.b_bar.to_affine().to_compressed().as_ref()); - transcript.append_message( - b"random commitment", - self.commitment.to_affine().to_compressed().as_ref(), - ); - let mut known = BTreeSet::new(); - for (idx, _) in revealed_messages { - known.insert(*idx); - } - - let mut points = Vec::with_capacity(public_key.y.len() + 2); - for (idx, _) in public_key.y.iter().enumerate() { - if known.contains(&idx) { - continue; - } - points.push(public_key.y[idx]); - } - points.push(self.commitment); - points.push(self.a_bar); - points.push(self.b_bar); - let mut scalars = self.proof.clone(); - scalars.push(-challenge); - let commitment = G1Projective::sum_of_products(&points, &scalars); - transcript.append_message( - b"blind commitment", - commitment.to_affine().to_compressed().as_ref(), - ); + transcript.append_message(b"a_bar", self.a_bar.to_compressed().as_ref()); + transcript.append_message(b"b_bar", self.b_bar.to_compressed().as_ref()); + transcript.append_message(b"commitment", self.t.to_compressed().as_ref()); } fn verify( &self, - revealed_messages: &[(usize, Scalar)], public_key: &Self::PublicKey, + revealed_messages: &[(usize, Scalar)], + challenge: Scalar, ) -> CredxResult<()> { - if (self.a_bar.is_identity() | self.b_bar.is_identity()).into() { + if (self.a_bar.is_identity() | self.b_bar.is_identity() | self.t.is_identity()).into() { return Err(Error::General("Invalid proof - identity")); } if public_key.is_invalid().into() { return Err(Error::General("Invalid public key")); } - let mut points = Vec::with_capacity(public_key.y.len() + 2); + let mut points = Vec::with_capacity(public_key.y.len() + 3); let mut msgs = Vec::with_capacity(revealed_messages.len()); + let mut known = BTreeSet::new(); for (idx, msg) in revealed_messages { if *idx >= public_key.y.len() { continue; } + known.insert(*idx); points.push(public_key.y[*idx]); msgs.push(*msg); } - let commitment = G1Projective::GENERATOR + G1Projective::sum_of_products(&points, &msgs); - if self.commitment != commitment { - return Err(Error::General("Invalid proof - commitment")); + let lhs = -G1Projective::sum_of_products(&points, &msgs) - G1Projective::GENERATOR; + points.clear(); + msgs.clear(); + + for (idx, y) in public_key.y.iter().enumerate() { + if known.contains(&idx) { + continue; + } + points.push(*y); + } + + points.push(self.a_bar); + points.push(self.b_bar); + points.push(lhs); + let mut scalars = self.proof.clone(); + scalars.push(-challenge); + let commitment = G1Projective::sum_of_products(&points, &scalars); + if self.t != commitment { + return Err(Error::General("Invalid proof - invalid messages")); } let res = multi_miller_loop(&[ @@ -127,7 +121,10 @@ impl ProofOfSignatureKnowledge for PokSignatureProof { j += 1; continue; } - let message = self.proof.get(i).ok_or(Error::General("invalid proof"))?; + let message = self + .proof + .get(i - j) + .ok_or(Error::General("invalid proof"))?; hidden.insert(i, *message); } @@ -140,9 +137,9 @@ impl PokSignatureProof { pub fn to_bytes(&self) -> Vec { let mut buffer = Vec::with_capacity(48 * 3 + 32 * self.proof.len()); - buffer.extend_from_slice(&self.a_bar.to_affine().to_compressed()); - buffer.extend_from_slice(&self.b_bar.to_affine().to_compressed()); - buffer.extend_from_slice(&self.commitment.to_affine().to_compressed()); + buffer.extend_from_slice(&self.a_bar.to_compressed()); + buffer.extend_from_slice(&self.b_bar.to_compressed()); + buffer.extend_from_slice(&self.t.to_compressed()); for scalar in &self.proof { buffer.extend_from_slice(scalar.to_repr().as_ref()); } @@ -194,7 +191,7 @@ impl PokSignatureProof { Some(Self { a_bar: a_bar.unwrap(), b_bar: b_bar.unwrap(), - commitment: commitment.unwrap(), + t: commitment.unwrap(), proof, }) } diff --git a/src/knox/bbs/scheme.rs b/src/knox/bbs/scheme.rs index 9661014..87533a7 100644 --- a/src/knox/bbs/scheme.rs +++ b/src/knox/bbs/scheme.rs @@ -126,6 +126,6 @@ impl ShortGroupSignatureScheme for BbsScheme { transcript.challenge_bytes(b"signature proof of knowledge", &mut res); let v_challenge = Scalar::from_bytes_wide(&res); - proof.verify(revealed_msgs, public_key).is_ok() && challenge == v_challenge + proof.verify(public_key, revealed_msgs, challenge).is_ok() && challenge == v_challenge } } diff --git a/src/knox/ps/pok_signature_proof.rs b/src/knox/ps/pok_signature_proof.rs index 096f86e..fe7e570 100644 --- a/src/knox/ps/pok_signature_proof.rs +++ b/src/knox/ps/pok_signature_proof.rs @@ -72,7 +72,12 @@ impl ProofOfSignatureKnowledge for PokSignatureProof { /// Validate the proof, only checks the signature proof /// the selective disclosure proof is checked by verifying /// self.challenge == computed_challenge - fn verify(&self, rvl_msgs: &[(usize, Scalar)], public_key: &PublicKey) -> CredxResult<()> { + fn verify( + &self, + public_key: &Self::PublicKey, + revealed_messages: &[(usize, Scalar)], + _challenge: Scalar, + ) -> CredxResult<()> { // check the signature proof if self .sigma_1 @@ -84,7 +89,7 @@ impl ProofOfSignatureKnowledge for PokSignatureProof { return Err(Error::General("Invalid proof - identity")); } - if public_key.y.len() < rvl_msgs.len() { + if public_key.y.len() < revealed_messages.len() { return Err(Error::General( "Invalid key - revealed messages length is bigger than the public key", )); @@ -96,7 +101,7 @@ impl ProofOfSignatureKnowledge for PokSignatureProof { let mut points = Vec::new(); let mut scalars = Vec::new(); - for (idx, msg) in rvl_msgs { + for (idx, msg) in revealed_messages { if *idx > public_key.y.len() { return Err(Error::General("Invalid proof - revealed message index")); } diff --git a/src/knox/ps/scheme.rs b/src/knox/ps/scheme.rs index 40ca228..be1c330 100644 --- a/src/knox/ps/scheme.rs +++ b/src/knox/ps/scheme.rs @@ -135,6 +135,6 @@ impl ShortGroupSignatureScheme for PsScheme { transcript.challenge_bytes(b"signature proof of knowledge", &mut res); let v_challenge = Scalar::from_bytes_wide(&res); - proof.verify(revealed_msgs, public_key).is_ok() && challenge == v_challenge + proof.verify(public_key, revealed_msgs, challenge).is_ok() && challenge == v_challenge } } diff --git a/src/knox/short_group_sig_core/proof_committed_builder.rs b/src/knox/short_group_sig_core/proof_committed_builder.rs index fb58070..587228b 100644 --- a/src/knox/short_group_sig_core/proof_committed_builder.rs +++ b/src/knox/short_group_sig_core/proof_committed_builder.rs @@ -63,11 +63,15 @@ where /// Convert the committed values to bytes for the fiat-shamir challenge pub fn add_challenge_contribution(&self, label: &'static [u8], transcript: &mut Transcript) { - let mut scalars = self.scalars.clone(); - let commitment = (self.sum_of_products)(self.points.as_ref(), scalars.as_mut()); + let commitment = self.commitment(); transcript.append_message(label, commitment.to_affine().to_bytes().as_ref()); } + pub fn commitment(&self) -> B { + let mut scalars = self.scalars.clone(); + (self.sum_of_products)(self.points.as_ref(), scalars.as_mut()) + } + /// Generate the Schnorr challenges given the specified secrets /// by computing p = r + c * s pub fn generate_proof(&self, challenge: S, secrets: &[S]) -> CredxResult> { diff --git a/src/knox/short_group_sig_core/short_group_traits.rs b/src/knox/short_group_sig_core/short_group_traits.rs index c6d10c0..f267f81 100644 --- a/src/knox/short_group_sig_core/short_group_traits.rs +++ b/src/knox/short_group_sig_core/short_group_traits.rs @@ -131,8 +131,9 @@ pub trait ProofOfSignatureKnowledge: /// Verify the signature proof of knowledge fn verify( &self, - revealed_messages: &[(usize, Scalar)], public_key: &Self::PublicKey, + revealed_messages: &[(usize, Scalar)], + challenge: Scalar, ) -> CredxResult<()>; /// Get the hidden message proofs diff --git a/src/presentation/commitment.rs b/src/presentation/commitment.rs index a3d445b..0e33117 100644 --- a/src/presentation/commitment.rs +++ b/src/presentation/commitment.rs @@ -12,19 +12,16 @@ use serde::{Deserialize, Serialize}; pub(crate) struct CommitmentBuilder<'a> { pub(crate) commitment: G1Projective, pub(crate) statement: &'a CommitmentStatement, - pub(crate) message: Scalar, pub(crate) b: Scalar, pub(crate) r: Scalar, } impl PresentationBuilder for CommitmentBuilder<'_> { fn gen_proof(self, challenge: Scalar) -> PresentationProofs { - let message_proof = self.b + challenge * self.message; let blinder_proof = self.r + challenge * self.b; CommitmentProof { id: self.statement.id.clone(), commitment: self.commitment, - message_proof, blinder_proof, } .into() @@ -41,7 +38,6 @@ impl<'a> CommitmentBuilder<'a> { transcript: &mut Transcript, ) -> CredxResult { let r = Scalar::random(&mut rng); - let commitment = statement.message_generator * message + statement.blinder_generator * b; let blind_commitment = statement.message_generator * b + statement.blinder_generator * r; @@ -57,7 +53,6 @@ impl<'a> CommitmentBuilder<'a> { Ok(Self { commitment, statement, - message, b, r, }) @@ -71,8 +66,6 @@ pub struct CommitmentProof { pub id: String, /// The commitment pub commitment: G1Projective, - /// The schnorr message proof - pub message_proof: Scalar, /// The schnorr blinder proof pub blinder_proof: Scalar, } diff --git a/src/presentation/verifiable_encryption.rs b/src/presentation/verifiable_encryption.rs index 74be8c3..b7eb23e 100644 --- a/src/presentation/verifiable_encryption.rs +++ b/src/presentation/verifiable_encryption.rs @@ -13,20 +13,17 @@ pub(crate) struct VerifiableEncryptionBuilder<'a> { c1: G1Projective, c2: G1Projective, statement: &'a VerifiableEncryptionStatement, - message: Scalar, b: Scalar, r: Scalar, } impl PresentationBuilder for VerifiableEncryptionBuilder<'_> { fn gen_proof(self, challenge: Scalar) -> PresentationProofs { - let message_proof = self.b + challenge * self.message; let blinder_proof = self.r + challenge * self.b; VerifiableEncryptionProof { id: self.statement.id.clone(), c1: self.c1, c2: self.c2, - message_proof, blinder_proof, } .into() @@ -60,7 +57,6 @@ impl<'a> VerifiableEncryptionBuilder<'a> { c1, c2, statement, - message, b, r, }) @@ -76,8 +72,6 @@ pub struct VerifiableEncryptionProof { pub c1: G1Projective, /// The C2 El-Gamal component pub c2: G1Projective, - /// The schnorr message proof - pub message_proof: Scalar, /// The schnorr blinder proof pub blinder_proof: Scalar, } diff --git a/src/presentation/verify.rs b/src/presentation/verify.rs index 1ee02d4..77314a3 100644 --- a/src/presentation/verify.rs +++ b/src/presentation/verify.rs @@ -1,4 +1,6 @@ use super::*; +use crate::knox::short_group_sig_core::short_group_traits::ProofOfSignatureKnowledge; +use std::collections::BTreeMap; impl Presentation { /// Verify this presentation @@ -32,12 +34,22 @@ impl Presentation { for (id, pred_statement) in &predicate_statements { match (pred_statement, self.proofs.get(*id)) { (Statements::Revocation(aa), Some(PresentationProofs::Revocation(proof))) => { - let verifier = RevocationVerifier::new(aa, proof, nonce); + let hidden_messages = + self.get_sig_hidden_message_proofs(schema, &aa.reference_id)?; + let message_proof = hidden_messages + .get(&aa.claim) + .ok_or(Error::InvalidPresentationData)?; + let verifier = RevocationVerifier::new(aa, proof, nonce, *message_proof); verifier.add_challenge_contribution(self.challenge, &mut transcript)?; verifiers.push(verifier.into()); } (Statements::Membership(mm), Some(PresentationProofs::Membership(proof))) => { - let verifier = MembershipVerifier::new(mm, proof, nonce); + let hidden_messages = + self.get_sig_hidden_message_proofs(schema, &mm.reference_id)?; + let message_proof = hidden_messages + .get(&mm.claim) + .ok_or(Error::InvalidPresentationData)?; + let verifier = MembershipVerifier::new(mm, proof, nonce, *message_proof); verifier.add_challenge_contribution(self.challenge, &mut transcript)?; verifiers.push(verifier.into()); } @@ -54,7 +66,16 @@ impl Presentation { Statements::Commitment(statement), Some(PresentationProofs::Commitment(proof)), ) => { - let verifier = CommitmentVerifier { statement, proof }; + let hidden_messages = + self.get_sig_hidden_message_proofs(schema, &statement.reference_id)?; + let message_proof = hidden_messages + .get(&statement.claim) + .ok_or(Error::InvalidPresentationData)?; + let verifier = CommitmentVerifier { + statement, + proof, + message_proof: *message_proof, + }; verifier.add_challenge_contribution(self.challenge, &mut transcript)?; verifiers.push(verifier.into()); } @@ -62,7 +83,16 @@ impl Presentation { Statements::VerifiableEncryption(statement), Some(PresentationProofs::VerifiableEncryption(proof)), ) => { - let verifier = VerifiableEncryptionVerifier { statement, proof }; + let hidden_messages = + self.get_sig_hidden_message_proofs(schema, &statement.reference_id)?; + let message_proof = hidden_messages + .get(&statement.claim) + .ok_or(Error::InvalidPresentationData)?; + let verifier = VerifiableEncryptionVerifier { + statement, + proof, + message_proof: *message_proof, + }; verifier.add_challenge_contribution(self.challenge, &mut transcript)?; verifiers.push(verifier.into()); } @@ -115,4 +145,42 @@ impl Presentation { Ok(()) } + + fn get_sig_hidden_message_proofs( + &self, + schema: &PresentationSchema, + reference_id: &String, + ) -> CredxResult> { + let sig_proof = self + .proofs + .get(reference_id) + .ok_or(Error::InvalidPresentationData)?; + match sig_proof { + PresentationProofs::Signature(s) => { + match schema + .statements + .get(&s.id) + .ok_or(Error::InvalidPresentationData)? + { + Statements::Signature(sig_st) => { + let disclosed_messages: Vec<(usize, Scalar)> = s + .disclosed_messages + .iter() + .map(|(idx, scalar)| (*idx, *scalar)) + .collect(); + let hidden_messages = s + .pok + .get_hidden_message_proofs( + &sig_st.issuer.verifying_key, + disclosed_messages.as_slice(), + ) + .map_err(|_| Error::InvalidPresentationData)?; + Ok(hidden_messages) + } + _ => Err(Error::InvalidPresentationData), + } + } + _ => Err(Error::InvalidPresentationData), + } + } } diff --git a/src/verifier/commitment.rs b/src/verifier/commitment.rs index df8fbe9..c1c975e 100644 --- a/src/verifier/commitment.rs +++ b/src/verifier/commitment.rs @@ -9,6 +9,7 @@ use merlin::Transcript; pub struct CommitmentVerifier<'a, 'b> { pub statement: &'a CommitmentStatement, pub proof: &'b CommitmentProof, + pub message_proof: Scalar, } impl ProofVerifier for CommitmentVerifier<'_, '_> { @@ -18,7 +19,7 @@ impl ProofVerifier for CommitmentVerifier<'_, '_> { transcript: &mut Transcript, ) -> CredxResult<()> { let blind_commitment = self.proof.commitment * -challenge - + self.statement.message_generator * self.proof.message_proof + + self.statement.message_generator * self.message_proof + self.statement.blinder_generator * self.proof.blinder_proof; transcript.append_message(b"", self.statement.id.as_bytes()); diff --git a/src/verifier/membership.rs b/src/verifier/membership.rs index fa988ce..ab958d5 100644 --- a/src/verifier/membership.rs +++ b/src/verifier/membership.rs @@ -1,3 +1,4 @@ +use crate::error::Error; use crate::knox::accumulator::vb20::{Element, ProofParams}; use crate::presentation::MembershipProof; use crate::statement::MembershipStatement; @@ -10,6 +11,7 @@ pub struct MembershipVerifier<'a, 'b> { statement: &'a MembershipStatement, accumulator_proof: &'b MembershipProof, params: ProofParams, + message_proof: Scalar, } impl<'a, 'b> MembershipVerifier<'a, 'b> { @@ -17,12 +19,14 @@ impl<'a, 'b> MembershipVerifier<'a, 'b> { statement: &'a MembershipStatement, accumulator_proof: &'b MembershipProof, nonce: &[u8], + message_proof: Scalar, ) -> Self { let params = ProofParams::new(statement.verification_key, Some(nonce)); Self { statement, accumulator_proof, params, + message_proof, } } } @@ -45,6 +49,9 @@ impl ProofVerifier for MembershipVerifier<'_, '_> { } fn verify(&self, _challenge: Scalar) -> CredxResult<()> { + if self.accumulator_proof.proof.s_y != self.message_proof { + return Err(Error::InvalidPresentationData); + } Ok(()) } } diff --git a/src/verifier/revocation.rs b/src/verifier/revocation.rs index 49c25c0..9edea09 100644 --- a/src/verifier/revocation.rs +++ b/src/verifier/revocation.rs @@ -1,3 +1,4 @@ +use crate::error::Error; use crate::knox::accumulator::vb20::{Element, ProofParams}; use crate::presentation::RevocationProof; use crate::statement::RevocationStatement; @@ -10,6 +11,7 @@ pub struct RevocationVerifier<'a, 'b> { statement: &'a RevocationStatement, accumulator_proof: &'b RevocationProof, params: ProofParams, + message_proof: Scalar, } impl<'a, 'b> RevocationVerifier<'a, 'b> { @@ -17,12 +19,14 @@ impl<'a, 'b> RevocationVerifier<'a, 'b> { statement: &'a RevocationStatement, accumulator_proof: &'b RevocationProof, nonce: &[u8], + message_proof: Scalar, ) -> Self { let params = ProofParams::new(statement.verification_key, Some(nonce)); Self { statement, accumulator_proof, params, + message_proof, } } } @@ -45,6 +49,9 @@ impl ProofVerifier for RevocationVerifier<'_, '_> { } fn verify(&self, _challenge: Scalar) -> CredxResult<()> { + if self.accumulator_proof.proof.s_y != self.message_proof { + return Err(Error::InvalidPresentationData); + } Ok(()) } } diff --git a/src/verifier/signature.rs b/src/verifier/signature.rs index f15e76e..946c455 100644 --- a/src/verifier/signature.rs +++ b/src/verifier/signature.rs @@ -47,10 +47,11 @@ impl ProofVerifier for SignatureVerifier<'_, '_, S Ok(()) } - fn verify(&self, _challenge: Scalar) -> CredxResult<()> { + fn verify(&self, challenge: Scalar) -> CredxResult<()> { self.signature_proof.pok.verify( - &self.disclosed_messages, &self.statement.issuer.verifying_key, + &self.disclosed_messages, + challenge, ) } } diff --git a/src/verifier/verifiable_encryption.rs b/src/verifier/verifiable_encryption.rs index 46a4a6b..8514513 100644 --- a/src/verifier/verifiable_encryption.rs +++ b/src/verifier/verifiable_encryption.rs @@ -9,6 +9,7 @@ use merlin::Transcript; pub struct VerifiableEncryptionVerifier<'a, 'b> { pub statement: &'a VerifiableEncryptionStatement, pub proof: &'b VerifiableEncryptionProof, + pub message_proof: Scalar, } impl ProofVerifier for VerifiableEncryptionVerifier<'_, '_> { @@ -20,7 +21,7 @@ impl ProofVerifier for VerifiableEncryptionVerifier<'_, '_> { let challenge = -challenge; let r1 = self.proof.c1 * challenge + G1Projective::GENERATOR * self.proof.blinder_proof; let r2 = self.proof.c2 * challenge - + self.statement.message_generator * self.proof.message_proof + + self.statement.message_generator * self.message_proof + self.statement.encryption_key.0 * self.proof.blinder_proof; transcript.append_message(b"", self.statement.id.as_bytes()); diff --git a/tests/range.rs b/tests/range.rs index 75d0999..d1e905e 100644 --- a/tests/range.rs +++ b/tests/range.rs @@ -3,6 +3,7 @@ use credx::claim::{ClaimType, HashedClaim, NumberClaim, RevocationClaim}; use credx::credential::{ClaimSchema, CredentialSchema}; use credx::issuer::Issuer; use credx::knox::bbs::BbsScheme; +use credx::knox::ps::PsScheme; use credx::presentation::{Presentation, PresentationSchema}; use credx::statement::{CommitmentStatement, RangeStatement, SignatureStatement}; use credx::{random_string, CredxResult}; @@ -38,6 +39,11 @@ range_test_with!(in_range_max_implicit, isize::MAX, Some(0), None, false); range_test_with!(out_of_range_below, 0, Some(1), Some(isize::MAX), true); range_test_with!(out_of_range_above, 1001, Some(0), Some(1000), true); +#[test] +fn test_out_of_range_above() { + assert!(test_range_proof_works(1000, Some(0), Some(1000), false).is_ok()); +} + fn test_range_proof_works( val: isize, lower: Option,