#![allow(non_snake_case)] /// to run: /// 1: go to rocket_server -> cargo run /// 2: cargo run from PARTIES number of terminals use curv::{ arithmetic::traits::Converter, cryptographic_primitives::{ proofs::sigma_dlog::DLogProof, secret_sharing::feldman_vss::VerifiableSS, }, elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}, BigInt, }; use multi_party_ecdsa::protocols::multi_party_ecdsa::gg_2018::party_i::{ KeyGenBroadcastMessage1, KeyGenDecommitMessage1, Keys, Parameters, }; use paillier::EncryptionKey; use reqwest::Client; use sha2::Sha256; use std::{env, fs, time}; mod common; use common::{ aes_decrypt, aes_encrypt, broadcast, poll_for_broadcasts, poll_for_p2p, postb, sendp2p, Params, PartySignup, AEAD, AES_KEY_BYTES_LEN, }; fn main() { if env::args().nth(3).is_some() { panic!("too many arguments") } if env::args().nth(2).is_none() { panic!("too few arguments") } //read parameters: let data = fs::read_to_string("params.json") .expect("Unable to read params, make sure config file is present in the same folder "); let params: Params = serde_json::from_str(&data).unwrap(); let PARTIES: u16 = params.parties.parse::().unwrap(); let THRESHOLD: u16 = params.threshold.parse::().unwrap(); let client = Client::new(); // delay: let delay = time::Duration::from_millis(25); let params = Parameters { threshold: THRESHOLD, share_count: PARTIES, }; //signup: let (party_num_int, uuid) = match signup(&client).unwrap() { PartySignup { number, uuid } => (number, uuid), }; println!("number: {:?}, uuid: {:?}", party_num_int, uuid); let party_keys = Keys::create(party_num_int); let (bc_i, decom_i) = party_keys.phase1_broadcast_phase3_proof_of_correct_key(); // send commitment to ephemeral public keys, get round 1 commitments of other parties assert!(broadcast( &client, party_num_int, "round1", serde_json::to_string(&bc_i).unwrap(), uuid.clone() ) .is_ok()); let round1_ans_vec = poll_for_broadcasts( &client, party_num_int, PARTIES, delay, "round1", uuid.clone(), ); let mut bc1_vec = round1_ans_vec .iter() .map(|m| serde_json::from_str::(m).unwrap()) .collect::>(); bc1_vec.insert(party_num_int as usize - 1, bc_i); // send ephemeral public keys and check commitments correctness assert!(broadcast( &client, party_num_int, "round2", serde_json::to_string(&decom_i).unwrap(), uuid.clone() ) .is_ok()); let round2_ans_vec = poll_for_broadcasts( &client, party_num_int, PARTIES, delay, "round2", uuid.clone(), ); let mut j = 0; let mut point_vec: Vec> = Vec::new(); let mut decom_vec: Vec = Vec::new(); let mut enc_keys: Vec> = Vec::new(); for i in 1..=PARTIES { if i == party_num_int { point_vec.push(decom_i.y_i.clone()); decom_vec.push(decom_i.clone()); } else { let decom_j: KeyGenDecommitMessage1 = serde_json::from_str(&round2_ans_vec[j]).unwrap(); point_vec.push(decom_j.y_i.clone()); decom_vec.push(decom_j.clone()); let key_bn: BigInt = (decom_j.y_i.clone() * party_keys.u_i.clone()) .x_coord() .unwrap(); let key_bytes = BigInt::to_bytes(&key_bn); let mut template: Vec = vec![0u8; AES_KEY_BYTES_LEN - key_bytes.len()]; template.extend_from_slice(&key_bytes[..]); enc_keys.push(template); j += 1; } } let (head, tail) = point_vec.split_at(1); let y_sum = tail.iter().fold(head[0].clone(), |acc, x| acc + x); let (vss_scheme, secret_shares, _index) = party_keys .phase1_verify_com_phase3_verify_correct_key_phase2_distribute( ¶ms, &decom_vec, &bc1_vec, ) .expect("invalid key"); ////////////////////////////////////////////////////////////////////////////// let mut j = 0; for (k, i) in (1..=PARTIES).enumerate() { if i != party_num_int { // prepare encrypted ss for party i: let key_i = &enc_keys[j]; let plaintext = BigInt::to_bytes(&secret_shares[k].to_bigint()); let aead_pack_i = aes_encrypt(key_i, &plaintext); assert!(sendp2p( &client, party_num_int, i, "round3", serde_json::to_string(&aead_pack_i).unwrap(), uuid.clone() ) .is_ok()); j += 1; } } let round3_ans_vec = poll_for_p2p( &client, party_num_int, PARTIES, delay, "round3", uuid.clone(), ); let mut j = 0; let mut party_shares: Vec> = Vec::new(); for i in 1..=PARTIES { if i == party_num_int { party_shares.push(secret_shares[(i - 1) as usize].clone()); } else { let aead_pack: AEAD = serde_json::from_str(&round3_ans_vec[j]).unwrap(); let key_i = &enc_keys[j]; let out = aes_decrypt(key_i, aead_pack); let out_bn = BigInt::from_bytes(&out[..]); let out_fe = Scalar::::from(&out_bn); party_shares.push(out_fe); j += 1; } } // round 4: send vss commitments assert!(broadcast( &client, party_num_int, "round4", serde_json::to_string(&vss_scheme).unwrap(), uuid.clone() ) .is_ok()); let round4_ans_vec = poll_for_broadcasts( &client, party_num_int, PARTIES, delay, "round4", uuid.clone(), ); let mut j = 0; let mut vss_scheme_vec: Vec> = Vec::new(); for i in 1..=PARTIES { if i == party_num_int { vss_scheme_vec.push(vss_scheme.clone()); } else { let vss_scheme_j: VerifiableSS = serde_json::from_str(&round4_ans_vec[j]).unwrap(); vss_scheme_vec.push(vss_scheme_j); j += 1; } } let (shared_keys, dlog_proof) = party_keys .phase2_verify_vss_construct_keypair_phase3_pok_dlog( ¶ms, &point_vec, &party_shares, &vss_scheme_vec, party_num_int, ) .expect("invalid vss"); // round 5: send dlog proof assert!(broadcast( &client, party_num_int, "round5", serde_json::to_string(&dlog_proof).unwrap(), uuid.clone() ) .is_ok()); let round5_ans_vec = poll_for_broadcasts(&client, party_num_int, PARTIES, delay, "round5", uuid); let mut j = 0; let mut dlog_proof_vec: Vec> = Vec::new(); for i in 1..=PARTIES { if i == party_num_int { dlog_proof_vec.push(dlog_proof.clone()); } else { let dlog_proof_j: DLogProof = serde_json::from_str(&round5_ans_vec[j]).unwrap(); dlog_proof_vec.push(dlog_proof_j); j += 1; } } Keys::verify_dlog_proofs(¶ms, &dlog_proof_vec, &point_vec).expect("bad dlog proof"); //save key to file: let paillier_key_vec = (0..PARTIES) .map(|i| bc1_vec[i as usize].e.clone()) .collect::>(); let keygen_json = serde_json::to_string(&( party_keys, shared_keys, party_num_int, vss_scheme_vec, paillier_key_vec, y_sum, )) .unwrap(); fs::write(env::args().nth(2).unwrap(), keygen_json).expect("Unable to save !"); } pub fn signup(client: &Client) -> Result { let key = "signup-keygen".to_string(); let res_body = postb(client, "signupkeygen", key).unwrap(); serde_json::from_str(&res_body).unwrap() }