Skip to content

Instantly share code, notes, and snippets.

@hdevalence
Last active August 24, 2018 06:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hdevalence/4ef3f3e4c2e9f434adba1b738411b66e to your computer and use it in GitHub Desktop.
Save hdevalence/4ef3f3e4c2e9f434adba1b738411b66e to your computer and use it in GitHub Desktop.
example of zkp-expanded dleq with merlin
create_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
mod dleq {
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::{MultiscalarMul, VartimeMultiscalarMul};
use merlin::Transcript;
use rand::thread_rng;
use std::iter;
pub struct Secrets<'a> {
// Create a parameter for each secret value
pub x: &'a Scalar,
}
pub struct Publics<'a> {
// Create a parameter for each public value
pub A: &'a RistrettoPoint,
pub B: &'a RistrettoPoint,
pub G: &'a RistrettoPoint,
pub H: &'a RistrettoPoint,
}
struct Commitments {
A: RistrettoPoint,
B: RistrettoPoint,
}
struct Randomnesses {
x: Scalar,
}
struct Responses {
x: Scalar,
}
impl Proof {
/// Create a `Proof` from the given `Publics` and `Secrets`.
pub fn create(transcript: &mut Transcript, publics: Publics, secrets: Secrets) -> Proof {
transcript.commit_bytes(b"domain-sep", "dleq".as_bytes());
transcript.commit_bytes("A".as_bytes(), publics.A.compress().as_bytes());
transcript.commit_bytes("B".as_bytes(), publics.B.compress().as_bytes());
transcript.commit_bytes("G".as_bytes(), publics.G.compress().as_bytes());
transcript.commit_bytes("H".as_bytes(), publics.H.compress().as_bytes());
let rng_ctor = transcript.fork_transcript();
let rng_ctor = rng_ctor.commit_witness_bytes("x".as_bytes(), secrets.x.as_bytes());
let mut transcript_rng = rng_ctor.reseed_from_rng(&mut thread_rng());
let rand = Randomnesses {
x: Scalar::random(&mut transcript_rng),
};
let commitments = Commitments {
A: RistrettoPoint::multiscalar_mul(&[rand.x], &[*(publics.G)]),
B: RistrettoPoint::multiscalar_mul(&[rand.x], &[*(publics.H)]),
};
transcript.commit_bytes("com A".as_bytes(), commitments.A.compress().as_bytes());
transcript.commit_bytes("com B".as_bytes(), commitments.B.compress().as_bytes());
let challenge = {
let mut bytes = [0; 64];
transcript.challenge_bytes(b"chal", &mut bytes);
Scalar::from_bytes_mod_order_wide(&bytes)
};
let responses = Responses {
x: &(&challenge * secrets.x) + &rand.x,
};
Proof {
challenge: challenge,
responses: responses,
}
}
/// Verify the `Proof` using the public parameters `Publics`.
pub fn verify(&self, transcript: &mut Transcript, publics: Publics) -> Result<(), ()> {
let responses = &self.responses;
let minus_c = -&self.challenge;
let commitments = Commitments {
A: RistrettoPoint::vartime_multiscalar_mul(
(&[responses.x]).into_iter().chain(iter::once(&(minus_c))),
(&[*(publics.G)]).into_iter().chain(iter::once(publics.A)),
),
B: RistrettoPoint::vartime_multiscalar_mul(
(&[responses.x]).into_iter().chain(iter::once(&(minus_c))),
(&[*(publics.H)]).into_iter().chain(iter::once(publics.B)),
),
};
transcript.commit_bytes(b"domain-sep", "dleq".as_bytes());
transcript.commit_bytes("A".as_bytes(), publics.A.compress().as_bytes());
transcript.commit_bytes("B".as_bytes(), publics.B.compress().as_bytes());
transcript.commit_bytes("G".as_bytes(), publics.G.compress().as_bytes());
transcript.commit_bytes("H".as_bytes(), publics.H.compress().as_bytes());
transcript.commit_bytes("com A".as_bytes(), commitments.A.compress().as_bytes());
transcript.commit_bytes("com B".as_bytes(), commitments.B.compress().as_bytes());
let challenge = {
let mut bytes = [0; 64];
transcript.challenge_bytes(b"chal", &mut bytes);
Scalar::from_bytes_mod_order_wide(&bytes)
};
if challenge == self.challenge {
Ok(())
} else {
Err(())
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment