Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 96 additions & 16 deletions schnorr_pok/src/discrete_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//! 3. Computes 2 responses `s1 = r1 + c*x1` and `s2 = r2 + c*x2` and sends them to the verifier.
//! 4. Verifier checks if `G1 * s1 + G2 * s2 = T + Y*c`

use crate::error::SchnorrError;
use crate::{append_dst, append_labeled, error::SchnorrError};
use ark_ec::{AffineRepr, CurveGroup};
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
Expand Down Expand Up @@ -118,9 +118,10 @@ impl<G: AffineRepr> PokDiscreteLogProtocol<G> {
&self,
base: &G,
y: &G,
dst: &[u8],
writer: W,
) -> Result<(), SchnorrError> {
Self::compute_challenge_contribution(base, y, &self.t, writer)
Self::compute_challenge_contribution(base, y, &self.t, dst, writer)
}

pub fn gen_proof(self, challenge: &G::ScalarField) -> PokDiscreteLog<G> {
Expand All @@ -135,11 +136,14 @@ impl<G: AffineRepr> PokDiscreteLogProtocol<G> {
base: &G,
y: &G,
t: &G,
dst: &[u8],
mut writer: W,
) -> Result<(), SchnorrError> {
base.serialize_compressed(&mut writer)?;
y.serialize_compressed(&mut writer)?;
t.serialize_compressed(writer).map_err(|e| e.into())
append_dst(&mut writer, dst)?;
append_labeled(&mut writer, b"base", base)?;
append_labeled(&mut writer, b"y", y)?;
append_labeled(&mut writer, b"t", t)?;
Ok(())
}
}

Expand All @@ -148,9 +152,10 @@ impl<G: AffineRepr> PokDiscreteLog<G> {
&self,
base: &G,
y: &G,
dst: &[u8],
writer: W,
) -> Result<(), SchnorrError> {
PokDiscreteLogProtocol::compute_challenge_contribution(base, y, &self.t, writer)
PokDiscreteLogProtocol::compute_challenge_contribution(base, y, &self.t, dst, writer)
}

/// `base*response - y*challenge == t`
Expand Down Expand Up @@ -200,9 +205,10 @@ impl<G: AffineRepr> PokPedersenCommitmentProtocol<G> {
base1: &G,
base2: &G,
y: &G,
dst: &[u8],
writer: W,
) -> Result<(), SchnorrError> {
Self::compute_challenge_contribution(base1, base2, y, &self.t, writer)
Self::compute_challenge_contribution(base1, base2, y, &self.t, dst, writer)
}

pub fn gen_proof(self, challenge: &G::ScalarField) -> PokPedersenCommitment<G> {
Expand All @@ -220,12 +226,14 @@ impl<G: AffineRepr> PokPedersenCommitmentProtocol<G> {
base2: &G,
y: &G,
t: &G,
dst: &[u8],
mut writer: W,
) -> Result<(), SchnorrError> {
base1.serialize_compressed(&mut writer)?;
base2.serialize_compressed(&mut writer)?;
y.serialize_compressed(&mut writer)?;
t.serialize_compressed(&mut writer)?;
append_dst(&mut writer, dst)?;
append_labeled(&mut writer, b"base1", base1)?;
append_labeled(&mut writer, b"base2", base2)?;
append_labeled(&mut writer, b"y", y)?;
append_labeled(&mut writer, b"t", t)?;
Ok(())
}
}
Expand All @@ -236,10 +244,11 @@ impl<G: AffineRepr> PokPedersenCommitment<G> {
base1: &G,
base2: &G,
y: &G,
dst: &[u8],
writer: W,
) -> Result<(), SchnorrError> {
PokPedersenCommitmentProtocol::compute_challenge_contribution(
base1, base2, y, &self.t, writer,
base1, base2, y, &self.t, dst, writer,
)
}

Expand Down Expand Up @@ -309,7 +318,7 @@ mod tests {
);
let mut chal_contrib_prover = vec![];
protocol
.challenge_contribution(&base, &y, &mut chal_contrib_prover)
.challenge_contribution(&base, &y, b"test", &mut chal_contrib_prover)
.unwrap();

