sigma_protocols/protocols/
dleq.rs

1//! Discrete Logarithm Equality (DLEQ) proof.
2//!
3//! Proves that two points share the same discrete logarithm with respect to different bases.
4//! Specifically, proves knowledge of α such that X = α * G and Y = α * H.
5
6use curve25519_dalek::ristretto::RistrettoPoint;
7use curve25519_dalek::scalar::Scalar;
8
9use crate::error::{Error, Result};
10use crate::sigma::{MultiPointCommitment, ScalarChallenge, ScalarResponse, SigmaProtocol};
11use crate::utils::{random_scalar, scalar_from_state};
12
13/// Public statement for DLEQ proof.
14///
15/// Contains two base points (g, h) and two result points (x, y).
16#[derive(Clone, Debug)]
17pub struct DLEQStatement {
18    pub g: RistrettoPoint,
19    pub h: RistrettoPoint,
20    pub x: RistrettoPoint,
21    pub y: RistrettoPoint,
22}
23
24/// Private witness for DLEQ proof: the common discrete logarithm.
25#[derive(Clone, Debug)]
26pub struct DLEQWitness {
27    pub alpha: Scalar,
28}
29
30/// DLEQ proof implementation.
31///
32/// Proves that log_g(x) = log_h(y) without revealing the common logarithm.
33pub struct DLEQProof;
34
35impl SigmaProtocol for DLEQProof {
36    type Statement = DLEQStatement;
37    type Witness = DLEQWitness;
38    type Commitment = MultiPointCommitment;
39    type Challenge = ScalarChallenge;
40    type Response = ScalarResponse;
41
42    fn prover_commit(
43        statement: &Self::Statement,
44        _witness: &Self::Witness,
45    ) -> (Self::Commitment, Vec<u8>) {
46        let r = random_scalar();
47        let a = r * statement.g;
48        let b = r * statement.h;
49        (MultiPointCommitment(vec![a, b]), r.to_bytes().to_vec())
50    }
51
52    fn prover_response(
53        _statement: &Self::Statement,
54        witness: &Self::Witness,
55        state: &[u8],
56        challenge: &Self::Challenge,
57    ) -> Result<Self::Response> {
58        let r = scalar_from_state(state)?;
59        let response = r + challenge.0 * witness.alpha;
60        Ok(ScalarResponse(response))
61    }
62
63    fn verifier(
64        statement: &Self::Statement,
65        commitment: &Self::Commitment,
66        challenge: &Self::Challenge,
67        response: &Self::Response,
68    ) -> Result<()> {
69        if commitment.0.len() != 2 {
70            return Err(Error::InvalidCommitment);
71        }
72
73        let a = commitment.0[0];
74        let b = commitment.0[1];
75
76        let lhs_g = response.0 * statement.g;
77        let rhs_g = a + challenge.0 * statement.x;
78
79        let lhs_h = response.0 * statement.h;
80        let rhs_h = b + challenge.0 * statement.y;
81
82        if lhs_g == rhs_g && lhs_h == rhs_h {
83            Ok(())
84        } else {
85            Err(Error::InvalidProof)
86        }
87    }
88}