Skip to content

Commit

Permalink
Require using Schnorr proofs from signature proof for predicates (#42)
Browse files Browse the repository at this point in the history
* require using schnorr proofs from signature proof for predicates

Signed-off-by: Michael Lodder <mike@litprotocol.com>

* minor nits

Signed-off-by: Michael Lodder <mike@litprotocol.com>

---------

Signed-off-by: Michael Lodder <mike@litprotocol.com>
  • Loading branch information
mikelodder7 authored Feb 7, 2025
1 parent ff62964 commit 5a75b83
Show file tree
Hide file tree
Showing 17 changed files with 184 additions and 108 deletions.
16 changes: 8 additions & 8 deletions src/knox/accumulator/vb20/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
47 changes: 19 additions & 28 deletions src/knox/bbs/pok_signature.rs
Original file line number Diff line number Diff line change
@@ -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::*;

Expand All @@ -14,7 +15,6 @@ pub struct PokSignature {
proof: ProofCommittedBuilder<G1Projective, G1Affine, Scalar>,
a_bar: G1Projective,
b_bar: G1Projective,
commitment: G1Projective,
hidden_messages: Vec<Scalar>,
}

Expand All @@ -31,57 +31,48 @@ impl ProofOfSignatureKnowledgeContribution for PokSignature {
) -> CredxResult<Self> {
let msgs = messages.iter().map(|m| m.get_message()).collect::<Vec<_>>();

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<Self::ProofOfKnowledge> {
Expand All @@ -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,
})
}
Expand Down
83 changes: 40 additions & 43 deletions src/knox/bbs/pok_signature_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Scalar>,
}

Expand All @@ -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(&[
Expand Down Expand Up @@ -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);
}

Expand All @@ -140,9 +137,9 @@ impl PokSignatureProof {
pub fn to_bytes(&self) -> Vec<u8> {
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());
}
Expand Down Expand Up @@ -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,
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/knox/bbs/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
11 changes: 8 additions & 3 deletions src/knox/ps/pok_signature_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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",
));
Expand All @@ -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"));
}
Expand Down
2 changes: 1 addition & 1 deletion src/knox/ps/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
8 changes: 6 additions & 2 deletions src/knox/short_group_sig_core/proof_committed_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<S>> {
Expand Down
3 changes: 2 additions & 1 deletion src/knox/short_group_sig_core/short_group_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 0 additions & 7 deletions src/presentation/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@ use serde::{Deserialize, Serialize};
pub(crate) struct CommitmentBuilder<'a> {
pub(crate) commitment: G1Projective,
pub(crate) statement: &'a CommitmentStatement<G1Projective>,
pub(crate) message: Scalar,
pub(crate) b: Scalar,
pub(crate) r: Scalar,
}

impl<S: ShortGroupSignatureScheme> PresentationBuilder<S> for CommitmentBuilder<'_> {
fn gen_proof(self, challenge: Scalar) -> PresentationProofs<S> {
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()
Expand All @@ -41,7 +38,6 @@ impl<'a> CommitmentBuilder<'a> {
transcript: &mut Transcript,
) -> CredxResult<Self> {
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;

Expand All @@ -57,7 +53,6 @@ impl<'a> CommitmentBuilder<'a> {
Ok(Self {
commitment,
statement,
message,
b,
r,
})
Expand All @@ -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,
}
Loading

0 comments on commit 5a75b83

Please sign in to comment.