signifcant improvements

This commit is contained in:
J. Ayo Akinyele 2018-06-09 03:14:50 -04:00
parent 1ff493b6e1
commit 623cb0c873
5 changed files with 164 additions and 165 deletions

View File

@ -18,6 +18,7 @@ use libbolt::ote;
use libbolt::clsigs;
use libbolt::commit_scheme;
use time::PreciseTime;
use libbolt::bidirectional;
#[doc(hidden)]
#[macro_export]
@ -374,121 +375,102 @@ fn main() {
println!("{} seconds for verifying invalid signatures.", end1.to(end2));
// let rng = &mut rand::thread_rng();
// let G = G1::random(rng); // &dalek_constants::RISTRETTO_BASEPOINT_POINT;
// let H = G1::random(rng); // RistrettoPoint::hash_from_bytes::<Sha256>(G.compress().as_bytes());
// println!("******************************************");
// let b = keypair.pk.Z2.len();
// let mut bases: Vec<G2> = Vec::new();
// bases.push(mpk.g2);
// for i in 0 .. b {
// bases.push(keypair.pk.Z2[i]);
// }
//
// // simple ZKP
// generate_nipk!{dleq, (x), (A, G) : A = (G * x) }
// // generate sample commitment
// //let mut m: Vec<Fr> = Vec::new();
// let mut C = mpk.g2 * m1[0];
// for i in 0 .. b {
// println!("index: {}", i);
// C = C + (keypair.pk.Z2[i] * m1[i+1]);
// }
// let msg = "Sample Commit output:";
// libbolt::debug_g2_in_hex(msg, &C);
//
// let x = Fr::from_str("89327492234").unwrap();
// let A = G * x;
// let B = H * x;
// let cm_csp = commit_scheme::setup(b, keypair.pk.Z2, mpk.g2);
// let r = m1[0];
// let w_com = commit_scheme::commit(&cm_csp, &m1, r);
//
// let publics = dleq::Publics{A: &A, G: G};
// let secrets = dleq::Secrets{x: &x};
// assert!(commit_scheme::decommit(&cm_csp, &w_com, &m1));
//
// //let msg = "Commmit Scheme output:";
// //libbolt::debug_g2_in_hex(msg, &w_com.c);
//
// //assert_eq!(C, w_com.c);
// println!("Commitment scheme consistent!!");
// let proof = clsigs::bs_gen_nizk_proof(&m1, &cm_csp.pub_bases, w_com.c);
// // old -> let proof = clsigs::bs_gen_nizk_proof(&m1, &bases, C);
//
// let int_sig = clsigs::bs_gen_signature(&mpk, &keypair.sk, &proof);
//
// println!("Generated signature interactively!");
// generate_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
// let proof = clsigs::bs_gen_nizk_proof(&m1, &bases, C);
//
// let x = Fr::from_str("89327492234").unwrap();
// let A = G * x;
// let B = H * x;
// let int_sig = clsigs::bs_gen_signature(&mpk, &keypair.sk, &proof);
//
// let publics = dleq::Publics{A: &A, B: &B, G: G, H: &H};
// let secrets = dleq::Secrets{x: &x};
// println!("Generated signature interactively!");
// // int_sig = interactively generated signature
// assert!(clsigs::verifyD(&mpk, &keypair.pk, &m1, &int_sig) == true);
//
// let proof = dleq::Proof::create(&mut rng, publics, secrets);
// // serialize to bincode representation
// let proof_bytes = bincode::serialize(&proof, bincode::Infinite).unwrap();
// // parse bytes back to memory
// let parsed_proof: dleq::Proof
// = bincode::deserialize(&proof_bytes).unwrap();
// println!("Verified interactively produced signature!");
//
// assert!(parsed_proof.verify(publics).is_ok());
// let blind_sigs = clsigs::prover_generate_blinded_sig(&int_sig);
// let common_params = clsigs::gen_common_params(&mpk, &keypair.pk, &int_sig);
// let proof_vs = clsigs::vs_gen_nizk_proof(&m1, &common_params, common_params.vx);
// assert!(clsigs::vs_verify_blind_sig(&mpk, &keypair.pk, &proof_vs, &blind_sigs));
//
// println!("Verified blind signature!");
println!("******************************************");
let b = keypair.pk.Z2.len();
let mut bases: Vec<G2> = Vec::new();
bases.push(mpk.g2);
for i in 0 .. b {
bases.push(keypair.pk.Z2[i]);
}
// generate sample commitment
let mut C = mpk.g2 * m1[0];
for i in 0 .. b {
C = C + (keypair.pk.Z2[i] * m1[i+1]);
}
let proof = clsigs::bs_gen_nizk_proof(&m1, &bases, C);
println!("[1] libbolt - setup bidirecitonal scheme params");
let pp = bidirectional::setup();
let int_sig = clsigs::bs_gen_signature(&mpk, &keypair.sk, &proof);
// generate long-lived keypair for merchant -- used to identify
// it to all customers
println!("[2] libbolt - generate long-lived key pair for merchant");
let merch_keypair = bidirectional::keygen(&pp);
println!("Generated signature interactively!");
// int_sig = interactively generated signature
assert!(clsigs::verifyD(&mpk, &keypair.pk, &m1, &int_sig) == true);
// customer gnerates an ephemeral keypair for use on a single channel
println!("[3] libbolt - generate ephemeral key pair for customer (use with one channel)");
let cust_keypair = bidirectional::keygen(&pp);
println!("Verified interactively produced signature!");
// bidirectional::init_merchant_state();
let blind_sigs = clsigs::prover_generate_blinded_sig(&int_sig);
let common_params = clsigs::gen_common_params(&mpk, &keypair.pk, &int_sig);
let proof_vs = clsigs::vs_gen_nizk_proof(&m1, &common_params, common_params.vx);
assert!(clsigs::vs_verify_blind_sig(&mpk, &keypair.pk, &proof_vs, &blind_sigs));
println!("[4] libbolt - generate the channel identifier");
let b0_cust = 10;
let b0_merch = 15;
let cid = bidirectional::generate_channel_id();
let mut msg = "Open Channel ID: ";
libbolt::debug_elem_in_hex(msg, &cid);
println!("Verified blind signature!");
// each party executes the init algorithm on the agreed initial challence balance
// in order to derive the channel tokens
println!("[5a] libbolt - initialize on the customer side with balance {}", b0_cust);
let mut init_cust_data = bidirectional::init_customer(&pp, cid, b0_cust, &cust_keypair);
// sym::init();
// // SymKeyEnc tests
// let l = 128; // TODO: figure out how to apply this to secretbox
// let key1 = sym::keygen(l);
// //let key2 = sym::keygen(l);
//
// // println!("key: {:?}", key);
//
// let pt1 = String::from("hello world");
// let ciphertext = sym::encrypt(&key1, &pt1);
// println!("{}", ciphertext);
//
// let pt2 = sym::decrypt(&key1, &ciphertext);
// println!("Recovered plaintext: {}", pt2);
// assert!(pt1 == pt2);
//
//// let pt3 = sym::decrypt(&key2, &ciphertext);
//// assert!(pt1 != pt3);
// println!("SymKeyEnc is complete!");
// println!("******************************************");
//
// // CL sig tests
// let mpk = clsigs::setup();
// let keypair = clsigs::keygen(&mpk);
// println!("{}", keypair.pk);
//
// let msg1 = libbolt::RefundMessage::new(alice_sk, 10).hash(); // TODO: add ck (l-bit key)
// let msg2 = libbolt::RefundMessage::new(alice_sk, 11).hash(); // TODO: add ck (l-bit key)
// let signature = clsigs::sign(&keypair.sk, msg1);
// println!("{}", signature);
// assert!(clsigs::verify(&mpk, &keypair.pk, msg1, &signature) == true);
// assert!(clsigs::verify(&mpk, &keypair.pk, msg2, &signature) == false);
//
// println!("CL signature verified!");
//
// println!("******************************************");
// // commitment scheme tests
// let pk = commit_scheme::setup();
// // let sk = libbolt::SecretKeySigs { x: Fr::random(rng), y: Fr::random(rng) };
// // let msg = String::from("Hello, World!");
// let msg1 = libbolt::Message::new(keypair.sk, alice_sk, bob_sk, 10).hash();
// let msg2 = libbolt::Message::new(keypair.sk, alice_sk, bob_sk, 11).hash();
// let msg3 = libbolt::Message::new(keypair.sk, bob_sk, alice_sk, 10).hash();
//
// let cm = commit_scheme::commit(&pk, msg1, None);
//
// assert!(commit_scheme::decommit(&pk, &cm, msg1) == true);
// assert!(commit_scheme::decommit(&pk, &cm, msg2) == false);
// assert!(commit_scheme::decommit(&pk, &cm, msg3) == false);
// println!("Commitment scheme works!");
//
// println!("******************************************");
println!("[5b] libbolt - initialize on the merchant side with balance {}", b0_merch);
let mut init_merch_data = bidirectional::init_merchant(&pp, b0_merch, &merch_keypair);
// TODO: write tests
println!("[6a] libbolt - entering the establish protocol for the channel");
let proof1 = bidirectional::establish_customer_phase1(&pp, &init_cust_data);
println!("[6b] libbolt - obtain the wallet signature from the merchant");
let wallet_sig = bidirectional::establish_merchant_phase2(&pp, &init_merch_data, &proof1);
println!("[6c] libbolt - complete channel establishment");
let is_established = bidirectional::establish_customer_phase3(wallet_sig, &mut init_cust_data.csk);
assert!(is_established);
println!("Channel has been established! Woohoo!");
}

