sigma_protocols/protocols/
schnorr.rs

1//! Schnorr proof of knowledge of discrete logarithm.
2//!
3//! Proves knowledge of x such that X = x * G for a public point X.
4
5use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
6use curve25519_dalek::ristretto::RistrettoPoint;
7use curve25519_dalek::scalar::Scalar;
8
9use crate::error::Result;
10use crate::sigma::{PointCommitment, ScalarChallenge, ScalarResponse, SigmaProtocol};
11use crate::utils::{random_scalar, scalar_from_state};
12
13/// Public statement for Schnorr proof: the public key.
14#[derive(Clone, Debug)]
15pub struct SchnorrStatement {
16    pub public_key: RistrettoPoint,
17}
18
19/// Private witness for Schnorr proof: the secret key.
20#[derive(Clone, Debug)]
21pub struct SchnorrWitness {
22    pub secret_key: Scalar,
23}
24
25/// Schnorr proof implementation.
26///
27/// Proves knowledge of discrete logarithm x such that X = x * G.
28pub struct SchnorrProof;
29
30impl SigmaProtocol for SchnorrProof {
31    type Statement = SchnorrStatement;
32    type Witness = SchnorrWitness;
33    type Commitment = PointCommitment;
34    type Challenge = ScalarChallenge;
35    type Response = ScalarResponse;
36
37    fn prover_commit(
38        _statement: &Self::Statement,
39        _witness: &Self::Witness,
40    ) -> (Self::Commitment, Vec<u8>) {
41        let r = random_scalar();
42        let commitment = r * RISTRETTO_BASEPOINT_POINT;
43        (PointCommitment(commitment), r.to_bytes().to_vec())
44    }
45
46    fn prover_response(
47        _statement: &Self::Statement,
48        witness: &Self::Witness,
49        state: &[u8],
50        challenge: &Self::Challenge,
51    ) -> Result<Self::Response> {
52        let r = scalar_from_state(state)?;
53        let response = r + challenge.0 * witness.secret_key;
54        Ok(ScalarResponse(response))
55    }
56
57    fn verifier(
58        statement: &Self::Statement,
59        commitment: &Self::Commitment,
60        challenge: &Self::Challenge,
61        response: &Self::Response,
62    ) -> Result<()> {
63        let lhs = response.0 * RISTRETTO_BASEPOINT_POINT;
64        let rhs = commitment.0 + challenge.0 * statement.public_key;
65
66        if lhs == rhs {
67            Ok(())
68        } else {
69            Err(crate::error::Error::InvalidProof)
70        }
71    }
72}