test_serialization!(
Expand All @@ -323,7 +332,7 @@ mod tests {

let mut chal_contrib_verifier = vec![];
proof
.challenge_contribution(&base, &y, &mut chal_contrib_verifier)
.challenge_contribution(&base, &y, b"test", &mut chal_contrib_verifier)
.unwrap();

let challenge_verifier =
Expand Down Expand Up @@ -378,7 +387,7 @@ mod tests {
);
let mut chal_contrib_prover = vec![];
protocol
.challenge_contribution(&base1, &base2, &y, &mut chal_contrib_prover)
.challenge_contribution(&base1, &base2, &y, b"test", &mut chal_contrib_prover)
.unwrap();

test_serialization!(
Expand All @@ -392,7 +401,7 @@ mod tests {

let mut chal_contrib_verifier = vec![];
proof
.challenge_contribution(&base1, &base2, &y, &mut chal_contrib_verifier)
.challenge_contribution(&base1, &base2, &y, b"test", &mut chal_contrib_verifier)
.unwrap();

let challenge_verifier =
Expand Down Expand Up @@ -433,4 +442,75 @@ mod tests {
check!(G1Affine, G1);
check!(G2Affine, G2);
}

#[test]
fn dst_framing() {
let mut rng = StdRng::seed_from_u64(0u64);
let base = <Bls12_381 as Pairing>::G1::rand(&mut rng).into_affine();
let witness = Fr::rand(&mut rng);
let y = base.mul_bigint(witness.into_bigint()).into_affine();
let blinding = Fr::rand(&mut rng);
let protocol = PokDiscreteLogProtocol::<<Bls12_381 as Pairing>::G1Affine>::init(
witness, blinding, &base,
);

// Empty `dst` is rejected
let mut buf = vec![];
assert!(matches!(
protocol.challenge_contribution(&base, &y, b"", &mut buf),
Err(SchnorrError::EmptyDomainSeparator)
));

// Distinct `dst` yields distinct contribution bytes
let mut b1 = vec![];
protocol
.challenge_contribution(&base, &y, b"rel1", &mut b1)
.unwrap();
let mut b2 = vec![];
protocol
.challenge_contribution(&base, &y, b"rel2", &mut b2)
.unwrap();
assert_ne!(b1, b2);

// Prover and proof produce identical bytes for the same `dst`
let proof = protocol.gen_proof(&compute_random_oracle_challenge::<Fr, Blake2b512>(&b1));
let mut b3 = vec![];
proof
.challenge_contribution(&base, &y, b"rel1", &mut b3)
.unwrap();
assert_eq!(b1, b3);

// Same for the Pedersen commitment protocol
let base2 = <Bls12_381 as Pairing>::G1::rand(&mut rng).into_affine();
let witness2 = Fr::rand(&mut rng);
let y2 = (base * witness + base2 * witness2).into_affine();
let protocol = PokPedersenCommitmentProtocol::<<Bls12_381 as Pairing>::G1Affine>::init(
witness,
Fr::rand(&mut rng),
&base,
witness2,
Fr::rand(&mut rng),
&base2,
);
let mut buf = vec![];
assert!(matches!(
protocol.challenge_contribution(&base, &base2, &y2, b"", &mut buf),
Err(SchnorrError::EmptyDomainSeparator)
));
let mut p1 = vec![];
protocol
.challenge_contribution(&base, &base2, &y2, b"rel1", &mut p1)
.unwrap();
let mut p2 = vec![];
protocol
.challenge_contribution(&base, &base2, &y2, b"rel2", &mut p2)
.unwrap();
assert_ne!(p1, p2);
let proof = protocol.gen_proof(&compute_random_oracle_challenge::<Fr, Blake2b512>(&p1));
let mut p3 = vec![];
proof
.challenge_contribution(&base, &base2, &y2, b"rel1", &mut p3)
.unwrap();
assert_eq!(p1, p3);
}
}
58 changes: 50 additions & 8 deletions schnorr_pok/src/discrete_log_pairing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! Similar protocol would work for proving knowledge of `A2` in `e(A2, B2) = Y2`.
//!

use crate::error::SchnorrError;
use crate::{append_dst, append_labeled, error::SchnorrError};
use ark_ec::{
pairing::{Pairing, PairingOutput},
CurveGroup,
Expand Down Expand Up @@ -83,9 +83,10 @@ macro_rules! impl_protocol {
&self,
other: &$other_group,
y: &PairingOutput<E>,
dst: &[u8],
writer: W,
) -> Result<(), SchnorrError> {
Self::compute_challenge_contribution(other, y, &self.t, writer)
Self::compute_challenge_contribution(other, y, &self.t, dst, writer)
}

pub fn gen_proof(self, challenge: &E::ScalarField) -> $proof<E> {
Expand All @@ -99,11 +100,14 @@ macro_rules! impl_protocol {
other: &$other_group,
y: &PairingOutput<E>,
t: &PairingOutput<E>,
dst: &[u8],
mut writer: W,
) -> Result<(), SchnorrError> {
other.serialize_compressed(&mut writer)?;
y.serialize_compressed(&mut writer)?;
t.serialize_compressed(writer).map_err(|e| e.into())
append_dst(&mut writer, dst)?;
append_labeled(&mut writer, b"other", other)?;
append_labeled(&mut writer, b"y", y)?;
append_labeled(&mut writer, b"t", t)?;
Ok(())
}
}

Expand All @@ -124,9 +128,10 @@ macro_rules! impl_protocol {
&self,
other: &$other_group,
y: &PairingOutput<E>,
dst: &[u8],
writer: W,
) -> Result<(), SchnorrError> {
$protocol::compute_challenge_contribution(other, y, &self.t, writer)
$protocol::compute_challenge_contribution(other, y, &self.t, dst, writer)
}
}
}
Expand Down Expand Up @@ -192,7 +197,7 @@ mod tests {
let protocol = $protocol::<Bls12_381>::init(witness, blinding, base);
let mut chal_contrib_prover = vec![];
protocol
.challenge_contribution(&base, &y, &mut chal_contrib_prover)
.challenge_contribution(&base, &y, b"test", &mut chal_contrib_prover)
.unwrap();
test_serialization!($protocol<Bls12_381>, protocol);

Expand All @@ -202,7 +207,7 @@ mod tests {

let mut chal_contrib_verifier = vec![];
proof
.challenge_contribution(&base, &y, &mut chal_contrib_verifier)
.challenge_contribution(&base, &y, b"test", &mut chal_contrib_verifier)
.unwrap();

let challenge_verifier =
Expand Down Expand Up @@ -281,4 +286,41 @@ mod tests {
pair_g1_g2
);
}

#[test]
fn dst_framing() {
let mut rng = StdRng::seed_from_u64(0u64);
let base = G2Affine::rand(&mut rng);
let witness = G1Affine::rand(&mut rng);
let y = pair_g2_g1!(Bls12_381::pairing, base, witness);
let blinding = G1Affine::rand(&mut rng);
let protocol =
PoKG1DiscreteLogInPairingProtocol::<Bls12_381>::init(witness, blinding, base);

// Empty `dst` is rejected
let mut buf = vec![];
assert!(matches!(
protocol.challenge_contribution(&base, &y, b"", &mut buf),
Err(SchnorrError::EmptyDomainSeparator)
));

// Distinct `dst` yields distinct contribution bytes
let mut b1 = vec![];
protocol
.challenge_contribution(&base, &y, b"rel1", &mut b1)
.unwrap();
let mut b2 = vec![];
protocol
.challenge_contribution(&base, &y, b"rel2", &mut b2)
.unwrap();
assert_ne!(b1, b2);

// Prover and proof produce identical bytes for the same `dst`
let proof = protocol.gen_proof(&compute_random_oracle_challenge::<Fr, Blake2b512>(&b1));
let mut b3 = vec![];
proof
.challenge_contribution(&base, &y, b"rel1", &mut b3)
.unwrap();
assert_eq!(b1, b3);
}
}
1 change: 1 addition & 0 deletions schnorr_pok/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum SchnorrError {
NotAProduct,
NotASquare,
NotAnInverse,
EmptyDomainSeparator,
}

impl From<SerializationError> for SchnorrError {
Expand Down
Loading