View File

@ -528,7 +528,7 @@ The bidirectional payment construction enables compact closure and compact walle
\item Customer generates wallet commitment by sampling random coins $r$.
\item Compute ephemeral keypair $(wpk, wsk) \leftarrow {\sf KeyGen}({\sf PP})$.
\item Compute ${\sf wCom} = {\sf Commit}({\sf cID}, wpk, \BC; r)$.
\item For $i = 1$ to $\BC$, sample $ck_i \rightarrow {\sf SymKeyGen}(1^\lambda)$ to form the vector $\vec{ck}$.
%\item For $i = 1$ to $\BC$, sample $ck_i \rightarrow {\sf SymKeyGen}(1^\lambda)$ to form the vector $\vec{ck}$.
\item Output ${\sf T}_{\sf c} = (pk_c, {\sf wCom})$ and retains secret $csk_{\sf c} = (sk_c, {\sf cID}, wpk, wsk, r, \BC)$.
\end{itemize}

View File

@ -188,7 +188,7 @@ pub fn setupD() -> PublicParams {
return mpk;
}
pub fn keygenD(mpk : &PublicParams, l: i32) -> KeyPairD {
pub fn keygenD(mpk : &PublicParams, l: usize) -> KeyPairD {
let rng = &mut rand::thread_rng();
let x = Fr::random(rng);
let y = Fr::random(rng);
@ -342,8 +342,8 @@ pub fn bs_gen_nizk_proof(x: &Vec<Fr>, pub_bases: &Vec<G2>, C: G2) -> ProofCV {
// hash T to get the challenge
let c = hashG2ToFr(&T);
//let msg = "challenge -> c";
//debug_elem_in_hex(msg, &c);
let msg = "challenge -> c";
debug_elem_in_hex(msg, &c);
// compute s values
let mut s: Vec<Fr> = Vec::new();
@ -368,8 +368,8 @@ pub fn bs_gen_signature(mpk: &PublicParams, sk: &SecretKeyD, proof: &ProofCV) ->
fn part1_verify_proof(proof: &ProofCV) -> bool {
// if proof is valid, then call part
let c = hashG2ToFr(&proof.T);
//let mut msg = "(in verify proof) challenge -> c";
//debug_elem_in_hex(msg, &c);
let mut msg = "(in verify proof) challenge -> c";
debug_elem_in_hex(msg, &c);
let l = proof.s.len();
assert!(l > 1);
@ -379,12 +379,12 @@ fn part1_verify_proof(proof: &ProofCV) -> bool {
//println!("(in verify proof) i => {}", i);
lhs = lhs + (proof.pub_bases[i] * proof.s[i]);
}
//msg = "(in verify proof) lhs => ";
//debug_g2_in_hex(msg, &lhs);
msg = "(in verify proof) lhs => ";
debug_g2_in_hex(msg, &lhs);
let rhs = (proof.C * c) + proof.T;
//msg = "(in verify proof) rhs => ";
//debug_g2_in_hex(msg, &rhs);
msg = "(in verify proof) rhs => ";
debug_g2_in_hex(msg, &rhs);
return lhs == rhs;
}

View File

@ -26,8 +26,7 @@ pub struct Commitment {
#[derive(Clone)]
pub struct CSParams {
pub_bases: Vec<G2>,
h: G2
pub pub_bases: Vec<G2>
}
impl fmt::Display for PublicKey {
@ -126,29 +125,35 @@ Implements the setup algorithm for the Pedersen92 commitment scheme over
a vector of messages.
*/
pub fn setup(len: usize, pub_bases: Option<Vec<G2>>) -> CSParams {
pub fn setup(len: usize, pub_bases: Vec<G2>, h: G2) -> CSParams {
let rng = &mut rand::thread_rng();
let h = G2::random(rng);
if pub_bases.is_none() {
let mut p: Vec<G2> = Vec::new();
for i in 0 .. len {
p.push(G2::random(rng));
}
return CSParams { pub_bases: p, h: h };
}
//let base_h = h.unwrap_or(G2::random(rng));
let mut p: Vec<G2> = Vec::new();
p.push(h);
let p = pub_bases.unwrap();
assert_eq!(p.len(), len);
return CSParams { pub_bases: p, h: h };
// if pub_bases.is_none() {
// for i in 1 .. len-1 {
// p.push(G2::random(rng));
// }
// return CSParams { pub_bases: p };
// }
let _p = pub_bases;
for i in 0 .. _p.len() {
p.push(_p[i]);
}
return CSParams { pub_bases: p };
}
pub fn commit(csp: &CSParams, x: &Vec<Fr>, R: Option<Fr>) -> Commitment {
pub fn commit(csp: &CSParams, x: &Vec<Fr>, r: Fr) -> Commitment {
let rng = &mut rand::thread_rng();
let r = R.unwrap_or(Fr::random(rng));
//let r = R.unwrap_or(Fr::random(rng));
// c = g1^m1 * ... * gn^mn * h^r
let mut c = (csp.h * r);
for i in 0 .. x.len() {
//println!("(commit) index: 0");
let mut c = (csp.pub_bases[0] * r);
for i in 1 .. x.len() {
//println!("(commit) index: {}", i);
c = c + (csp.pub_bases[i] * x[i]);
}
// return (c, r) <- r
@ -160,10 +165,12 @@ pub fn commit(csp: &CSParams, x: &Vec<Fr>, R: Option<Fr>) -> Commitment {
}
pub fn decommit(csp: &CSParams, cm: &Commitment, x: &Vec<Fr>) -> bool {
let mut dc = (csp.h * cm.r);
//let mut dc = (csp.h * cm.r);
let l = x.len();
assert!(csp.pub_bases.len() == l);
for i in 0 .. l {
//assert!(csp.pub_bases.len() == l);
// pub_base[0] => h, x[0] => r
let mut dc = csp.pub_bases[0] * cm.r;
for i in 1 .. l {
dc = dc + (csp.pub_bases[i] * x[i]);
}
return dc == cm.c;

View File

@ -780,9 +780,9 @@ pub mod bidirectional {
use secp256k1; // ::{Secp256k1, PublicKey, SecretKey};
pub struct PublicParams {
cm_csp: commit_scheme::CSParams,
// cm_csp: commit_scheme::CSParams,
cl_mpk: clsigs::PublicParams,
l_bits: i32
l: usize // messages for committment
// TODO: add NIZK proof system pub params
}
@ -791,14 +791,15 @@ pub mod bidirectional {
pk: clsigs::PublicKeyD
}
pub struct CustSecretKey {
pub struct CustomerWallet {
sk: clsigs::SecretKeyD, // the secret key for the signature scheme (Is it possible to make this a generic field?)
cid: Fr, // channel Id
wpk: secp256k1::PublicKey, // signature verification key
wsk: secp256k1::SecretKey, // signature signing key
r: Fr, // random coins for commitment scheme
balance: i32, // the balance for the user
ck_vec: Vec<sym::SymKey>
signature: Option<clsigs::SignatureD>
// ck_vec: Vec<sym::SymKey>
}
pub struct MerchSecretKey {
@ -807,32 +808,38 @@ pub mod bidirectional {
}
pub struct InitCustomerData {
T: ChannelToken,
csk: CustSecretKey
pub T: ChannelToken,
pub csk: CustomerWallet,
pub bases: Vec<G2>
}
pub struct InitMerchantData {
T: clsigs::PublicKeyD,
csk: MerchSecretKey
pub T: clsigs::PublicKeyD,
pub csk: MerchSecretKey
}
pub fn setup() -> PublicParams {
// TODO: provide option for generating CRS parameters
let cm_pp = commit_scheme::setup(3, None);
//let cm_pp = commit_scheme::setup(3, None);
let cl_mpk = clsigs::setupD();
let l = 256;
let l = 3;
// let nizk = "nizk proof system";
let pp = PublicParams { cm_csp: cm_pp, cl_mpk: cl_mpk, l_bits: l };
let pp = PublicParams { cl_mpk: cl_mpk, l: l }; // cm_csp: cm_pp,
return pp;
}
pub fn keygen(pp: &PublicParams) -> clsigs::KeyPairD {
// TODO: figure out what we need from public params to generate keys
println!("Run Keygen...");
let keypair = clsigs::keygenD(&pp.cl_mpk, 3);
let keypair = clsigs::keygenD(&pp.cl_mpk, pp.l);
return keypair;
}
pub fn generate_channel_id() -> Fr {
let rng = &mut rand::thread_rng();
return Fr::random(rng);
}
pub fn init_customer(pp: &PublicParams, channelId: Fr, b0_customer: i32, keypair: &clsigs::KeyPairD) -> InitCustomerData {
println!("Run Init customer...");
sym::init();
@ -853,24 +860,23 @@ pub mod bidirectional {
let r = Fr::random(rng);
//let msg = Message::new(keypair.sk, k1, k2, b0_customer).hash();
let mut ck_vec: Vec<sym::SymKey> = Vec::new();
// generate the vector ck of sym keys
for i in 1 .. b0_customer {
let ck = sym::keygen(l);
ck_vec.push(ck);
}
let b = keypair.pk.Z2.len();
let bases = keypair.pk.Z2.clone();
let cm_csp = commit_scheme::setup(pp.l, bases, pp.cl_mpk.g2);
let mut x: Vec<Fr> = Vec::new();
x.push(r); // set randomness for commitment
x.push(channelId);
x.push(h_wpk);
x.push(b0);
// TODO: hash (wpk) and convert b0_customer into Fr
let w_com = commit_scheme::commit(&pp.cm_csp, &x, Some(r));
let w_com = commit_scheme::commit(&cm_csp, &x, r);
let t_c = ChannelToken { w_com: w_com, pk: keypair.pk.clone() };
let csk_c = CustSecretKey { sk: keypair.sk.clone(), cid: channelId, wpk: wpk, wsk: wsk,
r: r, balance: b0_customer, ck_vec: ck_vec };
return InitCustomerData { T: t_c, csk: csk_c };
let csk_c = CustomerWallet { sk: keypair.sk.clone(), cid: channelId, wpk: wpk, wsk: wsk,
r: r, balance: b0_customer, signature: None };
return InitCustomerData { T: t_c, csk: csk_c, bases: cm_csp.pub_bases };
}
pub fn init_merchant(pp: &PublicParams, b0_merchant: i32, keypair: &clsigs::KeyPairD) -> InitMerchantData {
@ -879,45 +885,49 @@ pub mod bidirectional {
return InitMerchantData { T: keypair.pk.clone(), csk: csk_m };
}
// TODO: requires NIZK proof system
pub fn establish_customer(pp: &PublicParams, t_m: &clsigs::PublicKeyD, c_data: &InitCustomerData) -> clsigs::ProofCV {
pub fn establish_customer_phase1(pp: &PublicParams, c_data: &InitCustomerData) -> clsigs::ProofCV {
println ! ("Run establish_customer algorithm...");
// set sk_0 to random bytes of length l
// let sk_0 = random_bytes(pp.l);
let buf_len: usize = pp.l_bits as usize;
let mut sk0 = vec![0; buf_len];
randombytes::randombytes_into(&mut sk0);
// obtain customer init data
let t_c = &c_data.T;
let csk_c = &c_data.csk;
let pub_bases = &c_data.bases;
let h_wpk = hashPubKeyToFr(&csk_c.wpk);
let b0 = Fr::from_str(csk_c.balance.to_string().as_str()).unwrap();
// collect secrets
let mut x: Vec<Fr> = Vec::new();
x.push(t_c.w_com.r); // set randomness used to generate commitment
x.push(csk_c.cid);
x.push(h_wpk);
x.push(b0);
// collect bases
let mut pub_bases: Vec<G2> = Vec::new();
let proof_1 = clsigs::bs_gen_nizk_proof(&x, &pub_bases, t_c.w_com.c);
return proof_1;
}
// the merchant calls this method after obtaining
pub fn estalibsh_merchant(proof: &clsigs::ProofCV) {
pub fn establish_merchant_phase2(pp: &PublicParams, m_data: &InitMerchantData, proof: &clsigs::ProofCV) -> clsigs::SignatureD {
// verifies proof and produces
let wallet_sig = clsigs::bs_gen_signature(&pp.cl_mpk, &m_data.csk.sk, &proof);
return wallet_sig;
}
pub fn establish_customer_phase3(sig: clsigs::SignatureD, wallet: &mut CustomerWallet) -> bool {
if wallet.signature.is_none() {
wallet.signature = Some(sig);
return true;
}
return false;
}
// TODO: requires NIZK proof system calls
pub fn pay_by_customer() {
pub fn payment_by_customer_phase1(pp: &PublicParams, old_w: &CustomerWallet) {
println!("Run pay algorithm by Customer - phase 1.");
}
pub fn pay_by_merchant() {
println!("Run pay algorithm by Merchant - phase 1");
pub fn payment_by_merchant_phase2() {
println!("Run pay algorithm by Merchant - phase 2");
}
// pub fn refund(pp: &PublicParams, imd : &InitMerchantData, w: Wallet) {