sigma-protocols 0.5.1

SIGMA zero-knowledge proof protocols
Documentation
//! Schnorr proof of knowledge of discrete logarithm.
//!
//! Proves knowledge of x such that X = x * G for a public point X.

use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;

use crate::error::Result;
use crate::sigma::{PointCommitment, ScalarChallenge, ScalarResponse, SigmaProtocol};
use crate::utils::{random_scalar, scalar_from_state};

/// Public statement for Schnorr proof: the public key.
#[derive(Clone, Debug)]
pub struct SchnorrStatement {
    pub public_key: RistrettoPoint,
}

/// Private witness for Schnorr proof: the secret key.
#[derive(Clone, Debug)]
pub struct SchnorrWitness {
    pub secret_key: Scalar,
}

/// Schnorr proof implementation.
///
/// Proves knowledge of discrete logarithm x such that X = x * G.
pub struct SchnorrProof;

impl SigmaProtocol for SchnorrProof {
    type Statement = SchnorrStatement;
    type Witness = SchnorrWitness;
    type Commitment = PointCommitment;
    type Challenge = ScalarChallenge;
    type Response = ScalarResponse;

    fn prover_commit(
        _statement: &Self::Statement,
        _witness: &Self::Witness,
    ) -> (Self::Commitment, Vec<u8>) {
        let r = random_scalar();
        let commitment = r * RISTRETTO_BASEPOINT_POINT;
        (PointCommitment(commitment), r.to_bytes().to_vec())
    }

    fn prover_response(
        _statement: &Self::Statement,
        witness: &Self::Witness,
        state: &[u8],
        challenge: &Self::Challenge,
    ) -> Result<Self::Response> {
        let r = scalar_from_state(state)?;
        let response = r + challenge.0 * witness.secret_key;
        Ok(ScalarResponse(response))
    }

    fn verifier(
        statement: &Self::Statement,
        commitment: &Self::Commitment,
        challenge: &Self::Challenge,
        response: &Self::Response,
    ) -> Result<()> {
        let lhs = response.0 * RISTRETTO_BASEPOINT_POINT;
        let rhs = commitment.0 + challenge.0 * statement.public_key;

        if lhs == rhs {
            Ok(())
        } else {
            Err(crate::error::Error::InvalidProof)
        }
    }
}