Skip to content

Commit a4d0717

Browse files
committedMay 9, 2024·
Add distributed discrete log check
Signed-off-by: lovesh <lovesh.bond@gmail.com>
1 parent 487741e commit a4d0717

File tree

16 files changed

+1523
-17
lines changed

16 files changed

+1523
-17
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Library providing privacy enhancing cryptographic primitives.
2222
- zk-SNARK created from R1CS and WASM generated by [Circom](https://docs.circom.io/) with witnesses as BBS+ signed messages (not exclusively though).
2323
5. [Verifiable encryption](./saver) using [SAVER](https://eprint.iacr.org/2019/1270).
2424
6. [Compression and amortization of Sigma protocols](./compressed_sigma). This is PoC implementation.
25-
7. [Secret sharing schemes and DKG](./secret_sharing_and_dkg). Implements verifiable secret sharing schemes and DKG from Gennaro and FROST.
25+
7. [Secret sharing schemes and DKG](./secret_sharing_and_dkg). Implements verifiable secret sharing schemes and DKG from Gennaro and FROST. Also implements protocol to do a distributed DLOG check.
2626
8. [Cocount and PS signatures](./coconut/). Based on the paper [Security Analysis of Coconut, an Attribute-Based Credential Scheme with Threshold Issuance](https://eprint.iacr.org/2022/011)
2727
9. [LegoGroth16](./legogroth16/). LegoGroth16, the [LegoSNARK](https://eprint.iacr.org/2019/142) variant of [Groth16](https://eprint.iacr.org/2016/260) zkSNARK proof system
2828
10. [Oblivious Transfer (OT) and Oblivious Transfer Extensions (OTE)](./oblivious_transfer).

‎proof_system/src/sub_protocols/accumulator/cdh.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use vb_accumulator::{
3333

3434
macro_rules! impl_cdh_protocol_struct_and_funcs {
3535
($(#[$doc:meta])*
36-
$name:ident, $statement_proof_variant: ident, $witness_type: ident, $wit_group:path, $protocol: ident, $proof: ident, $error_type: ident) => {
36+
$name: ident, $statement_proof_variant: ident, $witness_type: ident, $wit_group: path, $protocol: ident, $proof: ident, $error_type: ident) => {
3737
#[derive(Clone, Debug, PartialEq, Eq)]
3838
pub struct $name<'a, E: Pairing> {
3939
pub id: usize,

‎proof_system/src/sub_protocols/accumulator/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
macro_rules! impl_common_funcs {
2-
( $prepared_params_type: ident, $prepared_pk_type: ident, $wit_type:ident, $wit_group:path, $wit_protocol:ident, $proof_enum_variant:ident, $proof_typ: ident, $error_typ: ident) => {
2+
( $prepared_params_type: ident, $prepared_pk_type: ident, $wit_type: ident, $wit_group: path, $wit_protocol:ident, $proof_enum_variant: ident, $proof_typ: ident, $error_typ: ident) => {
33
pub fn init<R: RngCore>(
44
&mut self,
55
rng: &mut R,
@@ -84,7 +84,7 @@ macro_rules! impl_common_funcs {
8484

8585
macro_rules! impl_struct_and_funcs {
8686
($(#[$doc:meta])*
87-
$name:ident, $param_type:ident, $pk_type:ident, $prepared_params_type: ident, $prepared_pk_type: ident, $prk_type:ident, $protocol:ident, $wit_type:ident, $wit_group:path, $proof_enum_variant:ident, $proof_typ: ident, $error_typ: ident) => {
87+
$name: ident, $param_type: ident, $pk_type: ident, $prepared_params_type: ident, $prepared_pk_type: ident, $prk_type: ident, $protocol: ident, $wit_type: ident, $wit_group: path, $proof_enum_variant: ident, $proof_typ: ident, $error_typ: ident) => {
8888
#[derive(Clone, Debug, PartialEq, Eq)]
8989
pub struct $name<'a, E: Pairing> {
9090
pub id: usize,

‎schnorr_pok/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
Schnorr protocol to prove knowledge of 1 or more discrete logs in zero knowledge.
66
Refer [this](https://crypto.stanford.edu/cs355/19sp/lec5.pdf) for more details of Schnorr protocol.
77

8+
Also implements the proof of knowledge of discrete log in pairing groups, i.e. given prover and verifier
9+
both know (`A1`, `Y1`), and prover additionally knows `B1`, prove that `e(A1, B1) = Y1`. Similarly,
10+
proving `e(A2, B2) = Y2` when only prover knows `A2` but both know (`B2`, `Y2`). See [`discrete_log_pairing`]
11+
812
Also implements the proof of **inequality of discrete log** (a value committed in a Pedersen commitment),
913
either with a public value or with another discrete log in [`Inequality`]. eg. Given a message `m`,
1014
its commitment `C = g * m + h * r` and a public value `v`, proving that `m``v`. Or given 2 messages
@@ -45,5 +49,6 @@ with the implemented variant as verifier checks 2 equations `s1 = r1 + x1*c` and
4549

4650

4751
[`Inequality`]: https://docs.rs/schnorr_pok/latest/schnorr_pok/inequality/
52+
[`discrete_log_pairing`]: https://docs.rs/schnorr_pok/latest/schnorr_pok/discrete_log_pairing/
4853

4954
<!-- cargo-rdme end -->
+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
//! Schnorr protocol for proving knowledge of discrete logs, i.e. given prover and verifier both know (`A1`, `Y1`)
2+
//! and prover additionally knows `B1`, prove that `e(A1, B1) = Y1`. Similarly, proving `e(A2, B2) = Y2` when only
3+
//! prover knows `A2` but both know (`B2`, `Y2`).
4+
//!
5+
//! To prove knowledge of a single discrete log, i.e. given public `Y1` and `A1`, prove knowledge of `B1` in `e(A1, B1) = Y1`:
6+
//! 1. Prover chooses a random `R1` and computes `T1 = e(A1, R1)`
7+
//! 2. Hashes `T1` towards getting a challenge `c`.
8+
//! 3. Computes response `S1 = R1 + c*B1` and sends it to the verifier.
9+
//! 4. Verifier checks if `e(A1, S1) = T1 + Y1*c`. This works because `e(A1, S1) = e(A1, R1 + c*B1) = e(A1, R1) + e(A1, c*B1) = T1 + c*e(A1, B1) = T1 + c*Y1`.
10+
//!
11+
//! Similar protocol would work for proving knowledge of `A2` in `e(A2, B2) = Y2`.
12+
//!
13+
14+
use crate::error::SchnorrError;
15+
use ark_ec::{
16+
pairing::{Pairing, PairingOutput},
17+
CurveGroup,
18+
};
19+
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
20+
use ark_std::{io::Write, vec::Vec};
21+
use dock_crypto_utils::{
22+
pair_g1_g2, pair_g2_g1, randomized_pairing_check::RandomizedPairingChecker,
23+
serde_utils::ArkObjectBytes,
24+
};
25+
use serde::{Deserialize, Serialize};
26+
use serde_with::serde_as;
27+
use zeroize::{Zeroize, ZeroizeOnDrop};
28+
29+
macro_rules! impl_protocol {
30+
(
31+
$(#[$protocol_doc:meta])*
32+
$protocol: ident, $proof: ident, $witness_group: path, $other_group: path, $other_group_prepared: path, $pairing: tt) => {
33+
34+
$(#[$protocol_doc])*
35+
#[serde_as]
36+
#[derive(
37+
Default,
38+
Clone,
39+
PartialEq,
40+
Eq,
41+
Debug,
42+
CanonicalSerialize,
43+
CanonicalDeserialize,
44+
Serialize,
45+
Deserialize,
46+
Zeroize,
47+
ZeroizeOnDrop,
48+
)]
49+
pub struct $protocol<E: Pairing> {
50+
/// Commitment to randomness
51+
#[zeroize(skip)]
52+
#[serde_as(as = "ArkObjectBytes")]
53+
pub t: PairingOutput<E>,
54+
/// Randomness chosen by the prover
55+
#[serde_as(as = "ArkObjectBytes")]
56+
blinding: $witness_group,
57+
/// Prover's secret
58+
#[serde_as(as = "ArkObjectBytes")]
59+
witness: $witness_group,
60+
}
61+
62+
#[serde_as]
63+
#[derive(
64+
Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
65+
)]
66+
pub struct $proof<E: Pairing> {
67+
#[serde_as(as = "ArkObjectBytes")]
68+
pub t: PairingOutput<E>,
69+
#[serde_as(as = "ArkObjectBytes")]
70+
pub response: $witness_group,
71+
}
72+
73+
impl<E: Pairing> $protocol<E> {
74+
pub fn init(witness: $witness_group, blinding: $witness_group, other: &$other_group) -> Self {
75+
let t = $pairing!(E::pairing, other, blinding);
76+
Self {
77+
t,
78+
blinding,
79+
witness,
80+
}
81+
}
82+
83+
pub fn challenge_contribution<W: Write>(
84+
&self,
85+
other: &$other_group,
86+
y: &PairingOutput<E>,
87+
writer: W,
88+
) -> Result<(), SchnorrError> {
89+
Self::compute_challenge_contribution(other, y, &self.t, writer)
90+
}
91+
92+
pub fn gen_proof(self, challenge: &E::ScalarField) -> $proof<E> {
93+
$proof {
94+
t: self.t,
95+
response: (self.blinding + self.witness * challenge).into_affine(),
96+
}
97+
}
98+
99+
pub fn compute_challenge_contribution<W: Write>(
100+
other: &$other_group,
101+
y: &PairingOutput<E>,
102+
t: &PairingOutput<E>,
103+
mut writer: W,
104+
) -> Result<(), SchnorrError> {
105+
other.serialize_compressed(&mut writer)?;
106+
y.serialize_compressed(&mut writer)?;
107+
t.serialize_compressed(writer).map_err(|e| e.into())
108+
}
109+
}
110+
111+
impl<E: Pairing> $proof<E> {
112+
pub fn verify(
113+
&self,
114+
y: &PairingOutput<E>,
115+
other: impl Into<$other_group_prepared>,
116+
challenge: &E::ScalarField,
117+
) -> bool {
118+
$pairing!(E::pairing, other, self.response) == (self.t + *y * challenge)
119+
}
120+
121+
pub fn challenge_contribution<W: Write>(
122+
&self,
123+
other: &$other_group,
124+
y: &PairingOutput<E>,
125+
writer: W,
126+
) -> Result<(), SchnorrError> {
127+
$protocol::compute_challenge_contribution(other, y, &self.t, writer)
128+
}
129+
}
130+
}
131+
}
132+
133+
impl_protocol!(
134+
/// Protocol for proving knowledge of discrete log in group G1, i.e. given public `Y` and `B`, prove knowledge of `A` in `e(A, B) = Y`
135+
PokG1DiscreteLogInPairingProtocol, PokG1DiscreteLogInPairing, E::G1Affine, E::G2Affine, E::G2Prepared, pair_g2_g1
136+
);
137+
138+
impl<E: Pairing> PokG1DiscreteLogInPairing<E> {
139+
pub fn verify_with_randomized_pairing_checker(
140+
&self,
141+
y: &PairingOutput<E>,
142+
other: impl Into<E::G2Prepared>,
143+
challenge: &E::ScalarField,
144+
pairing_checker: &mut RandomizedPairingChecker<E>,
145+
) {
146+
pairing_checker.add_sources_and_target(&self.response, other, &(self.t + *y * challenge))
147+
}
148+
}
149+
150+
impl_protocol!(
151+
/// Protocol for proving knowledge of discrete log in group G2, i.e. given public `Y` and `A`, prove knowledge of `B` in `e(A, B) = Y`
152+
PokG2DiscreteLogInPairingProtocol, PokG2DiscreteLogInPairing, E::G2Affine, E::G1Affine, E::G1Prepared, pair_g1_g2
153+
);
154+
155+
impl<E: Pairing> PokG2DiscreteLogInPairing<E> {
156+
pub fn verify_with_randomized_pairing_checker(
157+
&self,
158+
y: &PairingOutput<E>,
159+
other: &E::G1Affine,
160+
challenge: &E::ScalarField,
161+
pairing_checker: &mut RandomizedPairingChecker<E>,
162+
) {
163+
pairing_checker.add_sources_and_target(other, self.response, &(self.t + *y * challenge))
164+
}
165+
}
166+
167+
#[cfg(test)]
168+
mod tests {
169+
use super::*;
170+
use crate::{compute_random_oracle_challenge, test_serialization};
171+
use ark_bls12_381::{Bls12_381, Fr, G1Affine, G2Affine};
172+
use ark_ec::pairing::Pairing;
173+
use ark_std::{
174+
rand::{rngs::StdRng, SeedableRng},
175+
UniformRand,
176+
};
177+
use blake2::Blake2b512;
178+
179+
#[test]
180+
fn discrete_log_proof_in_pairing_group() {
181+
let mut rng = StdRng::seed_from_u64(0u64);
182+
183+
macro_rules! check {
184+
($protocol:ident, $proof:ident, $witness_group:ident, $other_group:ident, $other_group_prepared:ident, $pairing: tt) => {
185+
let base = $other_group::rand(&mut rng);
186+
let witness = $witness_group::rand(&mut rng);
187+
let y = $pairing!(Bls12_381::pairing, base, witness);
188+
let blinding = $witness_group::rand(&mut rng);
189+
190+
let protocol = $protocol::<Bls12_381>::init(witness, blinding, &base);
191+
let mut chal_contrib_prover = vec![];
192+
protocol
193+
.challenge_contribution(&base, &y, &mut chal_contrib_prover)
194+
.unwrap();
195+
test_serialization!($protocol<Bls12_381>, protocol);
196+
197+
let challenge_prover =
198+
compute_random_oracle_challenge::<Fr, Blake2b512>(&chal_contrib_prover);
199+
let proof = protocol.gen_proof(&challenge_prover);
200+
201+
let mut chal_contrib_verifier = vec![];
202+
proof
203+
.challenge_contribution(&base, &y, &mut chal_contrib_verifier)
204+
.unwrap();
205+
206+
let challenge_verifier =
207+
compute_random_oracle_challenge::<Fr, Blake2b512>(&chal_contrib_verifier);
208+
assert!(proof.verify(&y, &base, &challenge_verifier));
209+
assert_eq!(chal_contrib_prover, chal_contrib_verifier);
210+
assert_eq!(challenge_prover, challenge_verifier);
211+
212+
test_serialization!($proof<Bls12_381>, proof);
213+
214+
// Check with prepared
215+
let base_prepared = <Bls12_381 as Pairing>::$other_group_prepared::from(base);
216+
assert!(proof.verify(&y, base_prepared, &challenge_verifier));
217+
218+
// Check with randomized pairing checker
219+
let count = 3;
220+
let bases = (0..count)
221+
.into_iter()
222+
.map(|_| $other_group::rand(&mut rng))
223+
.collect::<Vec<_>>();
224+
let witnesses = (0..count)
225+
.into_iter()
226+
.map(|_| $witness_group::rand(&mut rng))
227+
.collect::<Vec<_>>();
228+
let ys = (0..count)
229+
.into_iter()
230+
.map(|i| $pairing!(Bls12_381::pairing, bases[i], witnesses[i]))
231+
.collect::<Vec<_>>();
232+
let blindings = (0..count)
233+
.into_iter()
234+
.map(|_| $witness_group::rand(&mut rng))
235+
.collect::<Vec<_>>();
236+
237+
let challenge = Fr::rand(&mut rng);
238+
let mut proofs = vec![];
239+
for i in 0..count {
240+
let protocol =
241+
$protocol::<Bls12_381>::init(witnesses[i], blindings[i], &bases[i]);
242+
let proof = protocol.gen_proof(&challenge);
243+
assert!(proof.verify(&ys[i], &bases[i], &challenge));
244+
proofs.push(proof);
245+
}
246+
247+
for lazy in [true, false] {
248+
let mut checker =
249+
RandomizedPairingChecker::<Bls12_381>::new_using_rng(&mut rng, lazy);
250+
for i in 0..count {
251+
proofs[i].verify_with_randomized_pairing_checker(
252+
&ys[i],
253+
&bases[i],
254+
&challenge,
255+
&mut checker,
256+
);
257+
}
258+
assert!(checker.verify());
259+
}
260+
};
261+
}
262+
263+
check!(
264+
PokG1DiscreteLogInPairingProtocol,
265+
PokG1DiscreteLogInPairing,
266+
G1Affine,
267+
G2Affine,
268+
G2Prepared,
269+
pair_g2_g1
270+
);
271+
check!(
272+
PokG2DiscreteLogInPairingProtocol,
273+
PokG2DiscreteLogInPairing,
274+
G2Affine,
275+
G1Affine,
276+
G1Prepared,
277+
pair_g1_g2
278+
);
279+
}
280+
}

‎schnorr_pok/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
//! Schnorr protocol to prove knowledge of 1 or more discrete logs in zero knowledge.
44
//! Refer [this](https://crypto.stanford.edu/cs355/19sp/lec5.pdf) for more details of Schnorr protocol.
55
//!
6+
//! Also implements the proof of knowledge of discrete log in pairing groups, i.e. given prover and verifier
7+
//! both know (`A1`, `Y1`), and prover additionally knows `B1`, prove that `e(A1, B1) = Y1`. Similarly,
8+
//! proving `e(A2, B2) = Y2` when only prover knows `A2` but both know (`B2`, `Y2`). See [`discrete_log_pairing`].
9+
//!
610
//! Also implements the proof of **inequality of discrete log** (a value committed in a Pedersen commitment),
711
//! either with a public value or with another discrete log in [`Inequality`]. eg. Given a message `m`,
812
//! its commitment `C = g * m + h * r` and a public value `v`, proving that `m` ≠ `v`. Or given 2 messages
@@ -43,6 +47,7 @@
4347
//!
4448
//!
4549
//! [`Inequality`]: crate::inequality
50+
//! [`discrete_log_pairing`]: crate::discrete_log_pairing
4651
4752
use crate::error::SchnorrError;
4853
use ark_ec::{AffineRepr, CurveGroup, VariableBaseMSM};
@@ -63,6 +68,7 @@ use dock_crypto_utils::expect_equality;
6368
use rayon::prelude::*;
6469

6570
pub mod discrete_log;
71+
pub mod discrete_log_pairing;
6672
pub mod error;
6773
pub mod inequality;
6874

‎secret_sharing_and_dkg/README.md

+8-10
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
Implements Secret Sharing (SS), Verifiable Secret Sharing (VSS), Distributed Verifiable Secret Sharing (DVSS) and Distributed
44
Key Generation (DKG) algorithms. DVSS and DKG do not require a trusted dealer.
55

6-
1. [Shamir secret sharing (Requires a trusted dealer)](src/shamir_ss.rs)
7-
1. [Pedersen Verifiable Secret Sharing](src/pedersen_vss.rs)
8-
1. [Pedersen Distributed Verifiable Secret Sharing](src/pedersen_dvss.rs)
9-
1. [Feldman Verifiable Secret Sharing](src/feldman_vss.rs)
10-
1. [Feldman Distributed Verifiable Secret Sharing](src/feldman_dvss_dkg.rs)
11-
1. [Secure Distributed Key Generation for Discrete-Log Based Cryptosystems](src/gennaro_dkg.rs)
12-
1. [Distributed Key Generation from FROST](src/frost_dkg.rs)
13-
14-
**Note: This is largely a reimplementation of [secret-sharing-schemes](https://github.com/lovesh/secret-sharing-schemes) but
15-
based on arkworks-rs with some change in the API. Moreover, implements the Gennaro DKG and FROST's DKG**
6+
1. [Shamir secret sharing (Requires a trusted dealer)](./src/shamir_ss.rs)
7+
1. [Pedersen Verifiable Secret Sharing](./src/pedersen_vss.rs)
8+
1. [Pedersen Distributed Verifiable Secret Sharing](./src/pedersen_dvss.rs)
9+
1. [Feldman Verifiable Secret Sharing](./src/feldman_vss.rs)
10+
1. [Feldman Distributed Verifiable Secret Sharing](./src/feldman_dvss_dkg.rs)
11+
1. [Secure Distributed Key Generation for Discrete-Log Based Cryptosystems](./src/gennaro_dkg.rs)
12+
1. [Distributed Key Generation from FROST](./src/frost_dkg.rs)
13+
1. [Distributed discrete log (DLOG) check](./src/distributed_dlog_check)

0 commit comments

Comments
 (0)