sigma_protocols/protocols/
dleq.rs1use curve25519_dalek::ristretto::RistrettoPoint;
7use curve25519_dalek::scalar::Scalar;
8use rand::rngs::OsRng;
9use rand::TryRngCore;
10
11use crate::error::{Error, Result};
12use crate::sigma::{MultiPointCommitment, ScalarChallenge, ScalarResponse, SigmaProtocol};
13
14#[derive(Clone, Debug)]
18pub struct DLEQStatement {
19 pub g: RistrettoPoint,
20 pub h: RistrettoPoint,
21 pub x: RistrettoPoint,
22 pub y: RistrettoPoint,
23}
24
25#[derive(Clone, Debug)]
27pub struct DLEQWitness {
28 pub alpha: Scalar,
29}
30
31pub struct DLEQProof;
35
36impl SigmaProtocol for DLEQProof {
37 type Statement = DLEQStatement;
38 type Witness = DLEQWitness;
39 type Commitment = MultiPointCommitment;
40 type Challenge = ScalarChallenge;
41 type Response = ScalarResponse;
42
43 fn prover_commit(
44 statement: &Self::Statement,
45 _witness: &Self::Witness,
46 ) -> (Self::Commitment, Vec<u8>) {
47 let mut r_bytes = [0u8; 32];
48 OsRng
49 .try_fill_bytes(&mut r_bytes)
50 .expect("Failed to generate random bytes");
51 let r = Scalar::from_bytes_mod_order(r_bytes);
52
53 let a = r * statement.g;
54 let b = r * statement.h;
55
56 let state = r.to_bytes().to_vec();
57
58 (MultiPointCommitment(vec![a, b]), state)
59 }
60
61 fn prover_response(
62 _statement: &Self::Statement,
63 witness: &Self::Witness,
64 state: &[u8],
65 challenge: &Self::Challenge,
66 ) -> Result<Self::Response> {
67 if state.len() != 32 {
68 return Err(Error::InvalidProof);
69 }
70
71 let mut r_bytes = [0u8; 32];
72 r_bytes.copy_from_slice(state);
73 let r_option = Scalar::from_canonical_bytes(r_bytes);
74
75 let r = if r_option.is_some().unwrap_u8() == 1 {
76 r_option.unwrap()
77 } else {
78 return Err(Error::InvalidScalar);
79 };
80
81 let response = r + challenge.0 * witness.alpha;
82
83 Ok(ScalarResponse(response))
84 }
85
86 fn verifier(
87 statement: &Self::Statement,
88 commitment: &Self::Commitment,
89 challenge: &Self::Challenge,
90 response: &Self::Response,
91 ) -> Result<()> {
92 if commitment.0.len() != 2 {
93 return Err(Error::InvalidCommitment);
94 }
95
96 let a = commitment.0[0];
97 let b = commitment.0[1];
98
99 let lhs_g = response.0 * statement.g;
100 let rhs_g = a + challenge.0 * statement.x;
101
102 let lhs_h = response.0 * statement.h;
103 let rhs_h = b + challenge.0 * statement.y;
104
105 if lhs_g == rhs_g && lhs_h == rhs_h {
106 Ok(())
107 } else {
108 Err(Error::InvalidProof)
109 }
110 }
111}