2019-06-14 16:57:52 -07:00
|
|
|
// ped92.rs
|
2019-06-14 15:54:18 -07:00
|
|
|
use rand::{thread_rng, Rng};
|
2019-06-16 09:27:35 -07:00
|
|
|
use pairing::{Engine, CurveProjective};
|
2019-08-27 13:58:30 -07:00
|
|
|
use ff::{Rand, Field, PrimeField};
|
2019-07-26 01:18:54 -07:00
|
|
|
use std::fmt;
|
2019-07-29 14:13:40 -07:00
|
|
|
use util::is_vec_g1_equal;
|
|
|
|
use serde::{Serialize, Deserialize};
|
2019-08-27 13:58:30 -07:00
|
|
|
use util;
|
|
|
|
use std::borrow::BorrowMut;
|
2019-06-14 15:54:18 -07:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
2019-06-17 12:09:09 -07:00
|
|
|
pub struct CSParams<E: Engine> {
|
2019-07-12 07:46:25 -07:00
|
|
|
pub g: E::G1,
|
|
|
|
pub h: E::G1,
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
2019-07-31 19:06:57 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(bound(serialize = "<E as pairing::Engine>::G1: serde::Serialize"))]
|
|
|
|
#[serde(bound(deserialize = "<E as pairing::Engine>::G1: serde::Deserialize<'de>"))]
|
2019-06-14 15:54:18 -07:00
|
|
|
pub struct Commitment<E: Engine> {
|
2019-07-12 07:46:25 -07:00
|
|
|
pub c: E::G1,
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
2019-07-29 14:13:40 -07:00
|
|
|
impl<E: Engine> PartialEq for Commitment<E> {
|
|
|
|
fn eq(&self, other: &Commitment<E>) -> bool {
|
|
|
|
self.c == other.c
|
|
|
|
}
|
|
|
|
}
|
2019-07-26 01:18:54 -07:00
|
|
|
|
|
|
|
|
2019-07-29 21:53:58 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(bound(serialize = "<E as pairing::Engine>::G1: serde::Serialize"))]
|
|
|
|
#[serde(bound(deserialize = "<E as pairing::Engine>::G1: serde::Deserialize<'de>"))]
|
2019-06-17 12:09:09 -07:00
|
|
|
pub struct CSMultiParams<E: Engine> {
|
2019-07-23 06:54:53 -07:00
|
|
|
pub pub_bases: Vec<E::G1>
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
2019-07-29 14:13:40 -07:00
|
|
|
impl<E: Engine> PartialEq for CSMultiParams<E> {
|
|
|
|
fn eq(&self, other: &CSMultiParams<E>) -> bool {
|
|
|
|
is_vec_g1_equal::<E>(&self.pub_bases, &other.pub_bases)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-26 01:18:54 -07:00
|
|
|
impl<E: Engine> fmt::Display for CSMultiParams<E> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
|
|
|
let mut y_str = String::new();
|
|
|
|
let mut i = 0;
|
|
|
|
for y in self.pub_bases.iter() {
|
|
|
|
y_str = format!("{}\n{} => {}", y_str, i, y);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "CSMultiParams : (\n{}\n)", y_str)
|
|
|
|
}
|
|
|
|
}
|
2019-06-14 15:54:18 -07:00
|
|
|
|
2019-07-26 01:18:54 -07:00
|
|
|
impl<E: Engine> fmt::Display for Commitment<E> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "Commitment : (c={})", &self.c)
|
|
|
|
}
|
|
|
|
}
|
2019-06-14 15:54:18 -07:00
|
|
|
|
2019-06-17 12:09:09 -07:00
|
|
|
impl<E: Engine> CSParams<E> {
|
2019-06-14 17:55:02 -07:00
|
|
|
/*
|
2019-06-14 15:54:18 -07:00
|
|
|
Implements the setup algorithm for the Pedersen92 commitment scheme
|
|
|
|
*/
|
2019-06-14 17:55:02 -07:00
|
|
|
pub fn setup<R: Rng>(rng: &mut R) -> Self {
|
2019-07-12 07:46:25 -07:00
|
|
|
let g = E::G1::rand(rng);
|
|
|
|
let h = E::G1::rand(rng);
|
|
|
|
CSParams { g, h }
|
2019-06-14 17:55:02 -07:00
|
|
|
}
|
2019-06-14 15:54:18 -07:00
|
|
|
|
2019-06-14 17:55:02 -07:00
|
|
|
/*
|
2019-06-14 15:54:18 -07:00
|
|
|
commit(pk, msg) -> cm where
|
|
|
|
- pk is the public key generated from setup()
|
|
|
|
- msg is the message structure for the commitment scheme
|
|
|
|
- cm is the output commitment message for the given message
|
|
|
|
*/
|
2019-06-14 17:55:02 -07:00
|
|
|
pub fn commit<R: Rng>(&self, rng: &mut R, m: E::Fr, R: Option<E::Fr>) -> Commitment<E> {
|
|
|
|
let r = R.unwrap_or(E::Fr::rand(rng));
|
|
|
|
|
|
|
|
// c = g^m * h^r
|
2019-07-12 07:46:25 -07:00
|
|
|
let mut c = self.g.clone();
|
|
|
|
c.mul_assign(m.clone());
|
|
|
|
let mut h = self.h.clone();
|
|
|
|
h.mul_assign(r.clone());
|
|
|
|
c.add_assign(&h);
|
2019-06-14 17:55:02 -07:00
|
|
|
|
2019-07-12 07:46:25 -07:00
|
|
|
Commitment { c }
|
2019-06-14 17:55:02 -07:00
|
|
|
}
|
2019-06-14 15:54:18 -07:00
|
|
|
|
2019-06-14 17:55:02 -07:00
|
|
|
/*
|
2019-06-17 12:09:09 -07:00
|
|
|
decommit(csp, cm, msg) -> bool where
|
2019-06-14 15:54:18 -07:00
|
|
|
- cm is the commitment
|
|
|
|
- m is the message to validate
|
|
|
|
- outputs T/F for whether the cm is a valid commitment to the msg
|
|
|
|
*/
|
2019-06-17 12:09:09 -07:00
|
|
|
pub fn decommit(&self, cm: &Commitment<E>, m: &E::Fr, r: &E::Fr) -> bool {
|
2019-07-12 07:46:25 -07:00
|
|
|
let mut dm = self.g.clone();
|
|
|
|
dm.mul_assign(m.clone());
|
|
|
|
let mut h = self.h.clone();
|
|
|
|
h.mul_assign(r.clone());
|
|
|
|
dm.add_assign(&h);
|
|
|
|
dm == cm.c
|
2019-06-14 17:55:02 -07:00
|
|
|
}
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-17 12:09:09 -07:00
|
|
|
impl<E: Engine> CSMultiParams<E> {
|
2019-06-14 16:57:52 -07:00
|
|
|
/*
|
|
|
|
Implements the setup algorithm for the Pedersen92 commitment scheme over
|
2019-07-05 14:57:03 -07:00
|
|
|
a vector of messages of length len.
|
2019-06-14 16:57:52 -07:00
|
|
|
*/
|
|
|
|
pub fn setup_gen_params<R: Rng>(rng: &mut R, len: usize) -> Self {
|
2019-07-12 07:46:25 -07:00
|
|
|
let mut p: Vec<E::G1> = Vec::new();
|
2019-07-07 13:38:38 -07:00
|
|
|
// 1 extra base element for the random parameter
|
2019-07-05 14:57:03 -07:00
|
|
|
for i in 0..len + 1 {
|
2019-07-12 07:46:25 -07:00
|
|
|
p.push(E::G1::rand(rng));
|
2019-06-14 16:57:52 -07:00
|
|
|
}
|
2019-07-12 07:46:25 -07:00
|
|
|
CSMultiParams { pub_bases: p }
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
2019-07-05 14:57:03 -07:00
|
|
|
pub fn commit(&self, x: &Vec<E::Fr>, r: &E::Fr) -> Commitment<E> {
|
2019-06-14 16:57:52 -07:00
|
|
|
// c = g1^m1 * ... * gn^mn * h^r
|
2019-07-12 07:46:25 -07:00
|
|
|
let mut c = self.pub_bases[0].clone();
|
2019-07-27 12:09:03 -07:00
|
|
|
let p_len = self.pub_bases.len();
|
2019-07-12 07:46:25 -07:00
|
|
|
c.mul_assign(r.clone());
|
2019-07-27 12:09:03 -07:00
|
|
|
//println!("commit => x.len = {}, p.len = {}", x.len(), p_len);
|
2019-07-05 14:57:03 -07:00
|
|
|
for i in 0..x.len() {
|
2019-07-27 12:09:03 -07:00
|
|
|
if (i < p_len) {
|
|
|
|
let mut basis = self.pub_bases[i + 1];
|
|
|
|
basis.mul_assign(x[i]);
|
|
|
|
c.add_assign(&basis);
|
|
|
|
}
|
2019-06-14 16:57:52 -07:00
|
|
|
}
|
2019-07-12 07:46:25 -07:00
|
|
|
Commitment { c }
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
2019-07-23 06:54:53 -07:00
|
|
|
pub fn extend_commit(&self, com: &Commitment<E>, x: &E::Fr) -> Commitment<E> {
|
|
|
|
// c = com * gn+1 ^ x
|
|
|
|
let len = self.pub_bases.len();
|
|
|
|
let mut c = self.pub_bases[len-1].clone();
|
|
|
|
c.mul_assign(x.clone());
|
|
|
|
c.add_assign(&com.c);
|
|
|
|
|
|
|
|
return Commitment { c };
|
|
|
|
}
|
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
pub fn remove_commit(&self, com: &Commitment<E>, x: &E::Fr) -> Commitment<E> {
|
|
|
|
// c = com * gn+1 ^ x
|
|
|
|
let len = self.pub_bases.len();
|
|
|
|
let mut c = self.pub_bases[len-1].clone();
|
|
|
|
let xx = x.clone();
|
|
|
|
c.mul_assign(xx);
|
|
|
|
c.negate();
|
|
|
|
c.add_assign(&com.c);
|
|
|
|
|
|
|
|
return Commitment { c };
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-17 12:09:09 -07:00
|
|
|
pub fn decommit(&self, cm: &Commitment<E>, x: &Vec<E::Fr>, r: &E::Fr) -> bool {
|
2019-06-14 16:57:52 -07:00
|
|
|
let l = x.len();
|
|
|
|
// pub_base[0] => h, x[0] => r
|
2019-07-12 07:46:25 -07:00
|
|
|
let mut dc = self.pub_bases[0].clone();
|
|
|
|
dc.mul_assign(r.clone());
|
2019-07-05 14:57:03 -07:00
|
|
|
for i in 0..l {
|
2019-07-12 07:46:25 -07:00
|
|
|
let mut basis = self.pub_bases[i+1];
|
|
|
|
basis.mul_assign(x[i]);
|
|
|
|
dc.add_assign(&basis);
|
2019-06-14 16:57:52 -07:00
|
|
|
}
|
2019-07-12 07:46:25 -07:00
|
|
|
return dc == cm.c;
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 13:58:30 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
|
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Serialize"
|
|
|
|
))]
|
|
|
|
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
|
|
|
))]
|
|
|
|
pub struct CommitmentProof<E: Engine> {
|
|
|
|
pub T: E::G1,
|
|
|
|
pub z: Vec<E::Fr>,
|
|
|
|
pub t: Vec<E::Fr>,
|
|
|
|
pub index: Vec<usize>,
|
|
|
|
pub reveal: Vec<E::Fr>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Engine> CommitmentProof<E> {
|
|
|
|
pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>) -> Self {
|
|
|
|
let (Tvals, t, rt, mut reveal_wallet) = CommitmentProof::<E>::prove_commitment::<R>(csprng, com_params, wallet, reveal_index);
|
|
|
|
|
|
|
|
// compute the challenge
|
|
|
|
let x: Vec<E::G1> = vec![Tvals, com.clone()];
|
|
|
|
let challenge = util::hash_g1_to_fr::<E>(&x);
|
|
|
|
|
|
|
|
// compute the response
|
|
|
|
CommitmentProof::<E>::prove_response(wallet, r, reveal_index, Tvals, &t, rt, reveal_wallet.borrow_mut(), &challenge)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn prove_commitment<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, wallet: &Vec<E::Fr>, reveal_index: &Vec<usize>) -> (E::G1, Vec<E::Fr>, Vec<E::Fr>, Vec<E::Fr>) {
|
|
|
|
let mut Tvals = E::G1::zero();
|
|
|
|
assert!(wallet.len() <= com_params.pub_bases.len());
|
|
|
|
let mut t = Vec::<E::Fr>::with_capacity(wallet.len() + 1);
|
|
|
|
let mut rt: Vec<E::Fr> = Vec::new();
|
|
|
|
// t values that will be revealed
|
|
|
|
let mut reveal_wallet: Vec<E::Fr> = Vec::new();
|
|
|
|
// aspects of wallet being revealed
|
|
|
|
for i in 0..wallet.len() + 1 {
|
|
|
|
let ti = E::Fr::rand(csprng);
|
|
|
|
t.push(ti);
|
|
|
|
// check if we are revealing this index
|
|
|
|
if reveal_index.contains(&i) {
|
|
|
|
rt.push(ti);
|
|
|
|
} else {
|
|
|
|
rt.push(E::Fr::zero());
|
|
|
|
}
|
|
|
|
let mut gt = com_params.pub_bases[i].clone();
|
|
|
|
gt.mul_assign(ti.into_repr());
|
|
|
|
Tvals.add_assign(>);
|
|
|
|
}
|
|
|
|
(Tvals, t, rt, reveal_wallet)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn prove_response(wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>, Tvals: E::G1, t: &Vec<E::Fr>, rt: Vec<E::Fr>, reveal_wallet: &mut Vec<E::Fr>, challenge: &E::Fr) -> CommitmentProof<E> {
|
|
|
|
let mut z: Vec<E::Fr> = Vec::new();
|
|
|
|
let mut z0 = r.clone();
|
|
|
|
z0.mul_assign(&challenge);
|
|
|
|
z0.add_assign(&t[0]);
|
|
|
|
z.push(z0);
|
|
|
|
reveal_wallet.push(E::Fr::zero());
|
|
|
|
for i in 1..t.len() {
|
|
|
|
let mut zi = wallet[i - 1].clone();
|
|
|
|
zi.mul_assign(&challenge);
|
|
|
|
zi.add_assign(&t[i]);
|
|
|
|
z.push(zi);
|
|
|
|
// check if we are revealing this index
|
|
|
|
if reveal_index.contains(&i) {
|
|
|
|
reveal_wallet.push(wallet[i - 1].clone());
|
|
|
|
} else {
|
|
|
|
reveal_wallet.push(E::Fr::zero());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CommitmentProof {
|
|
|
|
T: Tvals, // commitment challenge
|
|
|
|
z: z, // response values
|
|
|
|
t: rt, // randomness for verifying partial reveals
|
|
|
|
index: reveal_index.clone(),
|
|
|
|
reveal: reveal_wallet.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn verify_proof(&self, com_params: &CSMultiParams<E>, com: &<E as Engine>::G1, challenge: &E::Fr) -> bool {
|
|
|
|
let mut comc = com.clone();
|
|
|
|
let T = self.T.clone();
|
|
|
|
comc.mul_assign(challenge.into_repr());
|
|
|
|
comc.add_assign(&T);
|
|
|
|
let mut x = E::G1::zero();
|
|
|
|
for i in 0..self.z.len() {
|
|
|
|
let mut base = com_params.pub_bases[i].clone();
|
|
|
|
base.mul_assign(self.z[i].into_repr());
|
|
|
|
x.add_assign(&base);
|
|
|
|
}
|
|
|
|
comc == x
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 15:54:18 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use pairing::bls12_381::{Bls12, Fr};
|
|
|
|
use ff::Field;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn commit_one_message_works() {
|
|
|
|
let rng = &mut thread_rng();
|
2019-06-17 12:09:09 -07:00
|
|
|
let csp = CSParams::<Bls12>::setup(rng);
|
2019-06-14 15:54:18 -07:00
|
|
|
|
|
|
|
let m1 = Fr::rand(rng);
|
|
|
|
let mut m2 = m1.clone();
|
|
|
|
m2.add_assign(&Fr::one());
|
|
|
|
let r = Fr::rand(rng);
|
2019-06-17 12:09:09 -07:00
|
|
|
let c = csp.commit(rng, m1, Some(r));
|
2019-06-14 15:54:18 -07:00
|
|
|
|
2019-06-18 14:46:54 -07:00
|
|
|
assert_eq!(csp.decommit(&c, &m1, &r), true);
|
|
|
|
assert_eq!(csp.decommit(&c, &m2, &r), false);
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn commit_n_message_works() {
|
|
|
|
let rng = &mut thread_rng();
|
|
|
|
let len = 3;
|
2019-06-17 12:09:09 -07:00
|
|
|
let csp = CSMultiParams::<Bls12>::setup_gen_params(rng, len);
|
2019-06-14 15:54:18 -07:00
|
|
|
|
|
|
|
let mut m: Vec<Fr> = Vec::new();
|
2019-06-14 15:59:33 -07:00
|
|
|
for i in 0..len {
|
2019-06-14 15:54:18 -07:00
|
|
|
m.push(Fr::rand(rng));
|
|
|
|
}
|
2019-07-05 14:57:03 -07:00
|
|
|
let r = Fr::rand(rng);
|
|
|
|
let c = csp.commit(&m, &r);
|
2019-06-14 15:54:18 -07:00
|
|
|
|
2019-06-18 14:46:54 -07:00
|
|
|
assert_eq!(csp.decommit(&c, &m, &r), true);
|
2019-06-17 12:09:09 -07:00
|
|
|
let mut r1 = r.clone();
|
|
|
|
r1.add_assign(&Fr::one());
|
2019-06-18 14:46:54 -07:00
|
|
|
assert_eq!(csp.decommit(&c, &m, &r1), false);
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|
2019-07-25 17:39:36 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn commit_variable_messages_works() {
|
|
|
|
let rng = &mut thread_rng();
|
|
|
|
let len = 5;
|
|
|
|
let csp = CSMultiParams::<Bls12>::setup_gen_params(rng, len);
|
|
|
|
|
|
|
|
let mut m1: Vec<Fr> = Vec::new();
|
|
|
|
for i in 0..len-1 {
|
|
|
|
m1.push(Fr::rand(rng));
|
|
|
|
}
|
|
|
|
let extra_m = Fr::rand(rng);
|
|
|
|
let r = Fr::rand(rng);
|
|
|
|
|
|
|
|
let c1 = csp.commit(&m1, &r);
|
|
|
|
|
|
|
|
assert_eq!(csp.decommit(&c1, &m1, &r), true);
|
|
|
|
let mut r1 = r.clone();
|
|
|
|
r1.add_assign(&Fr::one());
|
|
|
|
assert_eq!(csp.decommit(&c1, &m1, &r1), false);
|
|
|
|
|
|
|
|
// let's add another message
|
|
|
|
let mut m2 = m1.clone();
|
|
|
|
m2.push(extra_m);
|
|
|
|
let c2 = csp.commit(&m2, &r);
|
|
|
|
assert_eq!(csp.decommit(&c2, &m2, &r), true);
|
|
|
|
}
|
2019-07-28 22:18:40 -07:00
|
|
|
|
2019-07-31 19:06:57 -07:00
|
|
|
#[test]
|
|
|
|
fn test_csp_basic_serialize() {
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
let len = 5;
|
|
|
|
let csp = CSMultiParams::<Bls12>::setup_gen_params(rng, len);
|
|
|
|
|
|
|
|
let serialized = serde_json::to_string(&csp).unwrap();
|
|
|
|
|
|
|
|
let csp_des: CSMultiParams<Bls12> = serde_json::from_str(&serialized).unwrap();
|
|
|
|
}
|
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// add tests for extend/remove commits dynamically
|
2019-06-14 15:54:18 -07:00
|
|
|
}
|