diff --git a/.travis.yml b/.travis.yml index 81222c08..bacdf3aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,21 @@ language: rust cache: cargo -rust: - - nightly +rust: nightly +virt: lxd + +before_install: + - rustup component add rustfmt clippy script: - - cargo build --verbose + - cargo build --benches --verbose - cargo test --verbose + - cargo fmt --all -- --check + - cargo clippy -- -D clippy::all + +deploy: + provider: cargo + token: + secure: "QChykAD/vntzVNHePGuCHRNyLJwiqRAqIYw1uCqWVaca5IYMuItv2Qs6hShWt8AVQ631ZC5O5mnYTsPyxO3ZLZAPM/UEtmJiR9zf7v9DJyPPyyaT9kw+YrELVwit/xab2uJzJIZ1mBHSx0An/67gfdTITLjQmW2UVPhu3pdUz3rSrYBxp2quD7OgMfHeXXP8yk2xtZIXQ2mcNuNPnEkCk/siGTyS1Py/cpEFBsGfHSMPLyZq9Mn/PFPttPtebZiWUPvfDHFqbTd73SB2DmJrrdJ/rpeiHKNuPJUbc8qA1yDQjLATUNmDXjg+q8gcPIraj+zifeR6M+TIG0tLPU1NKVI1Oxta1CUurV+m5qY9YmFxtNyTNquOI4ehbckXADgZhIOLDD9/rfYETXdkxXwYh0WozNOp+yqZj+wGqFfxB3+DfMRKk/ooYQqCYJ2Pun+SzTSnv2REa0Sa70a67hADMV6h6qfumEq3XxgKouNHd3gg+b1urB6JKfL8RI9SrOwKgkU/mBl+qCzP+UwAUPqnzp/r9GONm86gsUZXuhwDJmru30B9YLOrzwnKdGjZEBWDV6OuT5p9e1R+rot069qeTqMOiu8ZAAulttBAEpFoG99vTW1elE3aSBasVa9/YS0M1kY4n4Yz8GTP8w8p9WXM6hX6MU8iR//hPsNHQiNwJws=" + on: + tags: true + condition: '"$TRAVIS_TAG" =~ ^v[0-9].+$' diff --git a/Cargo.toml b/Cargo.toml index b9d2c04b..9fc9dc5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-party-ecdsa" -version = "0.7.4" +version = "0.8.0" edition = "2018" authors = [ "Gary ", @@ -26,7 +26,7 @@ categories = ["cryptography"] crate-type = ["lib"] [features] -default = ["curv/rust-gmp-kzen"] +default = ["curv-kzen/rust-gmp-kzen"] cclst = ["class_group"] [dependencies] @@ -34,29 +34,22 @@ subtle = { version = "2" } serde = { version = "1.0", features = ["derive"] } zeroize = "1" libsecp256k1 = "0.3.2" -curv = { package = "curv-kzen", version = "0.7", default-features = false } +curv-kzen = { version = "0.9", default-features = false } +centipede = { version = "0.3", default-features = false } +zk-paillier = { version = "0.4.2", default-features = false } round-based = { version = "0.1.4", features = [] } thiserror = "1.0.23" derivative = "2" - -[dependencies.centipede] -git = "https://github.com/KZen-networks/centipede" -tag = "v0.2.12" -default-features = false +sha2 = "0.9" [dependencies.paillier] -git = "https://github.com/KZen-networks/rust-paillier" -tag = "v0.3.10" -default-features = false - -[dependencies.zk-paillier] -git = "https://github.com/KZen-networks/zk-paillier" -tag = "v0.3.12" +version = "0.4.2" +package = "kzen-paillier" default-features = false [dependencies.class_group] -git = "https://github.com/KZen-networks/class" -tag = "v0.5.2" +version = "0.6" +default-features = false optional = true [dev-dependencies] @@ -73,9 +66,6 @@ rand = "0.7" thiserror = "1.0.23" round-based = { version = "0.1.4", features = ["dev"] } -[patch.crates-io] -rust-gmp = { version = "0.5.0", features = ["serde_support"], git = "https://github.com/KZen-networks/rust-gmp" } - [[example]] name = "sm_manager" diff --git a/benches/multi_party_ecdsa/gg18/keygen.rs b/benches/multi_party_ecdsa/gg18/keygen.rs index f24dd37c..5c4b0c7a 100644 --- a/benches/multi_party_ecdsa/gg18/keygen.rs +++ b/benches/multi_party_ecdsa/gg18/keygen.rs @@ -3,8 +3,7 @@ use criterion::criterion_main; mod bench { use criterion::{criterion_group, Criterion}; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; - use curv::elliptic::curves::secp256_k1::{FE, GE}; - use curv::elliptic::curves::traits::*; + use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use multi_party_ecdsa::protocols::multi_party_ecdsa::gg_2018::party_i::*; pub fn bench_full_keygen_party_one_two(c: &mut Criterion) { c.bench_function("keygen t=1 n=2", move |b| { @@ -23,13 +22,21 @@ mod bench { pub fn keygen_t_n_parties( t: u16, n: u16, - ) -> (Vec, Vec, Vec, GE, VerifiableSS) { + ) -> ( + Vec, + Vec, + Vec>, + Point, + VerifiableSS, + ) { let parames = Parameters { threshold: t, share_count: n, }; let (t, n) = (t as usize, n as usize); - let party_keys_vec = (0..n).map(Keys::create).collect::>(); + let party_keys_vec = (0..n) + .map(|i| Keys::create(i as u16)) + .collect::>(); let mut bc1_vec = Vec::new(); let mut decom_vec = Vec::new(); @@ -40,7 +47,9 @@ mod bench { decom_vec.push(decom1); } - let y_vec = (0..n).map(|i| decom_vec[i].y_i).collect::>(); + let y_vec = (0..n) + .map(|i| decom_vec[i].y_i.clone()) + .collect::>>(); let mut y_vec_iter = y_vec.iter(); let head = y_vec_iter.next().unwrap(); let tail = y_vec_iter; @@ -56,7 +65,7 @@ mod bench { .expect("invalid key"); vss_scheme_vec.push(vss_scheme); secret_shares_vec.push(secret_shares); - index_vec.push(index); + index_vec.push(index as u16); } let vss_scheme_for_test = vss_scheme_vec.clone(); @@ -65,11 +74,11 @@ mod bench { (0..n) .map(|j| { let vec_j = &secret_shares_vec[j]; - vec_j[i] + vec_j[i].clone() }) - .collect::>() + .collect::>>() }) - .collect::>>(); + .collect::>>>(); let mut shared_keys_vec = Vec::new(); let mut dlog_proof_vec = Vec::new(); @@ -80,24 +89,30 @@ mod bench { &y_vec, &party_shares[i], &vss_scheme_vec, - &index_vec[i] + 1, + (&index_vec[i] + 1).into(), ) .expect("invalid vss"); shared_keys_vec.push(shared_keys); dlog_proof_vec.push(dlog_proof); } - let pk_vec = (0..n).map(|i| dlog_proof_vec[i].pk).collect::>(); + let pk_vec = (0..n) + .map(|i| dlog_proof_vec[i].pk.clone()) + .collect::>>(); //both parties run: Keys::verify_dlog_proofs(¶mes, &dlog_proof_vec, &y_vec).expect("bad dlog proof"); //test - let xi_vec = (0..=t).map(|i| shared_keys_vec[i].x_i).collect::>(); + let xi_vec = (0..=t) + .map(|i| shared_keys_vec[i].x_i.clone()) + .collect::>>(); let x = vss_scheme_for_test[0] .clone() .reconstruct(&index_vec[0..=t], &xi_vec); - let sum_u_i = party_keys_vec.iter().fold(FE::zero(), |acc, x| acc + x.u_i); + let sum_u_i = party_keys_vec + .iter() + .fold(Scalar::::zero(), |acc, x| acc + &x.u_i); assert_eq!(x, sum_u_i); ( diff --git a/benches/two_party_ecdsa/cclst_2019/keygen.rs b/benches/two_party_ecdsa/cclst_2019/keygen.rs index dc9a1735..35c89c41 100644 --- a/benches/two_party_ecdsa/cclst_2019/keygen.rs +++ b/benches/two_party_ecdsa/cclst_2019/keygen.rs @@ -13,10 +13,10 @@ mod bench { let (party_one_first_message, comm_witness, ec_key_pair_party1) = party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share( - ECScalar::new_random(), + Scalar::::random(), ); let (party_two_first_message, _ec_key_pair_party2) = - party_two::KeyGenFirstMsg::create_with_fixed_secret_share(ECScalar::from(&BigInt::from( + party_two::KeyGenFirstMsg::create_with_fixed_secret_share(Scalar::::from(&BigInt::from( 10, ))); let party_one_second_message = party_one::KeyGenSecondMsg::verify_and_decommit( diff --git a/benches/two_party_ecdsa/lindell_2017/keygen.rs b/benches/two_party_ecdsa/lindell_2017/keygen.rs index ec42e48a..412ff75c 100644 --- a/benches/two_party_ecdsa/lindell_2017/keygen.rs +++ b/benches/two_party_ecdsa/lindell_2017/keygen.rs @@ -3,7 +3,7 @@ use criterion::criterion_main; mod bench { use criterion::{criterion_group, Criterion}; use curv::arithmetic::traits::Samplable; - use curv::elliptic::curves::traits::*; + use curv::elliptic::curves::{secp256_k1::Secp256k1, Scalar}; use curv::BigInt; use multi_party_ecdsa::protocols::two_party_ecdsa::lindell_2017::*; @@ -12,12 +12,12 @@ mod bench { b.iter(|| { let (party_one_first_message, comm_witness, ec_key_pair_party1) = party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share( - ECScalar::from(&BigInt::sample(253)), + Scalar::::from(&BigInt::sample(253)), ); let (party_two_first_message, _ec_key_pair_party2) = - party_two::KeyGenFirstMsg::create_with_fixed_secret_share(ECScalar::from( - &BigInt::from(10), - )); + party_two::KeyGenFirstMsg::create_with_fixed_secret_share( + Scalar::::from(&BigInt::from(10)), + ); let party_one_second_message = party_one::KeyGenSecondMsg::verify_and_decommit( comm_witness, &party_two_first_message.d_log_proof, diff --git a/examples/common.rs b/examples/common.rs index 45ecad38..ae414562 100644 --- a/examples/common.rs +++ b/examples/common.rs @@ -7,8 +7,7 @@ use crypto::{ }; use curv::{ arithmetic::traits::Converter, - elliptic::curves::secp256_k1::{FE, GE}, - elliptic::curves::traits::{ECPoint, ECScalar}, + elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}, BigInt, }; use reqwest::Client; @@ -55,7 +54,7 @@ pub fn aes_encrypt(key: &[u8], plaintext: &[u8]) -> AEAD { let mut gcm = AesGcm::new(KeySize256, key, &nonce[..], &aad); let mut out: Vec = repeat(0).take(plaintext.len()).collect(); let mut out_tag: Vec = repeat(0).take(16).collect(); - gcm.encrypt(&plaintext[..], &mut out[..], &mut out_tag[..]); + gcm.encrypt(plaintext, &mut out[..], &mut out_tag[..]); AEAD { ciphertext: out.to_vec(), tag: out_tag.to_vec(), @@ -103,12 +102,9 @@ pub fn broadcast( sender_uuid: String, ) -> Result<(), ()> { let key = format!("{}-{}-{}", party_num, round, sender_uuid); - let entry = Entry { - key: key.clone(), - value: data, - }; + let entry = Entry { key, value: data }; - let res_body = postb(&client, "set", entry).unwrap(); + let res_body = postb(client, "set", entry).unwrap(); serde_json::from_str(&res_body).unwrap() } @@ -122,12 +118,9 @@ pub fn sendp2p( ) -> Result<(), ()> { let key = format!("{}-{}-{}-{}", party_from, party_to, round, sender_uuid); - let entry = Entry { - key: key.clone(), - value: data, - }; + let entry = Entry { key, value: data }; - let res_body = postb(&client, "set", entry).unwrap(); + let res_body = postb(client, "set", entry).unwrap(); serde_json::from_str(&res_body).unwrap() } @@ -190,27 +183,32 @@ pub fn poll_for_p2p( } #[allow(dead_code)] -pub fn check_sig(r: &FE, s: &FE, msg: &BigInt, pk: &GE) { +pub fn check_sig( + r: &Scalar, + s: &Scalar, + msg: &BigInt, + pk: &Point, +) { use secp256k1::{verify, Message, PublicKey, PublicKeyFormat, Signature}; - let raw_msg = BigInt::to_bytes(&msg); + let raw_msg = BigInt::to_bytes(msg); let mut msg: Vec = Vec::new(); // padding msg.extend(vec![0u8; 32 - raw_msg.len()]); msg.extend(raw_msg.iter()); let msg = Message::parse_slice(msg.as_slice()).unwrap(); - let mut raw_pk = pk.pk_to_key_slice(); + let mut raw_pk = pk.to_bytes(false).to_vec(); if raw_pk.len() == 64 { raw_pk.insert(0, 4u8); } let pk = PublicKey::parse_slice(&raw_pk, Some(PublicKeyFormat::Full)).unwrap(); let mut compact: Vec = Vec::new(); - let bytes_r = &r.get_element()[..]; + let bytes_r = &r.to_bytes().to_vec(); compact.extend(vec![0u8; 32 - bytes_r.len()]); compact.extend(bytes_r.iter()); - let bytes_s = &s.get_element()[..]; + let bytes_s = &s.to_bytes().to_vec(); compact.extend(vec![0u8; 32 - bytes_s.len()]); compact.extend(bytes_s.iter()); diff --git a/examples/gg18_keygen_client.rs b/examples/gg18_keygen_client.rs index 4f082723..bc5b8f0b 100644 --- a/examples/gg18_keygen_client.rs +++ b/examples/gg18_keygen_client.rs @@ -7,8 +7,7 @@ use curv::{ cryptographic_primitives::{ proofs::sigma_dlog::DLogProof, secret_sharing::feldman_vss::VerifiableSS, }, - elliptic::curves::secp256_k1::{FE, GE}, - elliptic::curves::traits::{ECPoint, ECScalar}, + elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}, BigInt, }; use multi_party_ecdsa::protocols::multi_party_ecdsa::gg_2018::party_i::{ @@ -16,6 +15,7 @@ use multi_party_ecdsa::protocols::multi_party_ecdsa::gg_2018::party_i::{ }; use paillier::EncryptionKey; use reqwest::Client; +use sha2::Sha256; use std::{env, fs, time}; mod common; @@ -53,7 +53,7 @@ fn main() { }; println!("number: {:?}, uuid: {:?}", party_num_int, uuid); - let party_keys = Keys::create(party_num_int as usize); + 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 @@ -100,28 +100,30 @@ fn main() { ); let mut j = 0; - let mut point_vec: Vec = Vec::new(); + 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); + 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); + 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).x_coor().unwrap(); + 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 = j + 1; + j += 1; } } let (head, tail) = point_vec.split_at(1); - let y_sum = tail.iter().fold(head[0], |acc, x| acc + x); + 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( @@ -136,7 +138,7 @@ fn main() { 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_big_int()); + let plaintext = BigInt::to_bytes(&secret_shares[k].to_bigint()); let aead_pack_i = aes_encrypt(key_i, &plaintext); assert!(sendp2p( &client, @@ -161,16 +163,16 @@ fn main() { ); let mut j = 0; - let mut party_shares: Vec = Vec::new(); + 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]); + 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 = ECScalar::from(&out_bn); + let out_fe = Scalar::::from(&out_bn); party_shares.push(out_fe); j += 1; @@ -196,12 +198,13 @@ fn main() { ); let mut j = 0; - let mut vss_scheme_vec: Vec> = Vec::new(); + 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(); + let vss_scheme_j: VerifiableSS = + serde_json::from_str(&round4_ans_vec[j]).unwrap(); vss_scheme_vec.push(vss_scheme_j); j += 1; } @@ -213,7 +216,7 @@ fn main() { &point_vec, &party_shares, &vss_scheme_vec, - party_num_int as usize, + party_num_int, ) .expect("invalid vss"); @@ -226,22 +229,17 @@ fn main() { uuid.clone() ) .is_ok()); - let round5_ans_vec = poll_for_broadcasts( - &client, - party_num_int, - PARTIES, - delay, - "round5", - uuid.clone(), - ); + 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(); + 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(); + let dlog_proof_j: DLogProof = + serde_json::from_str(&round5_ans_vec[j]).unwrap(); dlog_proof_vec.push(dlog_proof_j); j += 1; } @@ -268,6 +266,6 @@ fn main() { pub fn signup(client: &Client) -> Result { let key = "signup-keygen".to_string(); - let res_body = postb(&client, "signupkeygen", key).unwrap(); + let res_body = postb(client, "signupkeygen", key).unwrap(); serde_json::from_str(&res_body).unwrap() } diff --git a/examples/gg18_sign_client.rs b/examples/gg18_sign_client.rs index fdf1d26f..86e7ed2a 100644 --- a/examples/gg18_sign_client.rs +++ b/examples/gg18_sign_client.rs @@ -6,8 +6,7 @@ use curv::{ proofs::sigma_correct_homomorphic_elgamal_enc::HomoELGamalProof, proofs::sigma_dlog::DLogProof, secret_sharing::feldman_vss::VerifiableSS, }, - elliptic::curves::secp256_k1::{FE, GE}, - elliptic::curves::traits::ECScalar, + elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}, BigInt, }; use multi_party_ecdsa::protocols::multi_party_ecdsa::gg_2018::party_i::{ @@ -15,6 +14,7 @@ use multi_party_ecdsa::protocols::multi_party_ecdsa::gg_2018::party_i::{ SharedKeys, SignBroadcastPhase1, SignDecommitPhase1, SignKeys, }; use multi_party_ecdsa::utilities::mta::*; +use sha2::Sha256; use paillier::EncryptionKey; use reqwest::Client; @@ -49,9 +49,9 @@ fn main() { Keys, SharedKeys, u16, - Vec>, + Vec>, Vec, - GE, + Point, ) = serde_json::from_str(&data).unwrap(); //read parameters: @@ -85,13 +85,13 @@ fn main() { ); let mut j = 0; - let mut signers_vec: Vec = Vec::new(); + let mut signers_vec: Vec = Vec::new(); for i in 1..=THRESHOLD + 1 { if i == party_num_int { - signers_vec.push((party_id - 1) as usize); + signers_vec.push(party_id - 1); } else { let signer_j: u16 = serde_json::from_str(&round0_ans_vec[j]).unwrap(); - signers_vec.push((signer_j - 1) as usize); + signers_vec.push(signer_j - 1); j += 1; } } @@ -100,8 +100,8 @@ fn main() { let sign_keys = SignKeys::create( &private, - &vss_scheme_vec[signers_vec[(party_num_int - 1) as usize]], - signers_vec[(party_num_int - 1) as usize], + &vss_scheme_vec[usize::from(signers_vec[usize::from(party_num_int - 1)])], + signers_vec[usize::from(party_num_int - 1)], &signers_vec, ); @@ -113,7 +113,7 @@ fn main() { &client, party_num_int, "round1", - serde_json::to_string(&(com.clone(), m_a_k.clone())).unwrap(), + serde_json::to_string(&(com.clone(), m_a_k)).unwrap(), uuid.clone() ) .is_ok()); @@ -149,22 +149,22 @@ fn main() { ////////////////////////////////////////////////////////////////////////////// let mut m_b_gamma_send_vec: Vec = Vec::new(); - let mut beta_vec: Vec = Vec::new(); + let mut beta_vec: Vec> = Vec::new(); let mut m_b_w_send_vec: Vec = Vec::new(); - let mut ni_vec: Vec = Vec::new(); + let mut ni_vec: Vec> = Vec::new(); let mut j = 0; for i in 1..THRESHOLD + 2 { if i != party_num_int { let (m_b_gamma, beta_gamma, _, _) = MessageB::b( &sign_keys.gamma_i, - &paillier_key_vector[signers_vec[(i - 1) as usize]], + &paillier_key_vector[usize::from(signers_vec[usize::from(i - 1)])], m_a_vec[j].clone(), &[], ) .unwrap(); let (m_b_w, beta_wi, _, _) = MessageB::b( &sign_keys.w_i, - &paillier_key_vector[signers_vec[(i - 1) as usize]], + &paillier_key_vector[usize::from(signers_vec[usize::from(i - 1)])], m_a_vec[j].clone(), &[], ) @@ -215,8 +215,8 @@ fn main() { // } } - let mut alpha_vec: Vec = Vec::new(); - let mut miu_vec: Vec = Vec::new(); + let mut alpha_vec: Vec> = Vec::new(); + let mut miu_vec: Vec> = Vec::new(); let mut j = 0; for i in 1..THRESHOLD + 2 { @@ -233,9 +233,9 @@ fn main() { alpha_vec.push(alpha_ij_gamma.0); miu_vec.push(alpha_ij_wi.0); let g_w_i = Keys::update_commitments_to_xi( - &xi_com_vec[signers_vec[(i - 1) as usize]], - &vss_scheme_vec[signers_vec[(i - 1) as usize]], - signers_vec[(i - 1) as usize], + &xi_com_vec[usize::from(signers_vec[usize::from(i - 1)])], + &vss_scheme_vec[usize::from(signers_vec[usize::from(i - 1)])], + signers_vec[usize::from(i - 1)], &signers_vec, ); assert_eq!(m_b.b_proof.pk, g_w_i); @@ -262,7 +262,7 @@ fn main() { "round3", uuid.clone(), ); - let mut delta_vec: Vec = Vec::new(); + let mut delta_vec: Vec> = Vec::new(); format_vec_from_reads( &round3_ans_vec, party_num_int as usize, @@ -297,11 +297,11 @@ fn main() { decommit, &mut decommit_vec, ); - let decomm_i = decommit_vec.remove((party_num_int - 1) as usize); - bc1_vec.remove((party_num_int - 1) as usize); + let decomm_i = decommit_vec.remove(usize::from(party_num_int - 1)); + bc1_vec.remove(usize::from(party_num_int - 1)); let b_proof_vec = (0..m_b_gamma_rec_vec.len()) .map(|i| &m_b_gamma_rec_vec[i].b_proof) - .collect::>>(); + .collect::>>(); let R = SignKeys::phase4(&delta_inv, &b_proof_vec, decommit_vec, &bc1_vec) .expect("bad gamma_i decommit"); @@ -367,32 +367,28 @@ fn main() { let mut decommit5a_and_elgamal_and_dlog_vec: Vec<( Phase5ADecom1, - HomoELGamalProof, - DLogProof, + HomoELGamalProof, + DLogProof, )> = Vec::new(); format_vec_from_reads( &round6_ans_vec, party_num_int as usize, - ( - phase_5a_decom.clone(), - helgamal_proof.clone(), - dlog_proof_rho.clone(), - ), + (phase_5a_decom.clone(), helgamal_proof, dlog_proof_rho), &mut decommit5a_and_elgamal_and_dlog_vec, ); let decommit5a_and_elgamal_and_dlog_vec_includes_i = decommit5a_and_elgamal_and_dlog_vec.clone(); - decommit5a_and_elgamal_and_dlog_vec.remove((party_num_int - 1) as usize); - commit5a_vec.remove((party_num_int - 1) as usize); + decommit5a_and_elgamal_and_dlog_vec.remove(usize::from(party_num_int - 1)); + commit5a_vec.remove(usize::from(party_num_int - 1)); let phase_5a_decomm_vec = (0..THRESHOLD) .map(|i| decommit5a_and_elgamal_and_dlog_vec[i as usize].0.clone()) .collect::>(); let phase_5a_elgamal_vec = (0..THRESHOLD) .map(|i| decommit5a_and_elgamal_and_dlog_vec[i as usize].1.clone()) - .collect::>>(); + .collect::>>(); let phase_5a_dlog_vec = (0..THRESHOLD) .map(|i| decommit5a_and_elgamal_and_dlog_vec[i as usize].2.clone()) - .collect::>>(); + .collect::>>(); let (phase5_com2, phase_5d_decom2) = local_sig .phase5c( &phase_5a_decomm_vec, @@ -452,7 +448,7 @@ fn main() { format_vec_from_reads( &round8_ans_vec, party_num_int as usize, - phase_5d_decom2.clone(), + phase_5d_decom2, &mut decommit5d_vec, ); @@ -480,32 +476,26 @@ fn main() { uuid.clone() ) .is_ok()); - let round9_ans_vec = poll_for_broadcasts( - &client, - party_num_int, - THRESHOLD + 1, - delay, - "round9", - uuid.clone(), - ); + let round9_ans_vec = + poll_for_broadcasts(&client, party_num_int, THRESHOLD + 1, delay, "round9", uuid); - let mut s_i_vec: Vec = Vec::new(); + let mut s_i_vec: Vec> = Vec::new(); format_vec_from_reads(&round9_ans_vec, party_num_int as usize, s_i, &mut s_i_vec); - s_i_vec.remove((party_num_int - 1) as usize); + s_i_vec.remove(usize::from(party_num_int - 1)); let sig = local_sig .output_signature(&s_i_vec) .expect("verification failed"); println!("party {:?} Output Signature: \n", party_num_int); - println!("R: {:?}", sig.r.get_element()); - println!("s: {:?} \n", sig.s.get_element()); + println!("R: {:?}", sig.r); + println!("s: {:?} \n", sig.s); println!("recid: {:?} \n", sig.recid.clone()); let sign_json = serde_json::to_string(&( "r", - (BigInt::from_bytes(&(sig.r.get_element())[..])).to_str_radix(16), + BigInt::from_bytes(sig.r.to_bytes().as_ref()).to_str_radix(16), "s", - (BigInt::from_bytes(&(sig.s.get_element())[..])).to_str_radix(16), + BigInt::from_bytes(sig.s.to_bytes().as_ref()).to_str_radix(16), )) .unwrap(); @@ -536,6 +526,6 @@ fn format_vec_from_reads<'a, T: serde::Deserialize<'a> + Clone>( pub fn signup(client: &Client) -> Result { let key = "signup-sign".to_string(); - let res_body = postb(&client, "signupsign", key).unwrap(); + let res_body = postb(client, "signupsign", key).unwrap(); serde_json::from_str(&res_body).unwrap() } diff --git a/examples/sm_manager.rs b/examples/sm_manager.rs index f023d5b0..409c3c42 100644 --- a/examples/sm_manager.rs +++ b/examples/sm_manager.rs @@ -22,7 +22,7 @@ fn get( Some(v) => { let entry = Entry { key: index.key, - value: v.clone().to_string(), + value: v.clone(), }; Json(Ok(entry)) } @@ -34,7 +34,7 @@ fn get( fn set(db_mtx: State>>, request: Json) -> Json> { let entry: Entry = request.0; let mut hm = db_mtx.write().unwrap(); - hm.insert(entry.key.clone(), entry.value.clone()); + hm.insert(entry.key.clone(), entry.value); Json(Ok(())) } @@ -50,7 +50,7 @@ fn signup_keygen(db_mtx: State>>) -> Json>>) -> Json */ +#![allow(clippy::many_single_char_names)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] + pub mod protocols; pub mod utilities; #[derive(Copy, PartialEq, Eq, Clone, Debug)] diff --git a/src/protocols/multi_party_ecdsa/gg_2018/party_i.rs b/src/protocols/multi_party_ecdsa/gg_2018/party_i.rs index cc2755d9..7899f311 100644 --- a/src/protocols/multi_party_ecdsa/gg_2018/party_i.rs +++ b/src/protocols/multi_party_ecdsa/gg_2018/party_i.rs @@ -15,25 +15,27 @@ @license GPL-3.0+ */ + +use std::convert::TryFrom; + use centipede::juggling::proof_system::{Helgamalsegmented, Witness}; use centipede::juggling::segmentation::Msegmentation; use curv::arithmetic::traits::*; use curv::cryptographic_primitives::commitments::hash_commitment::HashCommitment; use curv::cryptographic_primitives::commitments::traits::Commitment; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_correct_homomorphic_elgamal_enc::*; use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{Curve, Point, Scalar, Secp256k1}; use curv::BigInt; - use paillier::{ Decrypt, DecryptionKey, EncryptionKey, KeyGeneration, Paillier, RawCiphertext, RawPlaintext, }; +use sha2::Sha256; +use zk_paillier::zkproofs::NiCorrectKeyProof; + use serde::{Deserialize, Serialize}; -use zk_paillier::zkproofs::NICorrectKeyProof; use crate::Error::{self, InvalidCom, InvalidKey, InvalidSS, InvalidSig}; @@ -46,18 +48,18 @@ pub struct Parameters { } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Keys { - pub u_i: FE, - pub y_i: GE, +pub struct Keys { + pub u_i: Scalar, + pub y_i: Point, pub dk: DecryptionKey, pub ek: EncryptionKey, - pub party_index: usize, + pub party_index: u16, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PartyPrivate { - u_i: FE, - x_i: FE, + u_i: Scalar, + x_i: Scalar, dk: DecryptionKey, } @@ -65,28 +67,28 @@ pub struct PartyPrivate { pub struct KeyGenBroadcastMessage1 { pub e: EncryptionKey, pub com: BigInt, - pub correct_key_proof: NICorrectKeyProof, + pub correct_key_proof: NiCorrectKeyProof, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyGenDecommitMessage1 { pub blind_factor: BigInt, - pub y_i: GE, + pub y_i: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SharedKeys { - pub y: GE, - pub x_i: FE, + pub y: Point, + pub x_i: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SignKeys { - pub w_i: FE, - pub g_w_i: GE, - pub k_i: FE, - pub gamma_i: FE, - pub g_gamma_i: GE, + pub w_i: Scalar, + pub g_w_i: Point, + pub k_i: Scalar, + pub gamma_i: Scalar, + pub g_gamma_i: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -97,17 +99,17 @@ pub struct SignBroadcastPhase1 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SignDecommitPhase1 { pub blind_factor: BigInt, - pub g_gamma_i: GE, + pub g_gamma_i: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LocalSignature { - pub l_i: FE, - pub rho_i: FE, - pub R: GE, - pub s_i: FE, + pub l_i: Scalar, + pub rho_i: Scalar, + pub R: Point, + pub s_i: Scalar, pub m: BigInt, - pub y: GE, + pub y: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -122,30 +124,30 @@ pub struct Phase5Com2 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Phase5ADecom1 { - pub V_i: GE, - pub A_i: GE, - pub B_i: GE, + pub V_i: Point, + pub A_i: Point, + pub B_i: Point, pub blind_factor: BigInt, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Phase5DDecom2 { - pub u_i: GE, - pub t_i: GE, + pub u_i: Point, + pub t_i: Point, pub blind_factor: BigInt, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SignatureRecid { - pub r: FE, - pub s: FE, + pub r: Scalar, + pub s: Scalar, pub recid: u8, } impl Keys { - pub fn create(index: usize) -> Self { - let u = FE::new_random(); - let y = GE::generator() * u; + pub fn create(index: u16) -> Self { + let u = Scalar::::random(); + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair().keys(); Self { @@ -158,9 +160,9 @@ impl Keys { } // we recommend using safe primes if the code is used in production - pub fn create_safe_prime(index: usize) -> Keys { - let u: FE = ECScalar::new_random(); - let y = &ECPoint::generator() * &u; + pub fn create_safe_prime(index: u16) -> Keys { + let u = Scalar::::random(); + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair_safe_primes().keys(); @@ -169,11 +171,11 @@ impl Keys { y_i: y, dk, ek, - party_index: index.clone(), + party_index: index, } } - pub fn create_from(u: FE, index: usize) -> Keys { - let y = &ECPoint::generator() * &u; + pub fn create_from(u: Scalar, index: u16) -> Keys { + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair().keys(); Self { @@ -189,9 +191,9 @@ impl Keys { &self, ) -> (KeyGenBroadcastMessage1, KeyGenDecommitMessage1) { let blind_factor = BigInt::sample(SECURITY); - let correct_key_proof = NICorrectKeyProof::proof(&self.dk, None); - let com = HashCommitment::create_commitment_with_user_defined_randomness( - &self.y_i.bytes_compressed_to_big_int(), + let correct_key_proof = NiCorrectKeyProof::proof(&self.dk, None); + let com = HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(self.y_i.to_bytes(true).as_ref()), &blind_factor, ); let bcm1 = KeyGenBroadcastMessage1 { @@ -201,41 +203,37 @@ impl Keys { }; let decom1 = KeyGenDecommitMessage1 { blind_factor, - y_i: self.y_i, + y_i: self.y_i.clone(), }; (bcm1, decom1) } + #[allow(clippy::type_complexity)] pub fn phase1_verify_com_phase3_verify_correct_key_phase2_distribute( &self, params: &Parameters, decom_vec: &[KeyGenDecommitMessage1], bc1_vec: &[KeyGenBroadcastMessage1], - ) -> Result<(VerifiableSS, Vec, usize), Error> { + ) -> Result<(VerifiableSS, Vec>, u16), Error> { // test length: - assert_eq!(decom_vec.len() as u16, params.share_count); - assert_eq!(bc1_vec.len() as u16, params.share_count); + assert_eq!(decom_vec.len(), usize::from(params.share_count)); + assert_eq!(bc1_vec.len(), usize::from(params.share_count)); // test paillier correct key and test decommitments - let correct_key_correct_decom_all = (0..bc1_vec.len()) - .map(|i| { - HashCommitment::create_commitment_with_user_defined_randomness( - &decom_vec[i].y_i.bytes_compressed_to_big_int(), - &decom_vec[i].blind_factor, - ) == bc1_vec[i].com - && bc1_vec[i] - .correct_key_proof - .verify(&bc1_vec[i].e, zk_paillier::zkproofs::SALT_STRING) - .is_ok() - }) - .all(|x| x); + let correct_key_correct_decom_all = (0..bc1_vec.len()).all(|i| { + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(decom_vec[i].y_i.to_bytes(true).as_ref()), + &decom_vec[i].blind_factor, + ) == bc1_vec[i].com + && bc1_vec[i] + .correct_key_proof + .verify(&bc1_vec[i].e, zk_paillier::zkproofs::SALT_STRING) + .is_ok() + }); - let (vss_scheme, secret_shares) = VerifiableSS::share( - params.threshold as usize, - params.share_count as usize, - &self.u_i, - ); + let (vss_scheme, secret_shares) = + VerifiableSS::share(params.threshold, params.share_count, &self.u_i); if correct_key_correct_decom_all { - Ok((vss_scheme, secret_shares, self.party_index)) + Ok((vss_scheme, secret_shares.to_vec(), self.party_index)) } else { Err(InvalidKey) } @@ -244,29 +242,25 @@ impl Keys { pub fn phase2_verify_vss_construct_keypair_phase3_pok_dlog( &self, params: &Parameters, - y_vec: &[GE], - secret_shares_vec: &[FE], - vss_scheme_vec: &[VerifiableSS], - index: usize, - ) -> Result<(SharedKeys, DLogProof), Error> { - assert_eq!(y_vec.len() as u16, params.share_count); - assert_eq!(secret_shares_vec.len() as u16, params.share_count); - assert_eq!(vss_scheme_vec.len() as u16, params.share_count); - - let correct_ss_verify = (0..y_vec.len()) - .map(|i| { - vss_scheme_vec[i] - .validate_share(&secret_shares_vec[i], index) - .is_ok() - && vss_scheme_vec[i].commitments[0].get_element() == y_vec[i].get_element() - }) - .all(|x| x); + y_vec: &[Point], + secret_shares_vec: &[Scalar], + vss_scheme_vec: &[VerifiableSS], + index: u16, + ) -> Result<(SharedKeys, DLogProof), Error> { + assert_eq!(y_vec.len(), usize::from(params.share_count)); + assert_eq!(secret_shares_vec.len(), usize::from(params.share_count)); + assert_eq!(vss_scheme_vec.len(), usize::from(params.share_count)); + + let correct_ss_verify = (0..y_vec.len()).all(|i| { + vss_scheme_vec[i] + .validate_share(&secret_shares_vec[i], index) + .is_ok() + && vss_scheme_vec[i].commitments[0] == y_vec[i] + }); if correct_ss_verify { - let (head, tail) = y_vec.split_at(1); - let y = tail.iter().fold(head[0], |acc, x| acc + x); - - let x_i = secret_shares_vec.iter().fold(FE::zero(), |acc, x| acc + x); + let y: Point = y_vec.iter().sum(); + let x_i: Scalar = secret_shares_vec.iter().sum(); let dlog_proof = DLogProof::prove(&x_i); Ok((SharedKeys { y, x_i }, dlog_proof)) } else { @@ -274,43 +268,40 @@ impl Keys { } } - pub fn get_commitments_to_xi(vss_scheme_vec: &[VerifiableSS]) -> Vec { + pub fn get_commitments_to_xi( + vss_scheme_vec: &[VerifiableSS], + ) -> Vec> { let len = vss_scheme_vec.len(); - (1..=len) + (1..=u16::try_from(len).unwrap()) .map(|i| { - let xij_points_vec = (0..len) + (0..len) .map(|j| vss_scheme_vec[j].get_point_commitment(i)) - .collect::>(); - - let mut xij_points_iter = xij_points_vec.iter(); - let first = xij_points_iter.next().unwrap(); - - let tail = xij_points_iter; - tail.fold(first.clone(), |acc, x| acc + x) + .sum() }) - .collect::>() + .collect::>>() } pub fn update_commitments_to_xi( - comm: &GE, - vss_scheme: &VerifiableSS, - index: usize, - s: &[usize], - ) -> GE { - let li = VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, index, s); + comm: &Point, + vss_scheme: &VerifiableSS, + index: u16, + s: &[u16], + ) -> Point { + let li = + VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, index, s); comm * &li } pub fn verify_dlog_proofs( params: &Parameters, - dlog_proofs_vec: &[DLogProof], - y_vec: &[GE], + dlog_proofs_vec: &[DLogProof], + y_vec: &[Point], ) -> Result<(), Error> { - assert_eq!(y_vec.len() as u16, params.share_count); - assert_eq!(dlog_proofs_vec.len() as u16, params.share_count); - let xi_dlog_verify = (0..y_vec.len()) - .map(|i| DLogProof::verify(&dlog_proofs_vec[i]).is_ok()) - .all(|x| x); + assert_eq!(y_vec.len(), usize::from(params.share_count)); + assert_eq!(dlog_proofs_vec.len(), usize::from(params.share_count)); + + let xi_dlog_verify = + (0..y_vec.len()).all(|i| DLogProof::verify(&dlog_proofs_vec[i]).is_ok()); if xi_dlog_verify { Ok(()) @@ -329,18 +320,17 @@ impl PartyPrivate { } } - pub fn y_i(&self) -> GE { - let g: GE = ECPoint::generator(); - g * self.u_i + pub fn y_i(&self) -> Point { + Point::generator() * &self.u_i } pub fn decrypt(&self, ciphertext: BigInt) -> RawPlaintext { Paillier::decrypt(&self.dk, &RawCiphertext::from(ciphertext)) } - pub fn refresh_private_key(&self, factor: &FE, index: usize) -> Keys { - let u: FE = self.u_i + factor; - let y = GE::generator() * u; + pub fn refresh_private_key(&self, factor: &Scalar, index: u16) -> Keys { + let u: Scalar = &self.u_i + factor; + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair().keys(); Keys { @@ -353,9 +343,9 @@ impl PartyPrivate { } // we recommend using safe primes if the code is used in production - pub fn refresh_private_key_safe_prime(&self, factor: &FE, index: usize) -> Keys { - let u: FE = self.u_i + factor; - let y = &ECPoint::generator() * &u; + pub fn refresh_private_key_safe_prime(&self, factor: &Scalar, index: u16) -> Keys { + let u: Scalar = &self.u_i + factor; + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair_safe_primes().keys(); Keys { @@ -363,7 +353,7 @@ impl PartyPrivate { y_i: y, dk, ek, - party_index: index.clone(), + party_index: index, } } @@ -372,16 +362,20 @@ impl PartyPrivate { &self, segment_size: usize, num_of_segments: usize, - pub_ke_y: &GE, - g: &GE, + pub_ke_y: &Point, + g: &Point, ) -> (Witness, Helgamalsegmented) { Msegmentation::to_encrypted_segments(&self.u_i, &segment_size, num_of_segments, pub_ke_y, g) } - pub fn update_private_key(&self, factor_u_i: &FE, factor_x_i: &FE) -> Self { + pub fn update_private_key( + &self, + factor_u_i: &Scalar, + factor_x_i: &Scalar, + ) -> Self { PartyPrivate { - u_i: self.u_i + factor_u_i, - x_i: self.x_i + factor_x_i, + u_i: &self.u_i + factor_u_i, + x_i: &self.x_i + factor_x_i, dk: self.dk.clone(), } } @@ -390,21 +384,22 @@ impl PartyPrivate { impl SignKeys { pub fn create( private: &PartyPrivate, - vss_scheme: &VerifiableSS, - index: usize, - s: &[usize], + vss_scheme: &VerifiableSS, + index: u16, + s: &[u16], ) -> Self { - let li = VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, index, s); - let w_i = li * private.x_i; - let g: GE = ECPoint::generator(); - let g_w_i = g * w_i; - let gamma_i: FE = ECScalar::new_random(); - let g_gamma_i = g * gamma_i; + let li = + VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, index, s); + let w_i = li * &private.x_i; + let g = Point::generator(); + let g_w_i = g * &w_i; + let gamma_i = Scalar::::random(); + let g_gamma_i = g * &gamma_i; Self { w_i, g_w_i, - k_i: ECScalar::new_random(), + k_i: Scalar::::random(), gamma_i, g_gamma_i, } @@ -412,10 +407,10 @@ impl SignKeys { pub fn phase1_broadcast(&self) -> (SignBroadcastPhase1, SignDecommitPhase1) { let blind_factor = BigInt::sample(SECURITY); - let g: GE = ECPoint::generator(); - let g_gamma_i = g * self.gamma_i; - let com = HashCommitment::create_commitment_with_user_defined_randomness( - &g_gamma_i.bytes_compressed_to_big_int(), + let g = Point::generator(); + let g_gamma_i = g * &self.gamma_i; + let com = HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(g_gamma_i.to_bytes(true).as_ref()), &blind_factor, ); @@ -423,63 +418,62 @@ impl SignKeys { SignBroadcastPhase1 { com }, SignDecommitPhase1 { blind_factor, - g_gamma_i: self.g_gamma_i, + g_gamma_i: self.g_gamma_i.clone(), }, ) } - pub fn phase2_delta_i(&self, alpha_vec: &[FE], beta_vec: &[FE]) -> FE { - let vec_len = alpha_vec.len(); + pub fn phase2_delta_i( + &self, + alpha_vec: &[Scalar], + beta_vec: &[Scalar], + ) -> Scalar { assert_eq!(alpha_vec.len(), beta_vec.len()); - // assert_eq!(alpha_vec.len(), self.s.len() - 1); - let ki_gamma_i = self.k_i.mul(&self.gamma_i.get_element()); - (0..vec_len) - .map(|i| alpha_vec[i].add(&beta_vec[i].get_element())) - .fold(ki_gamma_i, |acc, x| acc + x) + let ki_gamma_i = &self.k_i * &self.gamma_i; + ki_gamma_i + alpha_vec.iter().chain(beta_vec).sum::>() } - pub fn phase2_sigma_i(&self, miu_vec: &[FE], ni_vec: &[FE]) -> FE { - let vec_len = miu_vec.len(); + pub fn phase2_sigma_i( + &self, + miu_vec: &[Scalar], + ni_vec: &[Scalar], + ) -> Scalar { assert_eq!(miu_vec.len(), ni_vec.len()); - //assert_eq!(miu_vec.len(), self.s.len() - 1); - let ki_w_i = self.k_i.mul(&self.w_i.get_element()); - (0..vec_len) - .map(|i| miu_vec[i].add(&ni_vec[i].get_element())) - .fold(ki_w_i, |acc, x| acc + x) + let ki_w_i = &self.k_i * &self.w_i; + ki_w_i + miu_vec.iter().chain(ni_vec).sum::>() } - pub fn phase3_reconstruct_delta(delta_vec: &[FE]) -> FE { - let sum = delta_vec.iter().fold(FE::zero(), |acc, x| acc + x); - sum.invert() + pub fn phase3_reconstruct_delta(delta_vec: &[Scalar]) -> Scalar { + delta_vec + .iter() + .sum::>() + .invert() + .expect("sum of deltas is zero") } pub fn phase4( - delta_inv: &FE, - b_proof_vec: &[&DLogProof], + delta_inv: &Scalar, + b_proof_vec: &[&DLogProof], phase1_decommit_vec: Vec, bc1_vec: &[SignBroadcastPhase1], - ) -> Result { + ) -> Result, Error> { // note: b_proof_vec is populated using the results //from the MtAwc, which is handling the proof of knowledge verification of gamma_i such that // Gamme_i = gamma_i * G in the verify_proofs_get_alpha() - let test_b_vec_and_com = (0..b_proof_vec.len()) - .map(|i| { - b_proof_vec[i].pk.get_element() == phase1_decommit_vec[i].g_gamma_i.get_element() - && HashCommitment::create_commitment_with_user_defined_randomness( - &phase1_decommit_vec[i] - .g_gamma_i - .bytes_compressed_to_big_int(), - &phase1_decommit_vec[i].blind_factor, - ) == bc1_vec[i].com - }) - .all(|x| x); + let test_b_vec_and_com = (0..b_proof_vec.len()).all(|i| { + b_proof_vec[i].pk == phase1_decommit_vec[i].g_gamma_i + && HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(phase1_decommit_vec[i].g_gamma_i.to_bytes(true).as_ref()), + &phase1_decommit_vec[i].blind_factor, + ) == bc1_vec[i].com + }); - let mut g_gamma_i_iter = phase1_decommit_vec.iter(); - let head = g_gamma_i_iter.next().unwrap(); - let tail = g_gamma_i_iter; if test_b_vec_and_com { Ok({ - let gamma_sum = tail.fold(head.g_gamma_i, |acc, x| acc + x.g_gamma_i); + let gamma_sum: Point = phase1_decommit_vec + .iter() + .map(|decom| &decom.g_gamma_i) + .sum(); // R gamma_sum * delta_inv }) @@ -490,19 +484,29 @@ impl SignKeys { } impl LocalSignature { - pub fn phase5_local_sig(k_i: &FE, message: &BigInt, R: &GE, sigma_i: &FE, pubkey: &GE) -> Self { - let m_fe: FE = ECScalar::from(message); - let r: FE = ECScalar::from(&R.x_coor().unwrap().mod_floor(&FE::q())); + pub fn phase5_local_sig( + k_i: &Scalar, + message: &BigInt, + R: &Point, + sigma_i: &Scalar, + pubkey: &Point, + ) -> Self { + let m_fe = Scalar::::from(message); + let r = Scalar::::from( + &R.x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()), + ); let s_i = m_fe * k_i + r * sigma_i; - let l_i: FE = ECScalar::new_random(); - let rho_i: FE = ECScalar::new_random(); + let l_i = Scalar::::random(); + let rho_i = Scalar::::random(); Self { l_i, rho_i, - R: *R, + R: R.clone(), s_i, m: message.clone(), - y: *pubkey, + y: pubkey.clone(), } } @@ -511,30 +515,32 @@ impl LocalSignature { ) -> ( Phase5Com1, Phase5ADecom1, - HomoELGamalProof, - DLogProof, + HomoELGamalProof, + DLogProof, ) { let blind_factor = BigInt::sample(SECURITY); - let g: GE = ECPoint::generator(); - let A_i = g * self.rho_i; - let l_i_rho_i = self.l_i.mul(&self.rho_i.get_element()); + let g = Point::generator(); + let A_i = g * &self.rho_i; + let l_i_rho_i = &self.l_i * &self.rho_i; let B_i = g * l_i_rho_i; - let V_i = self.R * self.s_i + g * self.l_i; - let input_hash = HSha256::create_hash_from_ge(&[&V_i, &A_i, &B_i]).to_big_int(); - let com = HashCommitment::create_commitment_with_user_defined_randomness( + let V_i = &self.R * &self.s_i + g * &self.l_i; + let input_hash = Sha256::new() + .chain_points([&V_i, &A_i, &B_i]) + .result_bigint(); + let com = HashCommitment::::create_commitment_with_user_defined_randomness( &input_hash, &blind_factor, ); let witness = HomoElGamalWitness { - r: self.l_i, - x: self.s_i, + r: self.l_i.clone(), + x: self.s_i.clone(), }; let delta = HomoElGamalStatement { - G: A_i, - H: self.R, - Y: g, - D: V_i, - E: B_i, + G: A_i.clone(), + H: self.R.clone(), + Y: g.to_point(), + D: V_i.clone(), + E: B_i.clone(), }; let dlog_proof_rho = DLogProof::prove(&self.rho_i); let proof = HomoELGamalProof::prove(&witness, &delta); @@ -556,64 +562,59 @@ impl LocalSignature { &self, decom_vec: &[Phase5ADecom1], com_vec: &[Phase5Com1], - elgamal_proofs: &[HomoELGamalProof], - dlog_proofs_rho: &[DLogProof], - v_i: &GE, - R: &GE, + elgamal_proofs: &[HomoELGamalProof], + dlog_proofs_rho: &[DLogProof], + v_i: &Point, + R: &Point, ) -> Result<(Phase5Com2, Phase5DDecom2), Error> { assert_eq!(decom_vec.len(), com_vec.len()); - let g: GE = ECPoint::generator(); - let test_com_elgamal = (0..com_vec.len()) - .map(|i| { - let delta = HomoElGamalStatement { - G: decom_vec[i].A_i, - H: *R, - Y: g, - D: decom_vec[i].V_i, - E: decom_vec[i].B_i, - }; - let input_hash = HSha256::create_hash_from_ge(&[ - &decom_vec[i].V_i, - &decom_vec[i].A_i, - &decom_vec[i].B_i, - ]) - .to_big_int(); - - HashCommitment::create_commitment_with_user_defined_randomness( - &input_hash, - &decom_vec[i].blind_factor, - ) == com_vec[i].com - && elgamal_proofs[i].verify(&delta).is_ok() - && DLogProof::verify(&dlog_proofs_rho[i]).is_ok() - }) - .all(|x| x); - - let v_vec = (0..com_vec.len()) - .map(|i| &decom_vec[i].V_i) - .collect::>(); - let a_vec = (0..com_vec.len()) - .map(|i| &decom_vec[i].A_i) - .collect::>(); - - let v = v_vec.iter().fold(v_i.clone(), |acc, x| acc + *x); + let g = Point::generator(); + let test_com_elgamal = (0..com_vec.len()).all(|i| { + let delta = HomoElGamalStatement { + G: decom_vec[i].A_i.clone(), + H: R.clone(), + Y: g.to_point(), + D: decom_vec[i].V_i.clone(), + E: decom_vec[i].B_i.clone(), + }; + + let input_hash = Sha256::new() + .chain_points([&decom_vec[i].V_i, &decom_vec[i].A_i, &decom_vec[i].B_i]) + .result_bigint(); + + HashCommitment::::create_commitment_with_user_defined_randomness( + &input_hash, + &decom_vec[i].blind_factor, + ) == com_vec[i].com + && elgamal_proofs[i].verify(&delta).is_ok() + && DLogProof::verify(&dlog_proofs_rho[i]).is_ok() + }); + + let v_iter = (0..com_vec.len()).map(|i| &decom_vec[i].V_i); + let a_iter = (0..com_vec.len()).map(|i| &decom_vec[i].A_i); + + let v = v_i + v_iter.sum::>(); // V = -mG -ry - sum (vi) - let mut a_i_iter = a_vec.iter(); - let head = a_i_iter.next().unwrap(); - let tail = a_i_iter; - let a = tail.fold((*head).clone(), |acc, x| acc.add_point(&(*x).get_element())); - - let r: FE = ECScalar::from(&self.R.x_coor().unwrap().mod_floor(&FE::q())); - let yr = self.y * r; - let g: GE = ECPoint::generator(); - let m_fe: FE = ECScalar::from(&self.m); + let a: Point = a_iter.sum(); + + let r = Scalar::::from( + &self + .R + .x_coord() + .ok_or(Error::InvalidSig)? + .mod_floor(Scalar::::group_order()), + ); + let yr = &self.y * r; + let g = Point::generator(); + let m_fe = Scalar::::from(&self.m); let gm = g * m_fe; - let v = v.sub_point(&gm.get_element()).sub_point(&yr.get_element()); - let u_i = v * self.rho_i; - let t_i = a * self.l_i; - let input_hash = HSha256::create_hash_from_ge(&[&u_i, &t_i]).to_big_int(); + let v = v - &gm - &yr; + let u_i = v * &self.rho_i; + let t_i = a * &self.l_i; + let input_hash = Sha256::new().chain_points([&u_i, &t_i]).result_bigint(); let blind_factor = BigInt::sample(SECURITY); - let com = HashCommitment::create_commitment_with_user_defined_randomness( + let com = HashCommitment::::create_commitment_with_user_defined_randomness( &input_hash, &blind_factor, ); @@ -639,40 +640,30 @@ impl LocalSignature { decom_vec2: &[Phase5DDecom2], com_vec2: &[Phase5Com2], decom_vec1: &[Phase5ADecom1], - ) -> Result { + ) -> Result, Error> { assert_eq!(decom_vec2.len(), decom_vec1.len()); assert_eq!(decom_vec2.len(), com_vec2.len()); - let test_com = (0..com_vec2.len()) - .map(|i| { - let input_hash = - HSha256::create_hash_from_ge(&[&decom_vec2[i].u_i, &decom_vec2[i].t_i]) - .to_big_int(); - HashCommitment::create_commitment_with_user_defined_randomness( - &input_hash, - &decom_vec2[i].blind_factor, - ) == com_vec2[i].com - }) - .all(|x| x); - - let t_vec = (0..com_vec2.len()) - .map(|i| &decom_vec2[i].t_i) - .collect::>(); - let u_vec = (0..com_vec2.len()) - .map(|i| &decom_vec2[i].u_i) - .collect::>(); - let b_vec = (0..decom_vec1.len()) - .map(|i| &decom_vec1[i].B_i) - .collect::>(); - - let g: GE = ECPoint::generator(); - let biased_sum_tb = t_vec.iter().zip(b_vec).fold(g, |acc, x| acc + *x.0 + x.1); - let biased_sum_tb_minus_u = u_vec - .iter() - .fold(biased_sum_tb, |acc, x| acc.sub_point(&x.get_element())); + let test_com = (0..com_vec2.len()).all(|i| { + let input_hash = Sha256::new() + .chain_points([&decom_vec2[i].u_i, &decom_vec2[i].t_i]) + .result_bigint(); + HashCommitment::::create_commitment_with_user_defined_randomness( + &input_hash, + &decom_vec2[i].blind_factor, + ) == com_vec2[i].com + }); + + let t_iter = decom_vec2.iter().map(|decom| &decom.t_i); + let u_iter = decom_vec2.iter().map(|decom| &decom.u_i); + let b_iter = decom_vec1.iter().map(|decom| &decom.B_i); + + let g = Point::generator(); + let biased_sum_tb = g + t_iter.chain(b_iter).sum::>(); + let biased_sum_tb_minus_u = biased_sum_tb - u_iter.sum::>(); if test_com { - if g == biased_sum_tb_minus_u { - Ok(self.s_i) + if *g.as_point() == biased_sum_tb_minus_u { + Ok(self.s_i.clone()) } else { Err(InvalidKey) } @@ -680,12 +671,22 @@ impl LocalSignature { Err(InvalidCom) } } - pub fn output_signature(&self, s_vec: &[FE]) -> Result { - let mut s = s_vec.iter().fold(self.s_i, |acc, x| acc + x); - let s_bn = s.to_big_int(); - - let r: FE = ECScalar::from(&self.R.x_coor().unwrap().mod_floor(&FE::q())); - let ry: BigInt = self.R.y_coor().unwrap().mod_floor(&FE::q()); + pub fn output_signature(&self, s_vec: &[Scalar]) -> Result { + let mut s = &self.s_i + s_vec.iter().sum::>(); + let s_bn = s.to_bigint(); + + let r = Scalar::::from( + &self + .R + .x_coord() + .ok_or(Error::InvalidSig)? + .mod_floor(Scalar::::group_order()), + ); + let ry: BigInt = self + .R + .y_coord() + .ok_or(Error::InvalidSig)? + .mod_floor(Scalar::::group_order()); /* Calculate recovery id - it is not possible to compute the public key out of the signature @@ -695,10 +696,10 @@ impl LocalSignature { */ let is_ry_odd = ry.test_bit(0); let mut recid = if is_ry_odd { 1 } else { 0 }; - let s_tag_bn = FE::q() - &s_bn; + let s_tag_bn = Scalar::::group_order() - &s_bn; if s_bn > s_tag_bn { - s = ECScalar::from(&s_tag_bn); - recid = recid ^ 1; + s = Scalar::::from(&s_tag_bn); + recid ^= 1; } let sig = SignatureRecid { r, s, recid }; let ver = verify(&sig, &self.y, &self.m).is_ok(); @@ -710,18 +711,25 @@ impl LocalSignature { } } -pub fn verify(sig: &SignatureRecid, y: &GE, message: &BigInt) -> Result<(), Error> { - let b = sig.s.invert(); - let a: FE = ECScalar::from(message); - let u1 = a * b; - let u2 = sig.r * b; +pub fn verify(sig: &SignatureRecid, y: &Point, message: &BigInt) -> Result<(), Error> { + let b = sig.s.invert().ok_or(Error::InvalidSig)?; + let a = Scalar::::from(message); + let u1 = a * &b; + let u2 = &sig.r * &b; - let g: GE = ECPoint::generator(); + let g = Point::generator(); let gu1 = g * u1; let yu2 = y * &u2; // can be faster using shamir trick - if sig.r == ECScalar::from(&(gu1 + yu2).x_coor().unwrap().mod_floor(&FE::q())) { + if sig.r + == Scalar::::from( + &(gu1 + yu2) + .x_coord() + .ok_or(Error::InvalidSig)? + .mod_floor(Scalar::::group_order()), + ) + { Ok(()) } else { Err(InvalidSig) diff --git a/src/protocols/multi_party_ecdsa/gg_2018/test.rs b/src/protocols/multi_party_ecdsa/gg_2018/test.rs index 07647dca..8f3781e0 100644 --- a/src/protocols/multi_party_ecdsa/gg_2018/test.rs +++ b/src/protocols/multi_party_ecdsa/gg_2018/test.rs @@ -23,13 +23,12 @@ use crate::protocols::multi_party_ecdsa::gg_2018::party_i::{ use crate::utilities::mta::{MessageA, MessageB}; use curv::arithmetic::traits::Converter; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use paillier::*; +use sha2::Sha256; #[test] fn test_keygen_t1_n2() { @@ -58,12 +57,17 @@ fn test_sign_n8_t4_ttag6() { fn keygen_t_n_parties( t: u16, n: u16, -) -> (Vec, Vec, Vec, GE, VerifiableSS) { +) -> ( + Vec, + Vec, + Vec>, + Point, + VerifiableSS, +) { let parames = Parameters { threshold: t, share_count: n, }; - let (t, n) = (t as usize, n as usize); let party_keys_vec = (0..n).map(Keys::create).collect::>(); let (bc1_vec, decom_vec): (Vec<_>, Vec<_>) = party_keys_vec @@ -71,7 +75,9 @@ fn keygen_t_n_parties( .map(|k| k.phase1_broadcast_phase3_proof_of_correct_key()) .unzip(); - let y_vec = (0..n).map(|i| decom_vec[i].y_i).collect::>(); + let y_vec = (0..usize::from(n)) + .map(|i| decom_vec[i].y_i.clone()) + .collect::>>(); let mut y_vec_iter = y_vec.iter(); let head = y_vec_iter.next().unwrap(); let tail = y_vec_iter; @@ -94,21 +100,18 @@ fn keygen_t_n_parties( for (vss_scheme, secret_shares, index) in vss_result { vss_scheme_vec.push(vss_scheme); secret_shares_vec.push(secret_shares); // cannot unzip - index_vec.push(index); + index_vec.push(index as u16); } let vss_scheme_for_test = vss_scheme_vec.clone(); - let party_shares = (0..n) + let party_shares = (0..usize::from(n)) .map(|i| { - (0..n) - .map(|j| { - let vec_j = &secret_shares_vec[j]; - vec_j[i] - }) - .collect::>() + (0..usize::from(n)) + .map(|j| secret_shares_vec[j][i].clone()) + .collect::>>() }) - .collect::>>(); + .collect::>>>(); let mut shared_keys_vec = Vec::new(); let mut dlog_proof_vec = Vec::new(); @@ -119,24 +122,33 @@ fn keygen_t_n_parties( &y_vec, &party_shares[i], &vss_scheme_vec, - &index_vec[i] + 1, + (&index_vec[i] + 1).into(), ) .expect("invalid vss"); shared_keys_vec.push(shared_keys); dlog_proof_vec.push(dlog_proof); } - let pk_vec = (0..n).map(|i| dlog_proof_vec[i].pk).collect::>(); + let pk_vec = dlog_proof_vec + .iter() + .map(|dlog_proof| dlog_proof.pk.clone()) + .collect::>>(); //both parties run: Keys::verify_dlog_proofs(¶mes, &dlog_proof_vec, &y_vec).expect("bad dlog proof"); //test - let xi_vec = (0..=t).map(|i| shared_keys_vec[i].x_i).collect::>(); + let xi_vec = shared_keys_vec + .iter() + .take(usize::from(t + 1)) + .map(|shared_keys| shared_keys.x_i.clone()) + .collect::>>(); let x = vss_scheme_for_test[0] .clone() - .reconstruct(&index_vec[0..=t], &xi_vec); - let sum_u_i = party_keys_vec.iter().fold(FE::zero(), |acc, x| acc + x.u_i); + .reconstruct(&index_vec[0..=usize::from(t)], &xi_vec); + let sum_u_i = party_keys_vec + .iter() + .fold(Scalar::::zero(), |acc, x| acc + &x.u_i); assert_eq!(x, sum_u_i); ( @@ -148,7 +160,7 @@ fn keygen_t_n_parties( ) } -fn sign(t: u16, n: u16, ttag: u16, s: Vec) { +fn sign(t: u16, n: u16, ttag: u16, s: Vec) { // full key gen emulation let (party_keys_vec, shared_keys_vec, _pk_vec, y, vss_scheme) = keygen_t_n_parties(t, n); @@ -166,7 +178,7 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { // create a vector of signing keys, one for each party. // throughout i will index parties let sign_keys_vec = (0..ttag) - .map(|i| SignKeys::create(&private_vec[s[i]], &vss_scheme, s[i], &s)) + .map(|i| SignKeys::create(&private_vec[usize::from(s[i])], &vss_scheme, s[i], &s)) .collect::>(); // each party computes [Ci,Di] = com(g^gamma_i) and broadcast the commitments @@ -179,7 +191,7 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { let m_a_vec: Vec<_> = sign_keys_vec .iter() .enumerate() - .map(|(i, k)| MessageA::a(&k.k_i, &party_keys_vec[s[i]].ek, &[]).0) + .map(|(i, k)| MessageA::a(&k.k_i, &party_keys_vec[usize::from(s[i])].ek, &[]).0) .collect(); // each party i sends responses to m_a_vec she received (one response with input gamma_i and one with w_i) @@ -202,14 +214,14 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { let (m_b_gamma, beta_gamma, _, _) = MessageB::b( &key.gamma_i, - &party_keys_vec[s[ind]].ek, + &party_keys_vec[usize::from(s[ind])].ek, m_a_vec[ind].clone(), &[], ) .unwrap(); let (m_b_w, beta_wi, _, _) = MessageB::b( &key.w_i, - &party_keys_vec[s[ind]].ek, + &party_keys_vec[usize::from(s[ind])].ek, m_a_vec[ind].clone(), &[], ) @@ -246,11 +258,17 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { let m_b = m_b_gamma_vec_i[j].clone(); let alpha_ij_gamma = m_b - .verify_proofs_get_alpha(&party_keys_vec[s[ind]].dk, &sign_keys_vec[ind].k_i) + .verify_proofs_get_alpha( + &party_keys_vec[usize::from(s[ind])].dk, + &sign_keys_vec[ind].k_i, + ) .expect("wrong dlog or m_b"); let m_b = m_b_w_vec_i[j].clone(); let alpha_ij_wi = m_b - .verify_proofs_get_alpha(&party_keys_vec[s[ind]].dk, &sign_keys_vec[ind].k_i) + .verify_proofs_get_alpha( + &party_keys_vec[usize::from(s[ind])].dk, + &sign_keys_vec[ind].k_i, + ) .expect("wrong dlog or m_b"); // since we actually run two MtAwc each party needs to make sure that the values B are the same as the public values @@ -270,11 +288,11 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { let mut sigma_vec = Vec::new(); for i in 0..ttag { - let alpha_vec: Vec = (0..alpha_vec_all[i].len()) - .map(|j| alpha_vec_all[i][j].0) + let alpha_vec: Vec> = (0..alpha_vec_all[i].len()) + .map(|j| alpha_vec_all[i][j].0.clone()) .collect(); - let miu_vec: Vec = (0..miu_vec_all[i].len()) - .map(|j| miu_vec_all[i][j].0) + let miu_vec: Vec> = (0..miu_vec_all[i].len()) + .map(|j| miu_vec_all[i][j].0.clone()) .collect(); let delta = sign_keys_vec[i].phase2_delta_i(&alpha_vec[..], &beta_vec_all[i]); @@ -290,8 +308,8 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { // Return R let _g_gamma_i_vec = (0..ttag) - .map(|i| sign_keys_vec[i].g_gamma_i) - .collect::>(); + .map(|i| sign_keys_vec[i].g_gamma_i.clone()) + .collect::>>(); let R_vec = (0..ttag) .map(|_| { @@ -301,14 +319,16 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { let b_gamma_vec = &m_b_gamma_vec_all[j]; &b_gamma_vec[0].b_proof }) - .collect::>>(); + .collect::>>(); SignKeys::phase4(&delta_inv, &b_proof_vec, decommit_vec1.clone(), &bc1_vec) .expect("bad gamma_i decommit") }) - .collect::>(); + .collect::>>(); let message: [u8; 4] = [79, 77, 69, 82]; - let message_bn = HSha256::create_hash(&[&BigInt::from_bytes(&message[..])]); + let message_bn = Sha256::new() + .chain_bigint(&BigInt::from_bytes(&message[..])) + .result_bigint(); let mut local_sig_vec = Vec::new(); // each party computes s_i but don't send it yet. we start with phase5 @@ -364,7 +384,7 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { } // assuming phase5 checks passes each party sends s_i and compute sum_i{s_i} - let mut s_vec: Vec = Vec::new(); + let mut s_vec: Vec> = Vec::new(); for sig in &local_sig_vec { let s_i = sig .phase5d(&phase_5d_decom2_vec, &phase5_com2_vec, &phase_5a_decom_vec) @@ -383,24 +403,24 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec) { check_sig(&sig.r, &sig.s, &local_sig_vec[0].m, &y); } -fn check_sig(r: &FE, s: &FE, msg: &BigInt, pk: &GE) { +fn check_sig(r: &Scalar, s: &Scalar, msg: &BigInt, pk: &Point) { use secp256k1::{verify, Message, PublicKey, PublicKeyFormat, Signature}; - let raw_msg = BigInt::to_bytes(&msg); + let raw_msg = BigInt::to_bytes(msg); let mut msg: Vec = Vec::new(); // padding msg.extend(vec![0u8; 32 - raw_msg.len()]); msg.extend(raw_msg.iter()); let msg = Message::parse_slice(msg.as_slice()).unwrap(); - let slice = pk.pk_to_key_slice(); + let slice = pk.to_bytes(false); let mut raw_pk = Vec::new(); if slice.len() != 65 { // after curv's pk_to_key_slice return 65 bytes, this can be removed raw_pk.insert(0, 4u8); raw_pk.extend(vec![0u8; 64 - slice.len()]); - raw_pk.extend(slice); + raw_pk.extend(slice.as_ref()); } else { - raw_pk.extend(slice); + raw_pk.extend(slice.as_ref()); } assert_eq!(raw_pk.len(), 65); @@ -408,11 +428,11 @@ fn check_sig(r: &FE, s: &FE, msg: &BigInt, pk: &GE) { let pk = PublicKey::parse_slice(&raw_pk, Some(PublicKeyFormat::Full)).unwrap(); let mut compact: Vec = Vec::new(); - let bytes_r = &r.get_element()[..]; + let bytes_r = &r.to_bytes()[..]; compact.extend(vec![0u8; 32 - bytes_r.len()]); compact.extend(bytes_r.iter()); - let bytes_s = &s.get_element()[..]; + let bytes_s = &s.to_bytes()[..]; compact.extend(vec![0u8; 32 - bytes_s.len()]); compact.extend(bytes_s.iter()); diff --git a/src/protocols/multi_party_ecdsa/gg_2020/blame.rs b/src/protocols/multi_party_ecdsa/gg_2020/blame.rs index 5dcac944..929a43d8 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/blame.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/blame.rs @@ -19,9 +19,7 @@ use crate::utilities::mta::{MessageA, MessageB}; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::ECDDHProof; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::ECDDHStatement; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::ECDDHWitness; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::ECPoint; -use curv::elliptic::curves::traits::ECScalar; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::traits::EncryptWithChosenRandomness; use paillier::traits::Open; @@ -29,12 +27,13 @@ use paillier::DecryptionKey; use paillier::Paillier; use paillier::{EncryptionKey, Randomness, RawCiphertext, RawPlaintext}; use serde::{Deserialize, Serialize}; +use sha2::Sha256; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LocalStatePhase5 { - pub k: FE, + pub k: Scalar, pub k_randomness: BigInt, - pub gamma: FE, + pub gamma: Scalar, pub beta_randomness: Vec, pub beta_tag: Vec, pub encryption_key: EncryptionKey, @@ -42,15 +41,15 @@ pub struct LocalStatePhase5 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GlobalStatePhase5 { - pub k_vec: Vec, + pub k_vec: Vec>, pub k_randomness_vec: Vec, - pub gamma_vec: Vec, + pub gamma_vec: Vec>, pub beta_randomness_vec: Vec>, pub beta_tag_vec: Vec>, pub encryption_key_vec: Vec, // stuff to check against - pub delta_vec: Vec, - pub g_gamma_vec: Vec, + pub delta_vec: Vec>, + pub g_gamma_vec: Vec>, pub m_a_vec: Vec, pub m_b_mat: Vec>, } @@ -60,22 +59,22 @@ pub struct GlobalStatePhase5 { impl GlobalStatePhase5 { pub fn local_state_to_global_state( encryption_key_vec: &[EncryptionKey], - delta_vec: &[FE], //to test against delta_vec - g_gamma_vec: &[GE], // to test against the opened commitment for g_gamma - m_a_vec: &[MessageA], // to test against broadcast message A - m_b_mat: Vec>, // to test against broadcast message B + delta_vec: &[Scalar], //to test against delta_vec + g_gamma_vec: &[Point], // to test against the opened commitment for g_gamma + m_a_vec: &[MessageA], // to test against broadcast message A + m_b_mat: Vec>, // to test against broadcast message B local_state_vec: &[LocalStatePhase5], ) -> Self { let len = local_state_vec.len(); let k_vec = (0..len) .map(|i| local_state_vec[i].k.clone()) - .collect::>(); + .collect::>>(); let k_randomness_vec = (0..len) .map(|i| local_state_vec[i].k_randomness.clone()) .collect::>(); let gamma_vec = (0..len) .map(|i| local_state_vec[i].gamma.clone()) - .collect::>(); + .collect::>>(); let beta_randomness_vec = (0..len) .map(|i| { (0..len - 1) @@ -120,7 +119,7 @@ impl GlobalStatePhase5 { // check commitment to g_gamma for i in 0..len { - if self.g_gamma_vec[i] != GE::generator() * self.gamma_vec[i] { + if self.g_gamma_vec[i] != Point::generator() * &self.gamma_vec[i] { bad_signers_vec.push(i) } } @@ -139,7 +138,7 @@ impl GlobalStatePhase5 { bad_signers_vec.push(i) } - let alpha_beta_vector = if bad_signers_vec.is_empty() { + if bad_signers_vec.is_empty() { (0..len - 1) .map(|j| { let ind = if j < i { j } else { j + 1 }; @@ -157,19 +156,17 @@ impl GlobalStatePhase5 { bad_signers_vec.push(ind) } - let k_i_gamma_j = self.k_vec[i] * self.gamma_vec[ind]; - let alpha = k_i_gamma_j.sub(&beta.get_element()); + let k_i_gamma_j = &self.k_vec[i] * &self.gamma_vec[ind]; + let alpha = k_i_gamma_j - β (alpha, beta) }) - .collect::>() + .collect::, Scalar)>>() } else { vec![] - }; - - alpha_beta_vector + } }) - .collect::>>(); + .collect::, Scalar)>>>(); // The matrix we got: // [P2, P1, P1, P1 ...] @@ -186,27 +183,30 @@ impl GlobalStatePhase5 { //reconstruct delta's let delta_vec_reconstruct = (0..len) .map(|i| { - let k_i_gamma_i = self.k_vec[i] * self.gamma_vec[i]; + let k_i_gamma_i = &self.k_vec[i] * &self.gamma_vec[i]; let alpha_sum = alpha_beta_matrix[i] .iter() - .fold(FE::zero(), |acc, x| acc + &x.0); + .fold(Scalar::::zero(), |acc, x| acc + &x.0); let beta_vec = (0..len - 1) .map(|j| { let ind1 = if j < i { j } else { j + 1 }; let ind2 = if j < i { i - 1 } else { i }; - alpha_beta_matrix[ind1][ind2].1 + alpha_beta_matrix[ind1][ind2].1.clone() }) - .collect::>(); + .collect::>>(); - let beta_sum = beta_vec.iter().fold(FE::zero(), |acc, x| acc + x); + let beta_sum = beta_vec + .iter() + .fold(Scalar::::zero(), |acc, x| acc + x); k_i_gamma_i + alpha_sum + beta_sum }) - .collect::>(); + .collect::>>(); // compare delta vec to reconstructed delta vec + #[allow(clippy::needless_range_loop)] for i in 0..len { if self.delta_vec[i] != delta_vec_reconstruct[i] { bad_signers_vec.push(i) @@ -214,7 +214,7 @@ impl GlobalStatePhase5 { } } - bad_signers_vec.sort(); + bad_signers_vec.sort_unstable(); bad_signers_vec.dedup(); let err_type = ErrorType { error_type: "phase6_blame".to_string(), @@ -226,24 +226,24 @@ impl GlobalStatePhase5 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LocalStatePhase6 { - pub k: FE, + pub k: Scalar, pub k_randomness: BigInt, pub miu: Vec, // we need the value before reduction pub miu_randomness: Vec, - pub proof_of_eq_dlog: ECDDHProof, + pub proof_of_eq_dlog: ECDDHProof, } // It is assumed the second message of MtAwc (ciphertext from b to a) is broadcasted in the original protocol #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GlobalStatePhase6 { - pub k_vec: Vec, + pub k_vec: Vec>, pub k_randomness_vec: Vec, pub miu_vec: Vec>, pub miu_randomness_vec: Vec>, - pub g_w_vec: Vec, + pub g_w_vec: Vec>, pub encryption_key_vec: Vec, - pub proof_vec: Vec>, - pub S_vec: Vec, + pub proof_vec: Vec>, + pub S_vec: Vec>, pub m_a_vec: Vec, pub m_b_mat: Vec>, } @@ -255,24 +255,27 @@ impl GlobalStatePhase6 { randomness.0 } - pub fn ecddh_proof(sigma_i: &FE, R: &GE, S: &GE) -> ECDDHProof { + pub fn ecddh_proof( + sigma_i: &Scalar, + R: &Point, + S: &Point, + ) -> ECDDHProof { let delta = ECDDHStatement { - g1: GE::generator(), + g1: Point::generator().to_point(), g2: R.clone(), - h1: GE::generator() * sigma_i, + h1: Point::generator() * sigma_i, h2: S.clone(), }; let w = ECDDHWitness { x: sigma_i.clone() }; - let proof = ECDDHProof::prove(&w, &delta); - proof + ECDDHProof::prove(&w, &delta) } // TODO: check all parties submitted inputs // TODO: if not - abort gracefully with list of parties that did not produce inputs pub fn local_state_to_global_state( encryption_key_vec: &[EncryptionKey], - S_vec: &[GE], - g_w_vec: &[GE], + S_vec: &[Point], + g_w_vec: &[Point], m_a_vec: &[MessageA], // to test against broadcast message A m_b_mat: Vec>, // to test against broadcast message B local_state_vec: &[LocalStatePhase6], @@ -280,13 +283,13 @@ impl GlobalStatePhase6 { let len = local_state_vec.len(); let k_vec = (0..len) .map(|i| local_state_vec[i].k.clone()) - .collect::>(); + .collect::>>(); let k_randomness_vec = (0..len) .map(|i| local_state_vec[i].k_randomness.clone()) .collect::>(); let proof_vec = (0..len) .map(|i| local_state_vec[i].proof_of_eq_dlog.clone()) - .collect::>>(); + .collect::>>(); let miu_randomness_vec = (0..len) .map(|i| { (0..len - 1) @@ -316,7 +319,7 @@ impl GlobalStatePhase6 { } } - pub fn phase6_blame(&self, R: &GE) -> Result<(), ErrorType> { + pub fn phase6_blame(&self, R: &Point) -> Result<(), ErrorType> { let len = self.k_vec.len(); let mut bad_signers_vec = Vec::new(); @@ -360,42 +363,44 @@ impl GlobalStatePhase6 { let k_i = &self.k_vec[i]; let g_w_j = &self.g_w_vec[ind]; let g_w_j_ki = g_w_j * k_i; - let miu: FE = ECScalar::from(&self.miu_vec[i][j]); - let g_miu = GE::generator() * &miu; - let g_ni = g_w_j_ki.sub_point(&g_miu.get_element()); - g_ni + let miu: Scalar = + Scalar::::from(&self.miu_vec[i][j]); + let g_miu = Point::generator() * &miu; + g_w_j_ki - &g_miu }) - .collect::>() + .collect::>>() }) - .collect::>>(); + .collect::>>>(); // compute g_sigma_i let mut g_sigma_i_vec = (0..len) .map(|i| { - let g_wi_ki = self.g_w_vec[i] * &self.k_vec[i]; + let g_wi_ki = &self.g_w_vec[i] * &self.k_vec[i]; let sum = self.miu_vec[i].iter().fold(g_wi_ki, |acc, x| { - acc + (GE::generator() * &ECScalar::from(&x)) + acc + (Point::generator() * &Scalar::::from(&*x)) }); sum }) - .collect::>(); + .collect::>>(); + #[allow(clippy::needless_range_loop)] for i in 0..len { for j in 0..len - 1 { let ind1 = if j < i { j } else { j + 1 }; let ind2 = if j < i { i - 1 } else { i }; - g_sigma_i_vec[i] = g_sigma_i_vec[i] + g_ni_mat[ind1][ind2]; + g_sigma_i_vec[i] = &g_sigma_i_vec[i] + &g_ni_mat[ind1][ind2]; } } // check zero knowledge proof + #[allow(clippy::needless_range_loop)] for i in 0..len { let statement = ECDDHStatement { - g1: GE::generator(), + g1: Point::generator().to_point(), g2: R.clone(), - h1: g_sigma_i_vec[i], - h2: self.S_vec[i], + h1: g_sigma_i_vec[i].clone(), + h2: self.S_vec[i].clone(), }; let result = self.proof_vec[i].verify(&statement); @@ -405,7 +410,7 @@ impl GlobalStatePhase6 { } } - bad_signers_vec.sort(); + bad_signers_vec.sort_unstable(); bad_signers_vec.dedup(); let err_type = ErrorType { error_type: "phase6_blame".to_string(), @@ -417,12 +422,12 @@ impl GlobalStatePhase6 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GlobalStatePhase7 { - pub s_vec: Vec, - pub r: FE, - pub R_dash_vec: Vec, + pub s_vec: Vec>, + pub r: Scalar, + pub R_dash_vec: Vec>, pub m: BigInt, - pub R: GE, - pub S_vec: Vec, + pub R: Point, + pub S_vec: Vec>, } impl GlobalStatePhase7 { @@ -431,9 +436,9 @@ impl GlobalStatePhase7 { let mut bad_signers_vec = Vec::new(); for i in 0..len { - let R_si = self.R * &self.s_vec[i]; - let R_dash_m = self.R_dash_vec[i] * &ECScalar::from(&self.m); - let Si_r = self.S_vec[i] * &self.r; + let R_si = &self.R * &self.s_vec[i]; + let R_dash_m = &self.R_dash_vec[i] * &Scalar::::from(&self.m); + let Si_r = &self.S_vec[i] * &self.r; let right = R_dash_m + Si_r; let left = R_si; if left != right { diff --git a/src/protocols/multi_party_ecdsa/gg_2020/party_i.rs b/src/protocols/multi_party_ecdsa/gg_2020/party_i.rs index ac2ce532..ba9266bd 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/party_i.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/party_i.rs @@ -18,8 +18,6 @@ use std::fmt::Debug; -use derivative::Derivative; - use centipede::juggling::proof_system::{Helgamalsegmented, Witness}; use centipede::juggling::segmentation::Msegmentation; use curv::arithmetic::traits::*; @@ -28,9 +26,9 @@ use curv::cryptographic_primitives::commitments::traits::Commitment; use curv::cryptographic_primitives::proofs::sigma_correct_homomorphic_elgamal_enc::*; use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Curve, Point, Scalar}; use curv::BigInt; +use sha2::Sha256; use crate::Error::{self, InvalidSig, Phase5BadSum, Phase6Error}; use paillier::{ @@ -38,13 +36,15 @@ use paillier::{ }; use serde::{Deserialize, Serialize}; -use zk_paillier::zkproofs::NICorrectKeyProof; +use zk_paillier::zkproofs::NiCorrectKeyProof; use zk_paillier::zkproofs::{CompositeDLogProof, DLogStatement}; use crate::protocols::multi_party_ecdsa::gg_2020::ErrorType; use crate::utilities::zk_pdl_with_slack::{PDLwSlackProof, PDLwSlackStatement, PDLwSlackWitness}; use curv::cryptographic_primitives::proofs::sigma_valid_pedersen::PedersenProof; +use std::convert::TryInto; + const SECURITY: usize = 256; const PAILLIER_MIN_BIT_LENGTH: usize = 2047; const PAILLIER_MAX_BIT_LENGTH: usize = 2048; @@ -55,15 +55,10 @@ pub struct Parameters { pub share_count: u16, //n } -#[derive(Derivative, Serialize, Deserialize)] -#[derivative(Clone(bound = "P: Clone, P::Scalar: Clone"))] -#[derivative(Debug(bound = "P: Debug, P::Scalar: Debug"))] -pub struct Keys

-where - P: ECPoint, -{ - pub u_i: P::Scalar, - pub y_i: P, +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct Keys { + pub u_i: Scalar, + pub y_i: Point, pub dk: DecryptionKey, pub ek: EncryptionKey, pub party_index: usize, @@ -76,8 +71,8 @@ where #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PartyPrivate { - u_i: FE, - x_i: FE, + u_i: Scalar, + x_i: Scalar, dk: DecryptionKey, } @@ -86,7 +81,7 @@ pub struct KeyGenBroadcastMessage1 { pub e: EncryptionKey, pub dlog_statement: DLogStatement, pub com: BigInt, - pub correct_key_proof: NICorrectKeyProof, + pub correct_key_proof: NiCorrectKeyProof, pub composite_dlog_proof_base_h1: CompositeDLogProof, pub composite_dlog_proof_base_h2: CompositeDLogProof, } @@ -94,25 +89,22 @@ pub struct KeyGenBroadcastMessage1 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyGenDecommitMessage1 { pub blind_factor: BigInt, - pub y_i: GE, + pub y_i: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SharedKeys

-where - P: ECPoint, -{ - pub y: P, - pub x_i: P::Scalar, +pub struct SharedKeys { + pub y: Point, + pub x_i: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SignKeys { - pub w_i: FE, - pub g_w_i: GE, - pub k_i: FE, - pub gamma_i: FE, - pub g_gamma_i: GE, + pub w_i: Scalar, + pub g_w_i: Point, + pub k_i: Scalar, + pub gamma_i: Scalar, + pub g_gamma_i: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -123,22 +115,22 @@ pub struct SignBroadcastPhase1 { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SignDecommitPhase1 { pub blind_factor: BigInt, - pub g_gamma_i: GE, + pub g_gamma_i: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LocalSignature { - pub r: FE, - pub R: GE, - pub s_i: FE, + pub r: Scalar, + pub R: Point, + pub s_i: Scalar, pub m: BigInt, - pub y: GE, + pub y: Point, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SignatureRecid { - pub r: FE, - pub s: FE, + pub r: Scalar, + pub s: Scalar, pub recid: u8, } @@ -165,8 +157,8 @@ pub fn generate_h1_h2_N_tilde() -> (BigInt, BigInt, BigInt, BigInt, BigInt) { impl Keys { pub fn create(index: usize) -> Self { - let u = FE::new_random(); - let y = GE::generator() * u; + let u = Scalar::::random(); + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair().keys(); let (N_tilde, h1, h2, xhi, xhi_inv) = generate_h1_h2_N_tilde(); @@ -185,9 +177,9 @@ impl Keys { } // we recommend using safe primes if the code is used in production - pub fn create_safe_prime(index: usize) -> Keys { - let u: FE = ECScalar::new_random(); - let y = &ECPoint::generator() * &u; + pub fn create_safe_prime(index: usize) -> Self { + let u = Scalar::::random(); + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair_safe_primes().keys(); let (N_tilde, h1, h2, xhi, xhi_inv) = generate_h1_h2_N_tilde(); @@ -205,8 +197,8 @@ impl Keys { xhi_inv, } } - pub fn create_from(u: FE, index: usize) -> Keys { - let y = &ECPoint::generator() * &u; + pub fn create_from(u: Scalar, index: usize) -> Self { + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair().keys(); let (N_tilde, h1, h2, xhi, xhi_inv) = generate_h1_h2_N_tilde(); @@ -228,7 +220,7 @@ impl Keys { &self, ) -> (KeyGenBroadcastMessage1, KeyGenDecommitMessage1) { let blind_factor = BigInt::sample(SECURITY); - let correct_key_proof = NICorrectKeyProof::proof(&self.dk, None); + let correct_key_proof = NiCorrectKeyProof::proof(&self.dk, None); let dlog_statement_base_h1 = DLogStatement { N: self.N_tilde.clone(), @@ -246,8 +238,8 @@ impl Keys { let composite_dlog_proof_base_h2 = CompositeDLogProof::prove(&dlog_statement_base_h2, &self.xhi_inv); - let com = HashCommitment::create_commitment_with_user_defined_randomness( - &self.y_i.bytes_compressed_to_big_int(), + let com = HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(self.y_i.to_bytes(true).as_ref()), &blind_factor, ); let bcm1 = KeyGenBroadcastMessage1 { @@ -260,7 +252,7 @@ impl Keys { }; let decom1 = KeyGenDecommitMessage1 { blind_factor, - y_i: self.y_i, + y_i: self.y_i.clone(), }; (bcm1, decom1) } @@ -270,11 +262,11 @@ impl Keys { params: &Parameters, decom_vec: &[KeyGenDecommitMessage1], bc1_vec: &[KeyGenBroadcastMessage1], - ) -> Result<(VerifiableSS, Vec, usize), ErrorType> { + ) -> Result<(VerifiableSS, Vec>, usize), ErrorType> { let mut bad_actors_vec = Vec::new(); // test length: - assert_eq!(decom_vec.len() as u16, params.share_count); - assert_eq!(bc1_vec.len() as u16, params.share_count); + assert_eq!(decom_vec.len(), usize::from(params.share_count)); + assert_eq!(bc1_vec.len(), usize::from(params.share_count)); // test paillier correct key, h1,h2 correct generation and test decommitments let correct_key_correct_decom_all = (0..bc1_vec.len()) .map(|i| { @@ -283,27 +275,28 @@ impl Keys { g: bc1_vec[i].dlog_statement.ni.clone(), ni: bc1_vec[i].dlog_statement.g.clone(), }; - let test_res = HashCommitment::create_commitment_with_user_defined_randomness( - &decom_vec[i].y_i.bytes_compressed_to_big_int(), - &decom_vec[i].blind_factor, - ) == bc1_vec[i].com - && bc1_vec[i] - .correct_key_proof - .verify(&bc1_vec[i].e, zk_paillier::zkproofs::SALT_STRING) - .is_ok() - && bc1_vec[i].e.n.bit_length() >= PAILLIER_MIN_BIT_LENGTH - && bc1_vec[i].e.n.bit_length() <= PAILLIER_MAX_BIT_LENGTH - && bc1_vec[i].dlog_statement.N.bit_length() >= PAILLIER_MIN_BIT_LENGTH - && bc1_vec[i].dlog_statement.N.bit_length() <= PAILLIER_MAX_BIT_LENGTH - && bc1_vec[i] - .composite_dlog_proof_base_h1 - .verify(&bc1_vec[i].dlog_statement) - .is_ok() - && bc1_vec[i] - .composite_dlog_proof_base_h2 - .verify(&dlog_statement_base_h2) - .is_ok(); - if test_res == false { + let test_res = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(&decom_vec[i].y_i.to_bytes(true)), + &decom_vec[i].blind_factor, + ) == bc1_vec[i].com + && bc1_vec[i] + .correct_key_proof + .verify(&bc1_vec[i].e, zk_paillier::zkproofs::SALT_STRING) + .is_ok() + && bc1_vec[i].e.n.bit_length() >= PAILLIER_MIN_BIT_LENGTH + && bc1_vec[i].e.n.bit_length() <= PAILLIER_MAX_BIT_LENGTH + && bc1_vec[i].dlog_statement.N.bit_length() >= PAILLIER_MIN_BIT_LENGTH + && bc1_vec[i].dlog_statement.N.bit_length() <= PAILLIER_MAX_BIT_LENGTH + && bc1_vec[i] + .composite_dlog_proof_base_h1 + .verify(&bc1_vec[i].dlog_statement) + .is_ok() + && bc1_vec[i] + .composite_dlog_proof_base_h2 + .verify(&dlog_statement_base_h2) + .is_ok(); + if !test_res { bad_actors_vec.push(i); false } else { @@ -317,13 +310,10 @@ impl Keys { bad_actors: bad_actors_vec, }; - let (vss_scheme, secret_shares) = VerifiableSS::share( - params.threshold as usize, - params.share_count as usize, - &self.u_i, - ); + let (vss_scheme, secret_shares) = + VerifiableSS::share(params.threshold, params.share_count, &self.u_i); if correct_key_correct_decom_all { - Ok((vss_scheme, secret_shares, self.party_index)) + Ok((vss_scheme, secret_shares.to_vec(), self.party_index)) } else { Err(err_type) } @@ -332,23 +322,23 @@ impl Keys { pub fn phase2_verify_vss_construct_keypair_phase3_pok_dlog( &self, params: &Parameters, - y_vec: &[GE], - secret_shares_vec: &[FE], - vss_scheme_vec: &[VerifiableSS], + y_vec: &[Point], + secret_shares_vec: &[Scalar], + vss_scheme_vec: &[VerifiableSS], index: usize, - ) -> Result<(SharedKeys, DLogProof), ErrorType> { + ) -> Result<(SharedKeys, DLogProof), ErrorType> { let mut bad_actors_vec = Vec::new(); - assert_eq!(y_vec.len() as u16, params.share_count); - assert_eq!(secret_shares_vec.len() as u16, params.share_count); - assert_eq!(vss_scheme_vec.len() as u16, params.share_count); + assert_eq!(y_vec.len(), usize::from(params.share_count)); + assert_eq!(secret_shares_vec.len(), usize::from(params.share_count)); + assert_eq!(vss_scheme_vec.len(), usize::from(params.share_count)); let correct_ss_verify = (0..y_vec.len()) .map(|i| { let res = vss_scheme_vec[i] - .validate_share(&secret_shares_vec[i], index) + .validate_share(&secret_shares_vec[i], index.try_into().unwrap()) .is_ok() - && vss_scheme_vec[i].commitments[0].get_element() == y_vec[i].get_element(); - if res == false { + && vss_scheme_vec[i].commitments[0] == y_vec[i]; + if !res { bad_actors_vec.push(i); false } else { @@ -364,9 +354,11 @@ impl Keys { if correct_ss_verify { let (head, tail) = y_vec.split_at(1); - let y = tail.iter().fold(head[0], |acc, x| acc + x); + let y = tail.iter().fold(head[0].clone(), |acc, x| acc + x); - let x_i = secret_shares_vec.iter().fold(FE::zero(), |acc, x| acc + x); + let x_i = secret_shares_vec + .iter() + .fold(Scalar::::zero(), |acc, x| acc + x); let dlog_proof = DLogProof::prove(&x_i); Ok((SharedKeys { y, x_i }, dlog_proof)) } else { @@ -374,14 +366,15 @@ impl Keys { } } - pub fn get_commitments_to_xi(vss_scheme_vec: &[VerifiableSS]) -> Vec { + pub fn get_commitments_to_xi( + vss_scheme_vec: &[VerifiableSS], + ) -> Vec> { let len = vss_scheme_vec.len(); let (head, tail) = vss_scheme_vec.split_at(1); let mut global_coefficients = head[0].commitments.clone(); for vss in tail { for (i, coefficient_commitment) in vss.commitments.iter().enumerate() { - global_coefficients[i] = - global_coefficients[i].add_point(&coefficient_commitment.get_element()); + global_coefficients[i] = &global_coefficients[i] + &*coefficient_commitment; } } @@ -390,29 +383,34 @@ impl Keys { commitments: global_coefficients, }; (1..=len) - .map(|i| global_vss.get_point_commitment(i)) - .collect::>() + .map(|i| global_vss.get_point_commitment(i.try_into().unwrap())) + .collect::>>() } pub fn update_commitments_to_xi( - comm: &GE, - vss_scheme: &VerifiableSS, + comm: &Point, + vss_scheme: &VerifiableSS, index: usize, s: &[usize], - ) -> GE { - let li = VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, index, s); + ) -> Point { + let s: Vec = s.iter().map(|&i| i.try_into().unwrap()).collect(); + let li = VerifiableSS::::map_share_to_new_params( + &vss_scheme.parameters, + index.try_into().unwrap(), + s.as_slice(), + ); comm * &li } pub fn verify_dlog_proofs_check_against_vss( params: &Parameters, - dlog_proofs_vec: &[DLogProof], - y_vec: &[GE], - vss_vec: &[VerifiableSS], + dlog_proofs_vec: &[DLogProof], + y_vec: &[Point], + vss_vec: &[VerifiableSS], ) -> Result<(), ErrorType> { let mut bad_actors_vec = Vec::new(); - assert_eq!(y_vec.len() as u16, params.share_count); - assert_eq!(dlog_proofs_vec.len() as u16, params.share_count); + assert_eq!(y_vec.len(), usize::from(params.share_count)); + assert_eq!(dlog_proofs_vec.len(), usize::from(params.share_count)); let xi_commitments = Keys::get_commitments_to_xi(vss_vec); let xi_dlog_verify = (0..y_vec.len()) .map(|i| { @@ -449,18 +447,18 @@ impl PartyPrivate { } } - pub fn y_i(&self) -> GE { - let g: GE = ECPoint::generator(); - g * self.u_i + pub fn y_i(&self) -> Point { + let g = Point::generator(); + g * &self.u_i } pub fn decrypt(&self, ciphertext: BigInt) -> RawPlaintext { Paillier::decrypt(&self.dk, &RawCiphertext::from(ciphertext)) } - pub fn refresh_private_key(&self, factor: &FE, index: usize) -> Keys { - let u: FE = self.u_i + factor; - let y = GE::generator() * u; + pub fn refresh_private_key(&self, factor: &Scalar, index: usize) -> Keys { + let u: Scalar = &self.u_i + factor; + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair().keys(); let (N_tilde, h1, h2, xhi, xhi_inv) = generate_h1_h2_N_tilde(); @@ -480,9 +478,9 @@ impl PartyPrivate { } // we recommend using safe primes if the code is used in production - pub fn refresh_private_key_safe_prime(&self, factor: &FE, index: usize) -> Keys { - let u: FE = self.u_i + factor; - let y = &ECPoint::generator() * &u; + pub fn refresh_private_key_safe_prime(&self, factor: &Scalar, index: usize) -> Keys { + let u: Scalar = &self.u_i + factor; + let y = Point::generator() * &u; let (ek, dk) = Paillier::keypair_safe_primes().keys(); let (N_tilde, h1, h2, xhi, xhi_inv) = generate_h1_h2_N_tilde(); @@ -492,7 +490,7 @@ impl PartyPrivate { y_i: y, dk, ek, - party_index: index.clone(), + party_index: index, N_tilde, h1, h2, @@ -506,46 +504,63 @@ impl PartyPrivate { &self, segment_size: usize, num_of_segments: usize, - pub_ke_y: &GE, - g: &GE, + pub_ke_y: &Point, + g: &Point, ) -> (Witness, Helgamalsegmented) { Msegmentation::to_encrypted_segments(&self.u_i, &segment_size, num_of_segments, pub_ke_y, g) } - pub fn update_private_key(&self, factor_u_i: &FE, factor_x_i: &FE) -> Self { + pub fn update_private_key( + &self, + factor_u_i: &Scalar, + factor_x_i: &Scalar, + ) -> Self { PartyPrivate { - u_i: self.u_i + factor_u_i, - x_i: self.x_i + factor_x_i, + u_i: &self.u_i + factor_u_i, + x_i: &self.x_i + factor_x_i, dk: self.dk.clone(), } } } impl SignKeys { - pub fn g_w_vec(pk_vec: &[GE], s: &[usize], vss_scheme: &VerifiableSS) -> Vec { + pub fn g_w_vec( + pk_vec: &[Point], + s: &[usize], + vss_scheme: &VerifiableSS, + ) -> Vec> { + let s: Vec = s.iter().map(|&i| i.try_into().unwrap()).collect(); // TODO: check bounds (0..s.len()) .map(|i| { - let li = - VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, s[i], s); - pk_vec[s[i]] * &li + let li = VerifiableSS::::map_share_to_new_params( + &vss_scheme.parameters, + s[i], + s.as_slice(), + ); + &pk_vec[s[i] as usize] * &li }) - .collect::>() + .collect::>>() } pub fn create( - private_x_i: &FE, - vss_scheme: &VerifiableSS, + private_x_i: &Scalar, + vss_scheme: &VerifiableSS, index: usize, s: &[usize], ) -> Self { - let li = VerifiableSS::::map_share_to_new_params(&vss_scheme.parameters, index, s); + let s: Vec = s.iter().map(|&i| i.try_into().unwrap()).collect(); + let li = VerifiableSS::::map_share_to_new_params( + &vss_scheme.parameters, + index.try_into().unwrap(), + s.as_slice(), + ); let w_i = li * private_x_i; - let g: GE = ECPoint::generator(); - let g_w_i = g * w_i; - let gamma_i: FE = ECScalar::new_random(); - let g_gamma_i = g * gamma_i; - let k_i: FE = ECScalar::new_random(); + let g = Point::generator(); + let g_w_i = g * &w_i; + let gamma_i = Scalar::::random(); + let g_gamma_i = g * &gamma_i; + let k_i = Scalar::::random(); Self { w_i, g_w_i, @@ -557,10 +572,10 @@ impl SignKeys { pub fn phase1_broadcast(&self) -> (SignBroadcastPhase1, SignDecommitPhase1) { let blind_factor = BigInt::sample(SECURITY); - let g: GE = ECPoint::generator(); - let g_gamma_i = g * self.gamma_i; - let com = HashCommitment::create_commitment_with_user_defined_randomness( - &g_gamma_i.bytes_compressed_to_big_int(), + let g = Point::generator(); + let g_gamma_i = g * &self.gamma_i; + let com = HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(g_gamma_i.to_bytes(true).as_ref()), &blind_factor, ); @@ -568,66 +583,81 @@ impl SignKeys { SignBroadcastPhase1 { com }, SignDecommitPhase1 { blind_factor, - g_gamma_i: self.g_gamma_i, + g_gamma_i: self.g_gamma_i.clone(), }, ) } - pub fn phase2_delta_i(&self, alpha_vec: &[FE], beta_vec: &[FE]) -> FE { + pub fn phase2_delta_i( + &self, + alpha_vec: &[Scalar], + beta_vec: &[Scalar], + ) -> Scalar { let vec_len = alpha_vec.len(); assert_eq!(alpha_vec.len(), beta_vec.len()); // assert_eq!(alpha_vec.len(), self.s.len() - 1); - let ki_gamma_i = self.k_i.mul(&self.gamma_i.get_element()); + let ki_gamma_i = &self.k_i * &self.gamma_i; (0..vec_len) - .map(|i| alpha_vec[i].add(&beta_vec[i].get_element())) + .map(|i| &alpha_vec[i] + &beta_vec[i]) .fold(ki_gamma_i, |acc, x| acc + x) } - pub fn phase2_sigma_i(&self, miu_vec: &[FE], ni_vec: &[FE]) -> FE { + pub fn phase2_sigma_i( + &self, + miu_vec: &[Scalar], + ni_vec: &[Scalar], + ) -> Scalar { let vec_len = miu_vec.len(); assert_eq!(miu_vec.len(), ni_vec.len()); //assert_eq!(miu_vec.len(), self.s.len() - 1); - let ki_w_i = self.k_i.mul(&self.w_i.get_element()); + let ki_w_i = &self.k_i * &self.w_i; (0..vec_len) - .map(|i| miu_vec[i].add(&ni_vec[i].get_element())) + .map(|i| &miu_vec[i] + &ni_vec[i]) .fold(ki_w_i, |acc, x| acc + x) } - pub fn phase3_compute_t_i(sigma_i: &FE) -> (GE, FE, PedersenProof) { - let g_sigma_i = GE::generator() * sigma_i; - let l: FE = ECScalar::new_random(); - let h_l = GE::base_point2() * &l; + pub fn phase3_compute_t_i( + sigma_i: &Scalar, + ) -> ( + Point, + Scalar, + PedersenProof, + ) { + let g_sigma_i = Point::generator() * sigma_i; + let l = Scalar::::random(); + let h_l = Point::::base_point2() * &l; let T = g_sigma_i + h_l; - let T_zk_proof = PedersenProof::::prove(&sigma_i, &l); + let T_zk_proof = PedersenProof::::prove(sigma_i, &l); (T, l, T_zk_proof) } - pub fn phase3_reconstruct_delta(delta_vec: &[FE]) -> FE { - let sum = delta_vec.iter().fold(FE::zero(), |acc, x| acc + x); - sum.invert() + pub fn phase3_reconstruct_delta(delta_vec: &[Scalar]) -> Scalar { + let sum = delta_vec + .iter() + .fold(Scalar::::zero(), |acc, x| acc + x); + sum.invert().unwrap() } pub fn phase4( - delta_inv: &FE, - b_proof_vec: &[&DLogProof], + delta_inv: &Scalar, + b_proof_vec: &[&DLogProof], phase1_decommit_vec: Vec, bc1_vec: &[SignBroadcastPhase1], index: usize, - ) -> Result { + ) -> Result, ErrorType> { let mut bad_actors_vec = Vec::new(); let test_b_vec_and_com = (0..b_proof_vec.len()) .map(|j| { let ind = if j < index { j } else { j + 1 }; - let res = b_proof_vec[j].pk.get_element() - == phase1_decommit_vec[ind].g_gamma_i.get_element() - && HashCommitment::create_commitment_with_user_defined_randomness( - &phase1_decommit_vec[ind] - .g_gamma_i - .bytes_compressed_to_big_int(), + let res = b_proof_vec[j].pk == phase1_decommit_vec[ind].g_gamma_i + && HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes( + phase1_decommit_vec[ind].g_gamma_i.to_bytes(true).as_ref(), + ), &phase1_decommit_vec[ind].blind_factor, ) == bc1_vec[ind].com; - if res == false { + if !res { bad_actors_vec.push(ind); false } else { @@ -647,7 +677,7 @@ impl SignKeys { if test_b_vec_and_com { Ok({ - let gamma_sum = tail.fold(head.g_gamma_i, |acc, x| acc + x.g_gamma_i); + let gamma_sum = tail.fold(head.g_gamma_i.clone(), |acc, x| acc + &x.g_gamma_i); // R gamma_sum * delta_inv }) @@ -659,11 +689,11 @@ impl SignKeys { impl LocalSignature { pub fn phase5_proof_pdl( - R_dash: &GE, - R: &GE, + R_dash: &Point, + R: &Point, k_ciphertext: &BigInt, ek: &EncryptionKey, - k_i: &FE, + k_i: &Scalar, k_enc_randomness: &BigInt, dlog_statement: &DLogStatement, ) -> PDLwSlackProof { @@ -683,14 +713,13 @@ impl LocalSignature { r: k_enc_randomness.clone(), }; - let proof = PDLwSlackProof::prove(&pdl_w_slack_witness, &pdl_w_slack_statement); - proof + PDLwSlackProof::prove(&pdl_w_slack_witness, &pdl_w_slack_statement) } pub fn phase5_verify_pdl( pdl_w_slack_proof_vec: &[PDLwSlackProof], - R_dash: &GE, - R: &GE, + R_dash: &Point, + R: &Point, k_ciphertext: &BigInt, ek: &EncryptionKey, dlog_statement: &[DLogStatement], @@ -705,8 +734,8 @@ impl LocalSignature { let pdl_w_slack_statement = PDLwSlackStatement { ciphertext: k_ciphertext.clone(), ek: ek.clone(), - Q: *R_dash, - G: *R, + Q: R_dash.clone(), + G: R.clone(), h1: dlog_statement[s[ind]].g.clone(), h2: dlog_statement[s[ind]].ni.clone(), N_tilde: dlog_statement[s[ind]].N.clone(), @@ -732,25 +761,27 @@ impl LocalSignature { } } - pub fn phase5_check_R_dash_sum(R_dash_vec: &[GE]) -> Result<(), Error> { - let sum = R_dash_vec.iter().fold(GE::generator(), |acc, x| acc + x); - match sum.sub_point(&GE::generator().get_element()) == GE::generator() { + pub fn phase5_check_R_dash_sum(R_dash_vec: &[Point]) -> Result<(), Error> { + let sum = R_dash_vec + .iter() + .fold(Point::generator().to_point(), |acc, x| acc + x); + match sum - &Point::generator().to_point() == Point::generator().to_point() { true => Ok(()), false => Err(Phase5BadSum), } } pub fn phase6_compute_S_i_and_proof_of_consistency( - R: &GE, - T: &GE, - sigma: &FE, - l: &FE, - ) -> (GE, HomoELGamalProof) { + R: &Point, + T: &Point, + sigma: &Scalar, + l: &Scalar, + ) -> (Point, HomoELGamalProof) { let S = R * sigma; let delta = HomoElGamalStatement { G: R.clone(), - H: GE::base_point2(), - Y: GE::generator(), + H: Point::::base_point2().clone(), + Y: Point::generator().to_point(), D: T.clone(), E: S.clone(), }; @@ -764,18 +795,18 @@ impl LocalSignature { } pub fn phase6_verify_proof( - S_vec: &[GE], - proof_vec: &[HomoELGamalProof], - R_vec: &[GE], - T_vec: &[GE], + S_vec: &[Point], + proof_vec: &[HomoELGamalProof], + R_vec: &[Point], + T_vec: &[Point], ) -> Result<(), ErrorType> { let mut bad_actors_vec = Vec::new(); let mut verify_proofs = true; for i in 0..proof_vec.len() { let delta = HomoElGamalStatement { G: R_vec[i].clone(), - H: GE::base_point2(), - Y: GE::generator(), + H: Point::::base_point2().clone(), + Y: Point::generator().to_point(), D: T_vec[i].clone(), E: S_vec[i].clone(), }; @@ -797,9 +828,14 @@ impl LocalSignature { } } - pub fn phase6_check_S_i_sum(pubkey_y: &GE, S_vec: &[GE]) -> Result<(), Error> { - let sum_plus_g = S_vec.iter().fold(GE::generator(), |acc, x| acc + x); - let sum = sum_plus_g.sub_point(&GE::generator().get_element()); + pub fn phase6_check_S_i_sum( + pubkey_y: &Point, + S_vec: &[Point], + ) -> Result<(), Error> { + let sum_plus_g = S_vec + .iter() + .fold(Point::generator().to_point(), |acc, x| acc + x); + let sum = sum_plus_g - &Point::generator().to_point(); match &sum == pubkey_y { true => Ok(()), @@ -807,25 +843,45 @@ impl LocalSignature { } } - pub fn phase7_local_sig(k_i: &FE, message: &BigInt, R: &GE, sigma_i: &FE, pubkey: &GE) -> Self { - let m_fe: FE = ECScalar::from(message); - let r: FE = ECScalar::from(&R.x_coor().unwrap().mod_floor(&FE::q())); - let s_i = m_fe * k_i + r * sigma_i; + pub fn phase7_local_sig( + k_i: &Scalar, + message: &BigInt, + R: &Point, + sigma_i: &Scalar, + pubkey: &Point, + ) -> Self { + let m_fe = Scalar::::from(message); + let r = Scalar::::from( + &R.x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()), + ); + let s_i = m_fe * k_i + &r * sigma_i; Self { r, - R: *R, + R: R.clone(), s_i, m: message.clone(), - y: *pubkey, + y: pubkey.clone(), } } - pub fn output_signature(&self, s_vec: &[FE]) -> Result { - let mut s = s_vec.iter().fold(self.s_i, |acc, x| acc + x); - let s_bn = s.to_big_int(); + pub fn output_signature(&self, s_vec: &[Scalar]) -> Result { + let mut s = s_vec.iter().fold(self.s_i.clone(), |acc, x| acc + x); + let s_bn = s.to_bigint(); - let r: FE = ECScalar::from(&self.R.x_coor().unwrap().mod_floor(&FE::q())); - let ry: BigInt = self.R.y_coor().unwrap().mod_floor(&FE::q()); + let r = Scalar::::from( + &self + .R + .x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()), + ); + let ry: BigInt = self + .R + .y_coord() + .unwrap() + .mod_floor(Scalar::::group_order()); /* Calculate recovery id - it is not possible to compute the public key out of the signature @@ -835,10 +891,10 @@ impl LocalSignature { */ let is_ry_odd = ry.test_bit(0); let mut recid = if is_ry_odd { 1 } else { 0 }; - let s_tag_bn = FE::q() - &s_bn; + let s_tag_bn = Scalar::::group_order() - &s_bn; if s_bn > s_tag_bn { - s = ECScalar::from(&s_tag_bn); - recid = recid ^ 1; + s = Scalar::::from(&s_tag_bn); + recid ^= 1; } let sig = SignatureRecid { r, s, recid }; let ver = verify(&sig, &self.y, &self.m).is_ok(); @@ -850,18 +906,25 @@ impl LocalSignature { } } -pub fn verify(sig: &SignatureRecid, y: &GE, message: &BigInt) -> Result<(), Error> { - let b = sig.s.invert(); - let a: FE = ECScalar::from(message); - let u1 = a * b; - let u2 = sig.r * b; +pub fn verify(sig: &SignatureRecid, y: &Point, message: &BigInt) -> Result<(), Error> { + let b = sig.s.invert().unwrap(); + let a = Scalar::::from(message); + let u1 = a * &b; + let u2 = &sig.r * &b; - let g: GE = ECPoint::generator(); + let g = Point::generator(); let gu1 = g * u1; let yu2 = y * &u2; // can be faster using shamir trick - if sig.r == ECScalar::from(&(gu1 + yu2).x_coor().unwrap().mod_floor(&FE::q())) { + if sig.r + == Scalar::::from( + &(gu1 + yu2) + .x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()), + ) + { Ok(()) } else { Err(InvalidSig) diff --git a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen.rs b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen.rs index 013242f0..37e157af 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen.rs @@ -6,13 +6,14 @@ use std::time::Duration; use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; -use curv::elliptic::curves::secp256_k1::{FE, GE}; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Scalar}; use round_based::containers::{ push::{Push, PushExt}, *, }; use round_based::{IsCritical, Msg, StateMachine}; use serde::{Deserialize, Serialize}; +use sha2::Sha256; use thiserror::Error; use crate::protocols::multi_party_ecdsa::gg_2020; @@ -32,8 +33,8 @@ pub struct Keygen { msgs1: Option>>, msgs2: Option>>, - msgs3: Option, FE)>>>, - msgs4: Option>>>, + msgs3: Option, Scalar)>>>, + msgs4: Option>>>, msgs_queue: Vec>, @@ -186,7 +187,7 @@ impl Keygen { impl StateMachine for Keygen { type MessageBody = ProtocolMessage; type Err = Error; - type Output = LocalKey; + type Output = LocalKey; fn handle_incoming(&mut self, msg: Msg) -> Result<()> { let current_round = self.current_round(); @@ -345,15 +346,14 @@ impl super::traits::RoundBlame for Keygen { let store4_blame = self.msgs4.as_ref().map(|s| s.blame()).unwrap_or_default(); let default = (0, vec![]); - let res = match &self.round { - R::Round0(_) => default.clone(), + match &self.round { + R::Round0(_) => default, R::Round1(_) => store1_blame, R::Round2(_) => store2_blame, R::Round3(_) => store3_blame, R::Round4(_) => store4_blame, - R::Final(_) | R::Gone => default.clone(), - }; - res + R::Final(_) | R::Gone => default, + } } } @@ -405,7 +405,7 @@ enum R { Round2(Round2), Round3(Round3), Round4(Round4), - Final(LocalKey), + Final(LocalKey), Gone, } @@ -421,8 +421,8 @@ pub struct ProtocolMessage(M); enum M { Round1(gg_2020::party_i::KeyGenBroadcastMessage1), Round2(gg_2020::party_i::KeyGenDecommitMessage1), - Round3((VerifiableSS, FE)), - Round4(DLogProof), + Round3((VerifiableSS, Scalar)), + Round4(DLogProof), } // Error @@ -495,7 +495,7 @@ pub mod test { use super::*; - pub fn simulate_keygen(t: u16, n: u16) -> Vec { + pub fn simulate_keygen(t: u16, n: u16) -> Vec> { let mut simulation = Simulation::new(); simulation.enable_benchmarks(true); diff --git a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen/rounds.rs b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen/rounds.rs index 314bf08b..ed8df423 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen/rounds.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/keygen/rounds.rs @@ -1,8 +1,8 @@ use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; -use curv::elliptic::curves::secp256_k1::{FE, GE}; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Curve, Point, Scalar}; +use sha2::Sha256; -use derivative::Derivative; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -16,7 +16,6 @@ use crate::protocols::multi_party_ecdsa::gg_2020::party_i::{ KeyGenBroadcastMessage1, KeyGenDecommitMessage1, Keys, }; use crate::protocols::multi_party_ecdsa::gg_2020::{self, ErrorType}; -use curv::elliptic::curves::traits::ECPoint; pub struct Round0 { pub party_i: u16, @@ -34,7 +33,7 @@ impl Round0 { party_keys.phase1_broadcast_phase3_proof_of_correct_key_proof_of_correct_h1h2(); output.push(Msg { - sender: self.party_i.clone(), + sender: self.party_i, receiver: None, body: bc1.clone(), }); @@ -71,7 +70,7 @@ impl Round1 { O: Push>, { output.push(Msg { - sender: self.party_i.clone(), + sender: self.party_i, receiver: None, body: self.decom1.clone(), }); @@ -80,7 +79,7 @@ impl Round1 { received_comm: input.into_vec_including_me(self.bc1), decom: self.decom1, - party_i: self.party_i.clone(), + party_i: self.party_i, t: self.t, n: self.n, }) @@ -110,11 +109,11 @@ impl Round2 { mut output: O, ) -> Result where - O: Push, FE)>>, + O: Push, Scalar)>>, { let params = gg_2020::party_i::Parameters { - threshold: self.t.into(), - share_count: self.n.into(), + threshold: self.t, + share_count: self.n, }; let received_decom = input.into_vec_including_me(self.decom); @@ -128,12 +127,12 @@ impl Round2 { .map_err(ProceedError::Round2VerifyCommitments)?; for (i, share) in vss_result.1.iter().enumerate() { - if i + 1 == usize::from(self.party_i.clone()) { + if i + 1 == usize::from(self.party_i) { continue; } output.push(Msg { - sender: self.party_i.clone(), + sender: self.party_i, receiver: Some(i as u16 + 1), body: (vss_result.0.clone(), share.clone()), }) @@ -146,9 +145,9 @@ impl Round2 { bc_vec: self.received_comm, own_vss: vss_result.0.clone(), - own_share: vss_result.1[usize::from(self.party_i.clone() - 1)].clone(), + own_share: vss_result.1[usize::from(self.party_i - 1)].clone(), - party_i: self.party_i.clone(), + party_i: self.party_i, t: self.t, n: self.n, }) @@ -164,11 +163,11 @@ impl Round2 { pub struct Round3 { keys: gg_2020::party_i::Keys, - y_vec: Vec, + y_vec: Vec>, bc_vec: Vec, - own_vss: VerifiableSS, - own_share: FE, + own_vss: VerifiableSS, + own_share: Scalar, party_i: u16, t: u16, @@ -176,13 +175,17 @@ pub struct Round3 { } impl Round3 { - pub fn proceed(self, input: P2PMsgs<(VerifiableSS, FE)>, mut output: O) -> Result + pub fn proceed( + self, + input: P2PMsgs<(VerifiableSS, Scalar)>, + mut output: O, + ) -> Result where - O: Push>>, + O: Push>>, { let params = gg_2020::party_i::Parameters { - threshold: self.t.into(), - share_count: self.n.into(), + threshold: self.t, + share_count: self.n, }; let (vss_schemes, party_shares): (Vec<_>, Vec<_>) = input .into_vec_including_me((self.own_vss, self.own_share)) @@ -196,7 +199,7 @@ impl Round3 { &self.y_vec, &party_shares, &vss_schemes, - self.party_i.clone() as usize, + self.party_i.into(), ) .map_err(ProceedError::Round3VerifyVssConstruct)?; @@ -211,10 +214,10 @@ impl Round3 { y_vec: self.y_vec.clone(), bc_vec: self.bc_vec, shared_keys, - own_dlog_proof: dlog_proof.clone(), + own_dlog_proof: dlog_proof, vss_vec: vss_schemes, - party_i: self.party_i.clone(), + party_i: self.party_i, t: self.t, n: self.n, }) @@ -222,18 +225,21 @@ impl Round3 { pub fn is_expensive(&self) -> bool { true } - pub fn expects_messages(i: u16, n: u16) -> Store, FE)>> { + pub fn expects_messages( + i: u16, + n: u16, + ) -> Store, Scalar)>> { containers::P2PMsgsStore::new(i, n) } } pub struct Round4 { keys: gg_2020::party_i::Keys, - y_vec: Vec, + y_vec: Vec>, bc_vec: Vec, shared_keys: gg_2020::party_i::SharedKeys, - own_dlog_proof: DLogProof, - vss_vec: Vec>, + own_dlog_proof: DLogProof, + vss_vec: Vec>, party_i: u16, t: u16, @@ -241,10 +247,13 @@ pub struct Round4 { } impl Round4 { - pub fn proceed(self, input: BroadcastMsgs>) -> Result { + pub fn proceed( + self, + input: BroadcastMsgs>, + ) -> Result> { let params = gg_2020::party_i::Parameters { - threshold: self.t.into(), - share_count: self.n.into(), + threshold: self.t, + share_count: self.n, }; let dlog_proofs = input.into_vec_including_me(self.own_dlog_proof.clone()); @@ -256,8 +265,8 @@ impl Round4 { ) .map_err(ProceedError::Round4VerifyDLogProof)?; let pk_vec = (0..params.share_count as usize) - .map(|i| dlog_proofs[i].pk) - .collect::>(); + .map(|i| dlog_proofs[i].pk.clone()) + .collect::>>(); let paillier_key_vec = (0..params.share_count) .map(|i| self.bc_vec[i as usize].e.clone()) @@ -269,7 +278,7 @@ impl Round4 { .collect::>(); let (head, tail) = self.y_vec.split_at(1); - let y_sum = tail.iter().fold(head[0], |acc, x| acc + x); + let y_sum = tail.iter().fold(head[0].clone(), |acc, x| acc + x); let local_key = LocalKey { paillier_dk: self.keys.dk, @@ -292,35 +301,29 @@ impl Round4 { pub fn is_expensive(&self) -> bool { true } - pub fn expects_messages(i: u16, n: u16) -> Store>> { + pub fn expects_messages(i: u16, n: u16) -> Store>> { containers::BroadcastMsgsStore::new(i, n) } } /// Local secret obtained by party after [keygen](super::Keygen) protocol is completed -#[derive(Derivative, Serialize, Deserialize)] -#[derivative(Clone(bound = "P: Clone, P::Scalar: Clone"))] -#[serde(bound(serialize = "P: Serialize, P::Scalar: Serialize"))] -#[serde(bound(deserialize = "P: Deserialize<'de>, P::Scalar: Deserialize<'de>"))] -pub struct LocalKey

-where - P: ECPoint, -{ +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct LocalKey { pub paillier_dk: paillier::DecryptionKey, - pub pk_vec: Vec

, - pub keys_linear: gg_2020::party_i::SharedKeys

, + pub pk_vec: Vec>, + pub keys_linear: gg_2020::party_i::SharedKeys, pub paillier_key_vec: Vec, - pub y_sum_s: P, + pub y_sum_s: Point, pub h1_h2_n_tilde_vec: Vec, - pub vss_scheme: VerifiableSS

, + pub vss_scheme: VerifiableSS, pub i: u16, pub t: u16, pub n: u16, } -impl LocalKey

{ +impl LocalKey { /// Public key of secret shared between parties - pub fn public_key(&self) -> P { + pub fn public_key(&self) -> Point { self.y_sum_s.clone() } } diff --git a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign.rs b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign.rs index 4ca2143d..04dbc1e5 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign.rs @@ -32,6 +32,7 @@ use thiserror::Error; use crate::utilities::mta::MessageA; use crate::protocols::multi_party_ecdsa::gg_2020 as gg20; +use curv::elliptic::curves::secp256_k1::Secp256k1; use gg20::party_i::{SignBroadcastPhase1, SignDecommitPhase1, SignatureRecid}; use gg20::state_machine::keygen::LocalKey; @@ -74,7 +75,7 @@ impl OfflineStage { /// party local secret share `local_key`. /// /// Returns error if given arguments are contradicting. - pub fn new(i: u16, s_l: Vec, local_key: LocalKey) -> Result { + pub fn new(i: u16, s_l: Vec, local_key: LocalKey) -> Result { if s_l.len() < 2 { return Err(Error::TooFewParties); } @@ -89,7 +90,7 @@ impl OfflineStage { { // Check if s_l has duplicates let mut s_l_sorted = s_l.clone(); - s_l_sorted.sort(); + s_l_sorted.sort_unstable(); let mut s_l_sorted_deduped = s_l_sorted.clone(); s_l_sorted_deduped.dedup(); @@ -461,6 +462,7 @@ impl super::traits::RoundBlame for OfflineStage { } } +#[allow(clippy::large_enum_variant)] enum OfflineR { R0(Round0), R1(Round1), @@ -477,6 +479,7 @@ enum OfflineR { pub struct OfflineProtocolMessage(OfflineM); #[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(clippy::large_enum_variant)] enum OfflineM { M1((MessageA, SignBroadcastPhase1)), M2((GammaI, WI)), @@ -637,7 +640,7 @@ impl SignManual { /// by other parties) pub fn complete(self, sigs: &[PartialSignature]) -> Result { self.state - .proceed_manual(&sigs) + .proceed_manual(sigs) .map_err(SignError::CompleteSigning) } } @@ -653,16 +656,16 @@ pub enum SignError { #[cfg(test)] mod test { use curv::arithmetic::Converter; - use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; - use curv::cryptographic_primitives::hashing::traits::Hash; + use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use round_based::dev::Simulation; + use sha2::Sha256; use super::*; use gg20::party_i::verify; use gg20::state_machine::keygen::test::simulate_keygen; fn simulate_offline_stage( - local_keys: Vec, + local_keys: Vec>, s_l: &[u16], ) -> Vec { let mut simulation = Simulation::new(); @@ -688,7 +691,9 @@ mod test { } fn simulate_signing(offline: Vec, message: &[u8]) { - let message = HSha256::create_hash(&[&BigInt::from_bytes(message)]); + let message = Sha256::new() + .chain_bigint(&BigInt::from_bytes(message)) + .result_bigint(); let pk = offline[0].public_key().clone(); let parties = offline @@ -746,7 +751,7 @@ mod test { simulate_signing(offline_stage, b"ZenGo"); let offline_stage = simulate_offline_stage(local_keys.clone(), &[1, 3]); simulate_signing(offline_stage, b"ZenGo"); - let offline_stage = simulate_offline_stage(local_keys.clone(), &[2, 3]); + let offline_stage = simulate_offline_stage(local_keys, &[2, 3]); simulate_signing(offline_stage, b"ZenGo"); } diff --git a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign/rounds.rs b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign/rounds.rs index 3804c22c..8bf81a6b 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign/rounds.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/state_machine/sign/rounds.rs @@ -6,8 +6,9 @@ use std::iter; use serde::{Deserialize, Serialize}; use thiserror::Error; -use curv::elliptic::curves::secp256_k1::{FE, GE}; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; +use sha2::Sha256; use round_based::containers::push::Push; use round_based::containers::{self, BroadcastMsgs, P2PMsgs, Store}; @@ -28,23 +29,24 @@ use gg20::ErrorType; type Result = std::result::Result; #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct GWI(pub GE); +#[allow(clippy::upper_case_acronyms)] +pub struct GWI(pub Point); #[derive(Serialize, Deserialize, Debug, Clone)] pub struct GammaI(pub MessageB); #[derive(Serialize, Deserialize, Debug, Clone)] pub struct WI(pub MessageB); #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct DeltaI(FE); +pub struct DeltaI(Scalar); #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct TI(pub GE); +pub struct TI(pub Point); #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct TIProof(pub PedersenProof); +pub struct TIProof(pub PedersenProof); #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct RDash(GE); +pub struct RDash(Point); #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct SI(pub GE); +pub struct SI(pub Point); #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct HEGProof(pub HomoELGamalProof); +pub struct HEGProof(pub HomoELGamalProof); pub struct Round0 { /// Index of this party @@ -59,7 +61,7 @@ pub struct Round0 { pub s_l: Vec, /// Party local secret share - pub local_key: LocalKey, + pub local_key: LocalKey, } impl Round0 { @@ -109,7 +111,7 @@ impl Round0 { pub struct Round1 { i: u16, s_l: Vec, - local_key: LocalKey, + local_key: LocalKey, m_a: (MessageA, BigInt), sign_keys: SignKeys, phase1_com: SignBroadcastPhase1, @@ -206,11 +208,11 @@ impl Round1 { pub struct Round2 { i: u16, s_l: Vec, - local_key: LocalKey, + local_key: LocalKey, sign_keys: SignKeys, m_a: (MessageA, BigInt), - beta_vec: Vec, - ni_vec: Vec, + beta_vec: Vec>, + ni_vec: Vec>, bc_vec: Vec, m_a_vec: Vec, phase1_decom: SignDecommitPhase1, @@ -267,7 +269,11 @@ impl Round2 { output.push(Msg { sender: self.i, receiver: None, - body: (DeltaI(delta_i), TI(t_i), TIProof(t_i_proof.clone())), + body: ( + DeltaI(delta_i.clone()), + TI(t_i.clone()), + TIProof(t_i_proof.clone()), + ), }); Ok(Round3 { @@ -300,17 +306,17 @@ impl Round2 { pub struct Round3 { i: u16, s_l: Vec, - local_key: LocalKey, + local_key: LocalKey, sign_keys: SignKeys, m_a: (MessageA, BigInt), mb_gamma_s: Vec, bc_vec: Vec, m_a_vec: Vec, - delta_i: FE, - t_i: GE, - l_i: FE, - sigma_i: FE, - t_i_proof: PedersenProof, + delta_i: Scalar, + t_i: Point, + l_i: Scalar, + sigma_i: Scalar, + t_i_proof: PedersenProof, phase1_decom: SignDecommitPhase1, } @@ -325,15 +331,19 @@ impl Round3 { O: Push>, { let (delta_vec, t_vec, t_proof_vec) = input - .into_vec_including_me((DeltaI(self.delta_i), TI(self.t_i), TIProof(self.t_i_proof))) + .into_vec_including_me(( + DeltaI(self.delta_i), + TI(self.t_i.clone()), + TIProof(self.t_i_proof), + )) .into_iter() .map(|(delta_i, t_i, t_i_proof)| (delta_i.0, t_i.0, t_i_proof.0)) .unzip3(); let delta_inv = SignKeys::phase3_reconstruct_delta(&delta_vec); let ttag = self.s_l.len(); - for i in 0..ttag { - PedersenProof::verify(&t_proof_vec[i]).expect("error T proof"); + for proof in t_proof_vec.iter().take(ttag) { + PedersenProof::verify(proof).expect("error T proof"); } output.push(Msg { @@ -372,17 +382,17 @@ impl Round3 { pub struct Round4 { i: u16, s_l: Vec, - local_key: LocalKey, + local_key: LocalKey, sign_keys: SignKeys, m_a: (MessageA, BigInt), mb_gamma_s: Vec, bc_vec: Vec, m_a_vec: Vec, - t_i: GE, - l_i: FE, - sigma_i: FE, - delta_inv: FE, - t_vec: Vec, + t_i: Point, + l_i: Scalar, + sigma_i: Scalar, + delta_inv: Scalar, + t_vec: Vec>, phase1_decom: SignDecommitPhase1, } @@ -402,12 +412,12 @@ impl Round4 { let R = SignKeys::phase4( &self.delta_inv, &b_proof_vec[..], - decom_vec.clone(), + decom_vec, &self.bc_vec, usize::from(self.i - 1), ) .expect(""); //TODO: propagate the error - let R_dash = R * self.sign_keys.k_i; + let R_dash = &R * &self.sign_keys.k_i; // each party sends first message to all other parties let mut phase5_proofs_vec = Vec::new(); @@ -436,7 +446,7 @@ impl Round4 { output.push(Msg { sender: self.i, receiver: None, - body: (RDash(R_dash), phase5_proofs_vec.clone()), + body: (RDash(R_dash.clone()), phase5_proofs_vec.clone()), }); Ok(Round5 { @@ -467,15 +477,15 @@ impl Round4 { pub struct Round5 { i: u16, s_l: Vec, - local_key: LocalKey, + local_key: LocalKey, sign_keys: SignKeys, - t_vec: Vec, + t_vec: Vec>, m_a_vec: Vec, - t_i: GE, - l_i: FE, - sigma_i: FE, - R: GE, - R_dash: GE, + t_i: Point, + l_i: Scalar, + sigma_i: Scalar, + R: Point, + R_dash: Point, phase5_proofs_vec: Vec, } @@ -554,8 +564,8 @@ impl Round5 { } pub struct Round6 { - S_i: GE, - homo_elgamal_proof: HomoELGamalProof, + S_i: Point, + homo_elgamal_proof: HomoELGamalProof, s_l: Vec, /// Round 6 guards protocol output until final checks are taken the place protocol_output: CompletedOfflineStage, @@ -600,21 +610,21 @@ impl Round6 { #[derive(Clone)] pub struct CompletedOfflineStage { i: u16, - local_key: LocalKey, + local_key: LocalKey, sign_keys: SignKeys, - t_vec: Vec, - R: GE, - sigma_i: FE, + t_vec: Vec>, + R: Point, + sigma_i: Scalar, } impl CompletedOfflineStage { - pub fn public_key(&self) -> &GE { + pub fn public_key(&self) -> &Point { &self.local_key.y_sum_s } } #[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PartialSignature(FE); +pub struct PartialSignature(Scalar); #[derive(Clone)] pub struct Round7 { @@ -628,7 +638,7 @@ impl Round7 { ) -> Result<(Self, PartialSignature)> { let local_signature = LocalSignature::phase7_local_sig( &completed_offline_stage.sign_keys.k_i, - &message, + message, &completed_offline_stage.R, &completed_offline_stage.sigma_i, &completed_offline_stage.local_key.y_sum_s, @@ -638,7 +648,7 @@ impl Round7 { } pub fn proceed_manual(self, sigs: &[PartialSignature]) -> Result { - let sigs = sigs.iter().map(|s_i| s_i.0).collect::>(); + let sigs = sigs.iter().map(|s_i| s_i.0.clone()).collect::>(); self.local_signature .output_signature(&sigs) .map_err(Error::Round7) diff --git a/src/protocols/multi_party_ecdsa/gg_2020/test.rs b/src/protocols/multi_party_ecdsa/gg_2020/test.rs index 45c796cf..1cd8bcb2 100644 --- a/src/protocols/multi_party_ecdsa/gg_2020/test.rs +++ b/src/protocols/multi_party_ecdsa/gg_2020/test.rs @@ -28,14 +28,13 @@ use curv::arithmetic::traits::Converter; use crate::protocols::multi_party_ecdsa::gg_2020::ErrorType; use crate::utilities::zk_pdl_with_slack::PDLwSlackProof; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; use curv::cryptographic_primitives::proofs::sigma_valid_pedersen::PedersenProof; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use paillier::*; +use sha2::Sha256; use zk_paillier::zkproofs::DLogStatement; #[test] @@ -155,9 +154,9 @@ fn keygen_t_n_parties( ( Vec, Vec, - Vec, - GE, - VerifiableSS, + Vec>, + Point, + VerifiableSS, Vec, Vec, ), @@ -183,7 +182,9 @@ fn keygen_t_n_parties( .iter() .map(|bc1| bc1.dlog_statement.clone()) .collect::>(); - let y_vec = (0..n).map(|i| decom_vec[i].y_i).collect::>(); + let y_vec = (0..n) + .map(|i| decom_vec[i].y_i.clone()) + .collect::>>(); let mut y_vec_iter = y_vec.iter(); let head = y_vec_iter.next().unwrap(); let tail = y_vec_iter; @@ -207,7 +208,7 @@ fn keygen_t_n_parties( for (vss_scheme, secret_shares, index) in vss_result { vss_scheme_vec.push(vss_scheme); secret_shares_vec.push(secret_shares); // cannot unzip - index_vec.push(index); + index_vec.push(index as u16); } let vss_scheme_for_test = vss_scheme_vec.clone(); @@ -217,11 +218,11 @@ fn keygen_t_n_parties( (0..n) .map(|j| { let vec_j = &secret_shares_vec[j]; - vec_j[i] + vec_j[i].clone() }) - .collect::>() + .collect::>>() }) - .collect::>>(); + .collect::>>>(); let mut shared_keys_vec = Vec::new(); let mut dlog_proof_vec = Vec::new(); @@ -231,7 +232,7 @@ fn keygen_t_n_parties( &y_vec, &party_shares[i], &vss_scheme_vec, - &index_vec[i] + 1, + (&index_vec[i] + 1).into(), ); if res.is_err() { return Err(res.err().unwrap()); @@ -241,7 +242,9 @@ fn keygen_t_n_parties( dlog_proof_vec.push(dlog_proof); } - let pk_vec = (0..n).map(|i| dlog_proof_vec[i].pk).collect::>(); + let pk_vec = (0..n) + .map(|i| dlog_proof_vec[i].pk.clone()) + .collect::>>(); let dlog_verification = Keys::verify_dlog_proofs_check_against_vss( ¶ms, @@ -254,11 +257,15 @@ fn keygen_t_n_parties( return Err(dlog_verification.err().unwrap()); } //test - let xi_vec = (0..=t).map(|i| shared_keys_vec[i].x_i).collect::>(); + let xi_vec = (0..=t) + .map(|i| shared_keys_vec[i].x_i.clone()) + .collect::>>(); let x = vss_scheme_for_test[0] .clone() .reconstruct(&index_vec[0..=t], &xi_vec); - let sum_u_i = party_keys_vec.iter().fold(FE::zero(), |acc, x| acc + x.u_i); + let sum_u_i = party_keys_vec + .iter() + .fold(Scalar::::zero(), |acc, x| acc + &x.u_i); assert_eq!(x, sum_u_i); Ok(( @@ -431,11 +438,10 @@ fn sign( .map(|j| { let ind1 = if j < i { j } else { j + 1 }; let ind2 = if j < i { i - 1 } else { i }; - let beta = beta_vec_all[ind1][ind2].clone(); - beta + beta_vec_all[ind1][ind2].clone() }) - .collect::>(); + .collect::>>(); // prepare ni_vec of party_i: let ni_vec = (0..ttag - 1) @@ -444,22 +450,18 @@ fn sign( let ind2 = if j < i { i - 1 } else { i }; ni_vec_all[ind1][ind2].clone() }) - .collect::>(); + .collect::>>(); let mut delta = sign_keys_vec[i].phase2_delta_i(&alpha_vec_all[i], &beta_vec); let mut sigma = sign_keys_vec[i].phase2_sigma_i(&miu_vec_all[i], &ni_vec); // test wrong delta corruption - if corrupt_step == 5 { - if corrupted_parties.iter().find(|&&x| x == i).is_some() { - delta = delta + δ - } + if corrupt_step == 5 && corrupted_parties.iter().any(|&x| x == i) { + delta = &delta + δ } // test wrong sigma corruption - if corrupt_step == 6 { - if corrupted_parties.iter().find(|&&x| x == i).is_some() { - sigma = sigma + σ - } + if corrupt_step == 6 && corrupted_parties.iter().any(|&x| x == i) { + sigma = &sigma + σ } delta_vec.push(delta); sigma_vec.push(sigma); @@ -490,17 +492,17 @@ fn sign( let m_b_gamma_vec = &m_b_gamma_vec_all[i]; let b_proof_vec = (0..ttag - 1) .map(|j| &m_b_gamma_vec[j].b_proof) - .collect::>>(); + .collect::>>(); SignKeys::phase4(&delta_inv, &b_proof_vec, decommit_vec1.clone(), &bc1_vec, i) .expect("") //TODO: propagate the error }) - .collect::>(); + .collect::>>(); //new phase 5 // all parties broadcast R_dash = k_i * R. let R_dash_vec = (0..ttag) - .map(|i| R_vec[i] * sign_keys_vec[i].k_i) - .collect::>(); + .map(|i| &R_vec[i] * &sign_keys_vec[i].k_i) + .collect::>>(); // each party sends first message to all other parties let mut phase5_proofs_vec: Vec> = vec![Vec::new(); ttag]; @@ -557,9 +559,9 @@ fn sign( } let local_state = LocalStatePhase5 { - k: sign_keys_vec[i].k_i, + k: sign_keys_vec[i].k_i.clone(), k_randomness: m_a_vec[i].1.clone(), - gamma: sign_keys_vec[i].gamma_i, + gamma: sign_keys_vec[i].gamma_i.clone(), beta_randomness: beta_randomness_vec_to_test, beta_tag: beta_tag_vec_to_test, encryption_key: ek_vec[s[i]].clone(), @@ -568,8 +570,8 @@ fn sign( } //g_gamma_vec: let g_gamma_vec = (0..decommit_vec1.len()) - .map(|i| decommit_vec1[i].g_gamma_i) - .collect::>(); + .map(|i| decommit_vec1[i].g_gamma_i.clone()) + .collect::>>(); //m_a_vec let m_a_vec = (0..m_a_vec.len()) .map(|i| m_a_vec[i].0.clone()) @@ -624,7 +626,7 @@ fn sign( } let proof = GlobalStatePhase6::ecddh_proof(&sigma_vec[i], &R_vec[i], &S_vec[i]); let local_state = LocalStatePhase6 { - k: sign_keys_vec[i].k_i, + k: sign_keys_vec[i].k_i.clone(), k_randomness: m_a_vec[i].1.clone(), miu: miu_bigint_vec_all[i].clone(), miu_randomness: miu_randomness_vec, @@ -655,7 +657,9 @@ fn sign( } let message: [u8; 4] = [79, 77, 69, 82]; - let message_bn = HSha256::create_hash(&[&BigInt::from_bytes(&message[..])]); + let message_bn = Sha256::new() + .chain_bigint(&BigInt::from_bytes(&message[..])) + .result_bigint(); let mut local_sig_vec = Vec::new(); let mut s_vec = Vec::new(); // each party computes s_i @@ -674,8 +678,8 @@ fn sign( // test corrupted local s if corrupt_step == 7 { for i in 0..s_vec.len() { - if corrupted_parties.iter().find(|&&x| x == i).is_some() { - s_vec[i] = s_vec[i] + &s_vec[i]; + if corrupted_parties.iter().any(|&x| x == i) { + s_vec[i] = &s_vec[i] + &s_vec[i]; } } } @@ -688,10 +692,10 @@ fn sign( if sig.is_err() { let global_state = GlobalStatePhase7 { s_vec, - r: local_sig_vec[0].r, + r: local_sig_vec[0].r.clone(), R_dash_vec, m: local_sig_vec[0].m.clone(), - R: local_sig_vec[0].R, + R: local_sig_vec[0].R.clone(), S_vec, }; global_state.phase7_blame()?; @@ -700,27 +704,32 @@ fn sign( let sig = sig.unwrap(); check_sig(&sig.r, &sig.s, &local_sig_vec[0].m, &y); - return Ok(sig); + Ok(sig) } -pub fn check_sig(r: &FE, s: &FE, msg: &BigInt, pk: &GE) { +pub fn check_sig( + r: &Scalar, + s: &Scalar, + msg: &BigInt, + pk: &Point, +) { use secp256k1::{verify, Message, PublicKey, PublicKeyFormat, Signature}; - let raw_msg = BigInt::to_bytes(&msg); + let raw_msg = BigInt::to_bytes(msg); let mut msg: Vec = Vec::new(); // padding msg.extend(vec![0u8; 32 - raw_msg.len()]); msg.extend(raw_msg.iter()); let msg = Message::parse_slice(msg.as_slice()).unwrap(); - let slice = pk.pk_to_key_slice(); + let slice = pk.to_bytes(false); let mut raw_pk = Vec::new(); if slice.len() != 65 { // after curv's pk_to_key_slice return 65 bytes, this can be removed raw_pk.insert(0, 4u8); raw_pk.extend(vec![0u8; 64 - slice.len()]); - raw_pk.extend(slice); + raw_pk.extend(slice.as_ref()); } else { - raw_pk.extend(slice); + raw_pk.extend(slice.as_ref()); } assert_eq!(raw_pk.len(), 65); @@ -728,11 +737,11 @@ pub fn check_sig(r: &FE, s: &FE, msg: &BigInt, pk: &GE) { let pk = PublicKey::parse_slice(&raw_pk, Some(PublicKeyFormat::Full)).unwrap(); let mut compact: Vec = Vec::new(); - let bytes_r = &r.get_element()[..]; + let bytes_r = &r.to_bytes()[..]; compact.extend(vec![0u8; 32 - bytes_r.len()]); compact.extend(bytes_r.iter()); - let bytes_s = &s.get_element()[..]; + let bytes_s = &s.to_bytes()[..]; compact.extend(vec![0u8; 32 - bytes_s.len()]); compact.extend(bytes_s.iter()); diff --git a/src/protocols/two_party_ecdsa/cclst_2019/party_one.rs b/src/protocols/two_party_ecdsa/cclst_2019/party_one.rs index 797fe4d6..7ee1d573 100644 --- a/src/protocols/two_party_ecdsa/cclst_2019/party_one.rs +++ b/src/protocols/two_party_ecdsa/cclst_2019/party_one.rs @@ -19,18 +19,17 @@ use class_group::primitives::cl_dl_public_setup::{ decrypt, verifiably_encrypt, CLDLProof, CLGroup, Ciphertext as CLCiphertext, PK, SK, }; -use curv::arithmetic::traits::*; +use curv::arithmetic::*; use curv::cryptographic_primitives::commitments::hash_commitment::HashCommitment; use curv::cryptographic_primitives::commitments::traits::Commitment; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_dlog::*; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::*; use curv::cryptographic_primitives::proofs::ProofError; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use serde::{Deserialize, Serialize}; +use sha2::Sha256; use subtle::ConstantTimeEq; use super::party_two::EphKeyGenFirstMsg as Party2EphKeyGenFirstMessage; @@ -41,16 +40,16 @@ use crate::Error::{self, InvalidSig}; //****************** Begin: Party One structs ******************// #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CommWitness { pub pk_commitment_blind_factor: BigInt, pub zk_pok_blind_factor: BigInt, - pub public_share: GE, - pub d_log_proof: DLogProof, + pub public_share: Point, + pub d_log_proof: DLogProof, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -95,7 +94,7 @@ pub struct Signature { #[derive(Serialize, Deserialize, Clone)] pub struct Party1Private { - x1: FE, + x1: Scalar, hsmcl_pub: PK, hsmcl_priv: SK, } @@ -107,7 +106,7 @@ pub struct PDLFirstMessage { #[derive(Debug, Serialize, Deserialize)] pub struct PDLdecommit { - pub q_hat: GE, + pub q_hat: Point, pub blindness: BigInt, } @@ -118,15 +117,15 @@ pub struct PDLSecondMessage { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EphEcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Debug, Serialize, Deserialize)] pub struct EphKeyGenFirstMsg { - pub d_log_proof: ECDDHProof, - pub public_share: GE, - pub c: GE, //c = secret_share * base_point2 + pub d_log_proof: ECDDHProof, + pub public_share: Point, + pub c: Point, //c = secret_share * base_point2 } #[derive(Debug, Serialize, Deserialize)] @@ -136,30 +135,30 @@ pub struct EphKeyGenSecondMsg {} impl KeyGenFirstMsg { pub fn create_commitments() -> (KeyGenFirstMsg, CommWitness, EcKeyPair) { - let base: GE = ECPoint::generator(); + let base = Point::generator(); - let secret_share: FE = ECScalar::new_random(); + let secret_share = Scalar::::random(); //in Lindell's protocol range proof works only for x1 = + Scalar::::from(&secret_share.to_bigint().div_floor(&BigInt::from(3))); - let public_share = base.scalar_mul(&secret_share.get_element()); + let public_share = base * &secret_share; let d_log_proof = DLogProof::prove(&secret_share); // we use hash based commitment let pk_commitment_blind_factor = BigInt::sample(SECURITY_BITS); - let pk_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &public_share.bytes_compressed_to_big_int(), - &pk_commitment_blind_factor, - ); + let pk_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(public_share.to_bytes(true).as_ref()), + &pk_commitment_blind_factor, + ); let zk_pok_blind_factor = BigInt::sample(SECURITY_BITS); - let zk_pok_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &d_log_proof - .pk_t_rand_commitment - .bytes_compressed_to_big_int(), - &zk_pok_blind_factor, - ); + let zk_pok_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(d_log_proof.pk_t_rand_commitment.to_bytes(true).as_ref()), + &zk_pok_blind_factor, + ); let ec_key_pair = EcKeyPair { public_share, secret_share, @@ -180,26 +179,26 @@ impl KeyGenFirstMsg { } pub fn create_commitments_with_fixed_secret_share( - secret_share: FE, + secret_share: Scalar, ) -> (KeyGenFirstMsg, CommWitness, EcKeyPair) { - let base: GE = ECPoint::generator(); - let public_share = base.scalar_mul(&secret_share.get_element()); + let base = Point::generator(); + let public_share = base * &secret_share; let d_log_proof = DLogProof::prove(&secret_share); let pk_commitment_blind_factor = BigInt::sample(SECURITY_BITS); - let pk_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &public_share.bytes_compressed_to_big_int(), - &pk_commitment_blind_factor, - ); + let pk_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(public_share.to_bytes(true).as_ref()), + &pk_commitment_blind_factor, + ); let zk_pok_blind_factor = BigInt::sample(SECURITY_BITS); - let zk_pok_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &d_log_proof - .pk_t_rand_commitment - .bytes_compressed_to_big_int(), - &zk_pok_blind_factor, - ); + let zk_pok_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(d_log_proof.pk_t_rand_commitment.to_bytes(true).as_ref()), + &zk_pok_blind_factor, + ); let ec_key_pair = EcKeyPair { public_share, @@ -224,14 +223,17 @@ impl KeyGenFirstMsg { impl KeyGenSecondMsg { pub fn verify_and_decommit( comm_witness: CommWitness, - proof: &DLogProof, + proof: &DLogProof, ) -> Result { DLogProof::verify(proof)?; Ok(KeyGenSecondMsg { comm_witness }) } } -pub fn compute_pubkey(party_one_private: &Party1Private, other_share_public_share: &GE) -> GE { +pub fn compute_pubkey( + party_one_private: &Party1Private, + other_share_public_share: &Point, +) -> Point { other_share_public_share * &party_one_private.x1 } @@ -250,7 +252,7 @@ impl HSMCL { keygen: &EcKeyPair, seed: &BigInt, ) -> (HSMCL, HSMCLPublic) { - let cl_group = CLGroup::new_from_setup(&1348, &seed); + let cl_group = CLGroup::new_from_setup(&1348, seed); let (secret_key, public_key) = cl_group.keygen(); let (ciphertext, proof) = verifiably_encrypt( &cl_group, @@ -262,13 +264,13 @@ impl HSMCL { HSMCL { cl_group: cl_group.clone(), public: public_key.clone(), - secret: secret_key.clone(), + secret: secret_key, encrypted_share: ciphertext.clone(), }, HSMCLPublic { - cl_pub_key: public_key.clone(), + cl_pub_key: public_key, proof, - encrypted_share: ciphertext.clone(), + encrypted_share: ciphertext, cl_group, }, ) @@ -277,16 +279,16 @@ impl HSMCL { impl EphKeyGenFirstMsg { pub fn create() -> (EphKeyGenFirstMsg, EphEcKeyPair) { - let base: GE = ECPoint::generator(); - let secret_share: FE = ECScalar::new_random(); - let public_share = &base * &secret_share; - let h: GE = GE::base_point2(); + let base = Point::generator(); + let secret_share = Scalar::::random(); + let public_share = base * &secret_share; + let h = Point::::base_point2(); let w = ECDDHWitness { x: secret_share.clone(), }; - let c = &h * &secret_share; + let c = h * &secret_share; let delta = ECDDHStatement { - g1: base.clone(), + g1: base.to_point(), h1: public_share.clone(), g2: h.clone(), h2: c.clone(), @@ -322,31 +324,31 @@ impl EphKeyGenSecondMsg { .pk_commitment_blind_factor; let party_two_d_log_proof = &party_two_second_message.comm_witness.d_log_proof; let mut flag = true; - match party_two_pk_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &party_two_public_share.bytes_compressed_to_big_int(), - &party_two_pk_commitment_blind_factor, - ) { - false => flag = false, - true => flag = flag, - }; - match party_two_zk_pok_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &HSha256::create_hash_from_ge(&[ - &party_two_d_log_proof.a1, - &party_two_d_log_proof.a2, - ]) - .to_big_int(), - &party_two_zk_pok_blind_factor, - ) { - false => flag = false, - true => flag = flag, - }; - assert!(flag); + if party_two_pk_commitment + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(party_two_public_share.to_bytes(true).as_ref()), + party_two_pk_commitment_blind_factor, + ) + { + flag = false + } + if party_two_zk_pok_commitment + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &Sha256::new() + .chain_points([&party_two_d_log_proof.a1, &party_two_d_log_proof.a2]) + .result_bigint(), + party_two_zk_pok_blind_factor, + ) + { + flag = false + } + if !flag { + return Err(ProofError); + } let delta = ECDDHStatement { - g1: GE::generator(), + g1: Point::generator().to_point(), h1: party_two_public_share.clone(), - g2: GE::base_point2(), + g2: Point::::base_point2().clone(), h2: party_two_second_message.comm_witness.c.clone(), }; party_two_d_log_proof.verify(&delta)?; @@ -360,44 +362,55 @@ impl Signature { party_one_private: &Party1Private, partial_sig_c3: CLCiphertext, ephemeral_local_share: &EphEcKeyPair, - ephemeral_other_public_share: &GE, + ephemeral_other_public_share: &Point, ) -> Signature { //compute r = k2* R1 - let mut r = ephemeral_other_public_share.clone(); - r = r.scalar_mul(&ephemeral_local_share.secret_share.get_element()); - - let rx = r.x_coor().unwrap().mod_floor(&FE::q()); - let k1_inv = &ephemeral_local_share - .secret_share - .to_big_int() - .invert(&FE::q()) - .unwrap(); + let r = ephemeral_other_public_share * &ephemeral_local_share.secret_share; + + let rx = r + .x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()); + let k1 = &ephemeral_local_share.secret_share.to_bigint(); + let k1_inv = BigInt::mod_inv(k1, Scalar::::group_order()).unwrap(); let s_tag = decrypt( &hsmcl.cl_group, &party_one_private.hsmcl_priv, &partial_sig_c3, ); - let s_tag_tag = BigInt::mod_mul(&k1_inv, &s_tag.to_big_int(), &FE::q()); - let s = cmp::min(s_tag_tag.clone(), FE::q().clone() - s_tag_tag.clone()); + let s_tag_tag = BigInt::mod_mul( + &k1_inv, + &s_tag.to_bigint(), + Scalar::::group_order(), + ); + let s = cmp::min( + s_tag_tag.clone(), + Scalar::::group_order().clone() - s_tag_tag, + ); Signature { s, r: rx } } } -pub fn verify(signature: &Signature, pubkey: &GE, message: &BigInt) -> Result<(), Error> { - let s_fe: FE = ECScalar::from(&signature.s); - let rx_fe: FE = ECScalar::from(&signature.r); +pub fn verify( + signature: &Signature, + pubkey: &Point, + message: &BigInt, +) -> Result<(), Error> { + let s_fe = Scalar::::from(&signature.s); + let rx_fe = Scalar::::from(&signature.r); - let s_inv_fe = s_fe.invert(); - let e_fe: FE = ECScalar::from(&message.mod_floor(&FE::q())); - let u1 = GE::generator() * e_fe * s_inv_fe; - let u2 = *pubkey * rx_fe * s_inv_fe; + let s_inv_fe = s_fe.invert().ok_or(Error::InvalidSig)?; + let e_fe: Scalar = + Scalar::::from(&message.mod_floor(Scalar::::group_order())); + let u1 = Point::generator() * e_fe * &s_inv_fe; + let u2 = pubkey * rx_fe * &s_inv_fe; // second condition is against malleability let rx_bytes = &BigInt::to_bytes(&signature.r)[..]; - let u1_plus_u2_bytes = &BigInt::to_bytes(&(u1 + u2).x_coor().unwrap())[..]; + let u1_plus_u2_bytes = &BigInt::to_bytes(&(u1 + u2).x_coord().unwrap())[..]; - if rx_bytes.ct_eq(&u1_plus_u2_bytes).unwrap_u8() == 1 - && signature.s < FE::q() - signature.s.clone() + if rx_bytes.ct_eq(u1_plus_u2_bytes).unwrap_u8() == 1 + && signature.s < Scalar::::group_order() - signature.s.clone() { Ok(()) } else { diff --git a/src/protocols/two_party_ecdsa/cclst_2019/party_two.rs b/src/protocols/two_party_ecdsa/cclst_2019/party_two.rs index aa282654..55f2aeef 100644 --- a/src/protocols/two_party_ecdsa/cclst_2019/party_two.rs +++ b/src/protocols/two_party_ecdsa/cclst_2019/party_two.rs @@ -21,15 +21,14 @@ use class_group::primitives::cl_dl_public_setup::{ use curv::arithmetic::traits::*; use curv::cryptographic_primitives::commitments::hash_commitment::HashCommitment; use curv::cryptographic_primitives::commitments::traits::Commitment; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_dlog::*; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::*; use curv::cryptographic_primitives::proofs::ProofError; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use serde::{Deserialize, Serialize}; +use sha2::Sha256; use super::party_one::EphKeyGenFirstMsg as Party1EphKeyGenFirstMsg; use super::party_one::KeyGenFirstMsg as Party1KeyGenFirstMessage; @@ -40,14 +39,14 @@ use super::SECURITY_BITS; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyGenFirstMsg { - pub d_log_proof: DLogProof, - pub public_share: GE, + pub d_log_proof: DLogProof, + pub public_share: Point, } #[derive(Debug, Serialize, Deserialize)] @@ -67,7 +66,7 @@ pub struct PartialSig { #[derive(Serialize, Deserialize)] pub struct Party2Private { - x2: FE, + x2: Scalar, } #[derive(Debug)] pub struct PDLchallenge { @@ -76,7 +75,7 @@ pub struct PDLchallenge { a: BigInt, b: BigInt, blindness: BigInt, - q_tag: GE, + q_tag: Point, } #[derive(Debug, Serialize, Deserialize)] @@ -98,17 +97,17 @@ pub struct PDLSecondMessage { } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EphEcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EphCommWitness { pub pk_commitment_blind_factor: BigInt, pub zk_pok_blind_factor: BigInt, - pub public_share: GE, - pub d_log_proof: ECDDHProof, - pub c: GE, //c = secret_share * base_point2 + pub public_share: Point, + pub d_log_proof: ECDDHProof, + pub c: Point, //c = secret_share * base_point2 } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -126,8 +125,8 @@ pub struct EphKeyGenSecondMsg { impl KeyGenFirstMsg { pub fn create() -> (KeyGenFirstMsg, EcKeyPair) { - let base: GE = ECPoint::generator(); - let secret_share: FE = ECScalar::new_random(); + let base = Point::generator(); + let secret_share = Scalar::::random(); let public_share = base * &secret_share; let d_log_proof = DLogProof::prove(&secret_share); let ec_key_pair = EcKeyPair { @@ -143,8 +142,10 @@ impl KeyGenFirstMsg { ) } - pub fn create_with_fixed_secret_share(secret_share: FE) -> (KeyGenFirstMsg, EcKeyPair) { - let base: GE = ECPoint::generator(); + pub fn create_with_fixed_secret_share( + secret_share: Scalar, + ) -> (KeyGenFirstMsg, EcKeyPair) { + let base = Point::generator(); let public_share = base * &secret_share; let d_log_proof = DLogProof::prove(&secret_share); let ec_key_pair = EcKeyPair { @@ -177,33 +178,42 @@ impl KeyGenSecondMsg { let party_one_d_log_proof = &party_one_second_message.comm_witness.d_log_proof; let mut flag = true; - match party_one_pk_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &party_one_public_share.bytes_compressed_to_big_int(), - &party_one_pk_commitment_blind_factor, - ) { - false => flag = false, - true => flag = flag, - }; - match party_one_zk_pok_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &party_one_d_log_proof - .pk_t_rand_commitment - .bytes_compressed_to_big_int(), - &party_one_zk_pok_blind_factor, - ) { - false => flag = false, - true => flag = flag, - }; - assert!(flag); - DLogProof::verify(&party_one_d_log_proof)?; + if party_one_pk_commitment + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(party_one_public_share.to_bytes(true).as_ref()), + party_one_pk_commitment_blind_factor, + ) + { + flag = false + } + if party_one_zk_pok_commitment + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes( + party_one_d_log_proof + .pk_t_rand_commitment + .to_bytes(true) + .as_ref(), + ), + party_one_zk_pok_blind_factor, + ) + { + flag = false + } + + if !flag { + return Err(ProofError); + } + + DLogProof::verify(party_one_d_log_proof)?; Ok(KeyGenSecondMsg {}) } } -pub fn compute_pubkey(local_share: &EcKeyPair, other_share_public_share: &GE) -> GE { - let pubkey = other_share_public_share.clone(); - pubkey.scalar_mul(&local_share.secret_share.get_element()) +pub fn compute_pubkey( + local_share: &EcKeyPair, + other_share_public_share: &Point, +) -> Point { + other_share_public_share * &local_share.secret_share } impl Party2Private { @@ -218,8 +228,8 @@ impl Party2Public { pub fn verify_setup_and_zkcldl_proof( hsmcl_public: &HSMCLPublic, seed: &BigInt, - party1_ec_pubkey: &GE, - ) -> Result { + party1_ec_pubkey: &Point, + ) -> Result { let setup_verify = hsmcl_public.cl_group.setup_verify(seed); let proof_verify = hsmcl_public.proof.verify( @@ -228,32 +238,33 @@ impl Party2Public { &hsmcl_public.encrypted_share, party1_ec_pubkey, ); - match proof_verify.is_ok() && setup_verify.is_ok() { - true => Ok(Party2Public { + if proof_verify.is_ok() && setup_verify.is_ok() { + Ok(Party2Public { group: hsmcl_public.cl_group.clone(), ek: hsmcl_public.cl_pub_key.clone(), encrypted_secret_share: hsmcl_public.encrypted_share.clone(), - }), - false => Err(()), + }) + } else { + Err(ProofError) } } } impl EphKeyGenFirstMsg { pub fn create_commitments() -> (EphKeyGenFirstMsg, EphCommWitness, EphEcKeyPair) { - let base: GE = ECPoint::generator(); + let base = Point::generator(); - let secret_share: FE = ECScalar::new_random(); + let secret_share = Scalar::::random(); - let public_share = base.scalar_mul(&secret_share.get_element()); + let public_share = base * &secret_share; - let h: GE = GE::base_point2(); + let h = Point::base_point2(); let w = ECDDHWitness { x: secret_share.clone(), }; - let c = &h * &secret_share; + let c = h * &secret_share; let delta = ECDDHStatement { - g1: base.clone(), + g1: base.to_point(), h1: public_share.clone(), g2: h.clone(), h2: c.clone(), @@ -262,16 +273,20 @@ impl EphKeyGenFirstMsg { // we use hash based commitment let pk_commitment_blind_factor = BigInt::sample(SECURITY_BITS); - let pk_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &public_share.bytes_compressed_to_big_int(), - &pk_commitment_blind_factor, - ); + let pk_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(public_share.to_bytes(true).as_ref()), + &pk_commitment_blind_factor, + ); let zk_pok_blind_factor = BigInt::sample(SECURITY_BITS); - let zk_pok_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &HSha256::create_hash_from_ge(&[&d_log_proof.a1, &d_log_proof.a2]).to_big_int(), - &zk_pok_blind_factor, - ); + let zk_pok_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &Sha256::new() + .chain_points([&d_log_proof.a1, &d_log_proof.a2]) + .result_bigint(), + &zk_pok_blind_factor, + ); let ec_key_pair = EphEcKeyPair { public_share, @@ -300,9 +315,9 @@ impl EphKeyGenSecondMsg { party_one_first_message: &Party1EphKeyGenFirstMsg, ) -> Result { let delta = ECDDHStatement { - g1: GE::generator(), + g1: Point::generator().to_point(), h1: party_one_first_message.public_share.clone(), - g2: GE::base_point2(), + g2: Point::::base_point2().clone(), h2: party_one_first_message.c.clone(), }; party_one_first_message.d_log_proof.verify(&delta)?; @@ -315,25 +330,22 @@ impl PartialSig { party_two_public: Party2Public, local_share: &Party2Private, ephemeral_local_share: &EphEcKeyPair, - ephemeral_other_public_share: &GE, + ephemeral_other_public_share: &Point, message: &BigInt, ) -> PartialSig { - let q = FE::q(); + let q = Scalar::::group_order(); //compute r = k2* R1 - let mut r: GE = ephemeral_other_public_share.clone(); - r = r.scalar_mul(&ephemeral_local_share.secret_share.get_element()); - - let rx = r.x_coor().unwrap().mod_floor(&q); - let k2_inv = &ephemeral_local_share - .secret_share - .to_big_int() - .invert(&q) - .unwrap(); - let k2_inv_m = BigInt::mod_mul(&k2_inv, message, &q); - let k2_inv_m_fe: FE = ECScalar::from(&k2_inv_m); + let r: Point = + ephemeral_other_public_share * &ephemeral_local_share.secret_share; + + let rx = r.x_coord().unwrap().mod_floor(q); + let k2 = &ephemeral_local_share.secret_share.to_bigint(); + let k2_inv = BigInt::mod_inv(k2, q).unwrap(); + let k2_inv_m = BigInt::mod_mul(&k2_inv, message, q); + let k2_inv_m_fe = Scalar::::from(&k2_inv_m); let c1 = encrypt(&party_two_public.group, &party_two_public.ek, &k2_inv_m_fe); - let v = BigInt::mod_mul(&k2_inv, &local_share.x2.to_big_int(), &q); - let v = BigInt::mod_mul(&v, &rx, &q); + let v = BigInt::mod_mul(&k2_inv, &local_share.x2.to_bigint(), q); + let v = BigInt::mod_mul(&v, &rx, q); let c2 = eval_scal(&party_two_public.encrypted_secret_share, &v); let c3 = eval_sum(&c1.0, &c2); diff --git a/src/protocols/two_party_ecdsa/cclst_2019/test.rs b/src/protocols/two_party_ecdsa/cclst_2019/test.rs index 876a4992..87aad0d0 100644 --- a/src/protocols/two_party_ecdsa/cclst_2019/test.rs +++ b/src/protocols/two_party_ecdsa/cclst_2019/test.rs @@ -1,7 +1,8 @@ // For integration tests, please add your tests in /tests instead use super::*; -use curv::elliptic::curves::traits::*; +use curv::arithmetic::Converter; +use curv::elliptic::curves::*; use curv::BigInt; #[test] @@ -26,12 +27,12 @@ fn test_d_log_proof_party_two_party_one() { fn test_full_key_gen() { let (party_one_first_message, comm_witness, ec_key_pair_party1) = party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share( - ECScalar::new_random(), + Scalar::::random(), ); let (party_two_first_message, _ec_key_pair_party2) = - party_two::KeyGenFirstMsg::create_with_fixed_secret_share(ECScalar::from(&BigInt::from( - 10, - ))); + party_two::KeyGenFirstMsg::create_with_fixed_secret_share(Scalar::::from( + &BigInt::from(10), + )); let party_one_second_message = party_one::KeyGenSecondMsg::verify_and_decommit( comm_witness, &party_two_first_message.d_log_proof, @@ -45,9 +46,10 @@ fn test_full_key_gen() { .expect("failed to verify commitments and DLog proof"); // init HSMCL keypair: - let seed: BigInt = str::parse( - "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848" - ).unwrap(); + let seed: BigInt = BigInt::from_str_radix( + "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848", + 10, + ).unwrap(); let (hsmcl, hsmcl_public) = party_one::HSMCL::generate_keypair_and_encrypted_share_and_proof( &ec_key_pair_party1, &seed, @@ -75,8 +77,9 @@ fn test_two_party_sign() { let (party_two_private_share_gen, ec_key_pair_party2) = party_two::KeyGenFirstMsg::create(); //pi (nothing up my sleeve) - let seed: BigInt = str::parse( - "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848" + let seed: BigInt = BigInt::from_str_radix( + "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848", + 10, ).unwrap(); let (party_one_hsmcl, hsmcl_public) = diff --git a/src/protocols/two_party_ecdsa/lindell_2017/party_one.rs b/src/protocols/two_party_ecdsa/lindell_2017/party_one.rs index 00d5065d..072d32f1 100644 --- a/src/protocols/two_party_ecdsa/lindell_2017/party_one.rs +++ b/src/protocols/two_party_ecdsa/lindell_2017/party_one.rs @@ -20,21 +20,19 @@ use centipede::juggling::segmentation::Msegmentation; use curv::arithmetic::traits::*; use curv::cryptographic_primitives::commitments::hash_commitment::HashCommitment; use curv::cryptographic_primitives::commitments::traits::Commitment; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_dlog::*; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::*; use curv::cryptographic_primitives::proofs::ProofError; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::Paillier; use paillier::{Decrypt, EncryptWithChosenRandomness, KeyGeneration}; use paillier::{DecryptionKey, EncryptionKey, Randomness, RawCiphertext, RawPlaintext}; use serde::{Deserialize, Serialize}; +use sha2::Sha256; use subtle::ConstantTimeEq; -use zeroize::Zeroize; -use zk_paillier::zkproofs::NICorrectKeyProof; +use zk_paillier::zkproofs::NiCorrectKeyProof; use super::party_two::EphKeyGenFirstMsg as Party2EphKeyGenFirstMessage; use super::party_two::EphKeyGenSecondMsg as Party2EphKeyGenSecondMessage; @@ -51,16 +49,16 @@ use zk_paillier::zkproofs::{CompositeDLogProof, DLogStatement}; //****************** Begin: Party One structs ******************// #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CommWitness { pub pk_commitment_blind_factor: BigInt, pub zk_pok_blind_factor: BigInt, - pub public_share: GE, - pub d_log_proof: DLogProof, + pub public_share: Point, + pub d_log_proof: DLogProof, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -97,7 +95,7 @@ pub struct Signature { #[derive(Serialize, Deserialize, Clone)] pub struct Party1Private { - x1: FE, + x1: Scalar, paillier_priv: DecryptionKey, c_key_randomness: BigInt, } @@ -109,7 +107,7 @@ pub struct PDLFirstMessage { #[derive(Debug, Serialize, Deserialize)] pub struct PDLdecommit { - pub q_hat: GE, + pub q_hat: Point, pub blindness: BigInt, } @@ -120,15 +118,15 @@ pub struct PDLSecondMessage { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EphEcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Debug, Serialize, Deserialize)] pub struct EphKeyGenFirstMsg { - pub d_log_proof: ECDDHProof, - pub public_share: GE, - pub c: GE, //c = secret_share * base_point2 + pub d_log_proof: ECDDHProof, + pub public_share: Point, + pub c: Point, //c = secret_share * base_point2 } #[derive(Debug, Serialize, Deserialize)] @@ -138,32 +136,31 @@ pub struct EphKeyGenSecondMsg {} impl KeyGenFirstMsg { pub fn create_commitments() -> (KeyGenFirstMsg, CommWitness, EcKeyPair) { - let base: GE = ECPoint::generator(); + let base = Point::generator(); - let mut secret_share: FE = ECScalar::new_random(); + let secret_share = Scalar::::random(); - let public_share = base.scalar_mul(&secret_share.get_element()); + let public_share = base * &secret_share; - let d_log_proof = DLogProof::::prove(&secret_share); + let d_log_proof = DLogProof::::prove(&secret_share); // we use hash based commitment let pk_commitment_blind_factor = BigInt::sample(SECURITY_BITS); - let pk_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &public_share.bytes_compressed_to_big_int(), - &pk_commitment_blind_factor, - ); + let pk_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(public_share.to_bytes(true).as_ref()), + &pk_commitment_blind_factor, + ); let zk_pok_blind_factor = BigInt::sample(SECURITY_BITS); - let zk_pok_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &d_log_proof - .pk_t_rand_commitment - .bytes_compressed_to_big_int(), - &zk_pok_blind_factor, - ); + let zk_pok_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(d_log_proof.pk_t_rand_commitment.to_bytes(true).as_ref()), + &zk_pok_blind_factor, + ); let ec_key_pair = EcKeyPair { public_share, secret_share, }; - secret_share.zeroize(); ( KeyGenFirstMsg { pk_commitment, @@ -172,7 +169,7 @@ impl KeyGenFirstMsg { CommWitness { pk_commitment_blind_factor, zk_pok_blind_factor, - public_share: ec_key_pair.public_share, + public_share: ec_key_pair.public_share.clone(), d_log_proof, }, ec_key_pair, @@ -180,32 +177,31 @@ impl KeyGenFirstMsg { } pub fn create_commitments_with_fixed_secret_share( - mut secret_share: FE, + secret_share: Scalar, ) -> (KeyGenFirstMsg, CommWitness, EcKeyPair) { - let base: GE = ECPoint::generator(); - let public_share = base.scalar_mul(&secret_share.get_element()); + let base = Point::generator(); + let public_share = base * &secret_share; - let d_log_proof = DLogProof::::prove(&secret_share); + let d_log_proof = DLogProof::::prove(&secret_share); let pk_commitment_blind_factor = BigInt::sample(SECURITY_BITS); - let pk_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &public_share.bytes_compressed_to_big_int(), - &pk_commitment_blind_factor, - ); + let pk_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(public_share.to_bytes(true).as_ref()), + &pk_commitment_blind_factor, + ); let zk_pok_blind_factor = BigInt::sample(SECURITY_BITS); - let zk_pok_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &d_log_proof - .pk_t_rand_commitment - .bytes_compressed_to_big_int(), - &zk_pok_blind_factor, - ); + let zk_pok_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(d_log_proof.pk_t_rand_commitment.to_bytes(true).as_ref()), + &zk_pok_blind_factor, + ); let ec_key_pair = EcKeyPair { public_share, secret_share, }; - secret_share.zeroize(); ( KeyGenFirstMsg { pk_commitment, @@ -214,7 +210,7 @@ impl KeyGenFirstMsg { CommWitness { pk_commitment_blind_factor, zk_pok_blind_factor, - public_share: ec_key_pair.public_share, + public_share: ec_key_pair.public_share.clone(), d_log_proof, }, ec_key_pair, @@ -225,21 +221,24 @@ impl KeyGenFirstMsg { impl KeyGenSecondMsg { pub fn verify_and_decommit( comm_witness: CommWitness, - proof: &DLogProof, + proof: &DLogProof, ) -> Result { DLogProof::verify(proof)?; Ok(KeyGenSecondMsg { comm_witness }) } } -pub fn compute_pubkey(party_one_private: &Party1Private, other_share_public_share: &GE) -> GE { +pub fn compute_pubkey( + party_one_private: &Party1Private, + other_share_public_share: &Point, +) -> Point { other_share_public_share * &party_one_private.x1 } impl Party1Private { pub fn set_private_key(ec_key: &EcKeyPair, paillier_key: &PaillierKeyPair) -> Party1Private { Party1Private { - x1: ec_key.secret_share, + x1: ec_key.secret_share.clone(), paillier_priv: paillier_key.dk.clone(), c_key_randomness: paillier_key.randomness.clone(), } @@ -251,23 +250,23 @@ impl Party1Private { EncryptionKey, BigInt, Party1Private, - NICorrectKeyProof, + NiCorrectKeyProof, PDLwSlackStatement, PDLwSlackProof, CompositeDLogProof, ) { let (ek_new, dk_new) = Paillier::keypair().keys(); let randomness = Randomness::sample(&ek_new); - let factor_fe: FE = ECScalar::from(&factor); - let x1_new = party_one_private.x1 * factor_fe; + let factor_fe = Scalar::::from(&*factor); + let x1_new = &party_one_private.x1 * factor_fe; let c_key_new = Paillier::encrypt_with_chosen_randomness( &ek_new, - RawPlaintext::from(x1_new.to_big_int().clone()), + RawPlaintext::from(x1_new.to_bigint()), &randomness, ) .0 .into_owned(); - let correct_key_proof_new = NICorrectKeyProof::proof(&dk_new, None); + let correct_key_proof_new = NiCorrectKeyProof::proof(&dk_new, None); let paillier_key_pair = PaillierKeyPair { ek: ek_new.clone(), @@ -278,7 +277,7 @@ impl Party1Private { let party_one_private_new = Party1Private { x1: x1_new, - paillier_priv: dk_new.clone(), + paillier_priv: dk_new, c_key_randomness: randomness.0, }; @@ -301,14 +300,17 @@ impl Party1Private { &self, segment_size: usize, num_of_segments: usize, - pub_ke_y: &GE, - g: &GE, + pub_ke_y: &Point, + g: &Point, ) -> (Witness, Helgamalsegmented) { Msegmentation::to_encrypted_segments(&self.x1, &segment_size, num_of_segments, pub_ke_y, g) } // used to transform lindell master key to gg18 master key - pub fn to_mta_message_b(&self, message_b: MessageB) -> Result<(FE, BigInt), Error> { + pub fn to_mta_message_b( + &self, + message_b: MessageB, + ) -> Result<(Scalar, BigInt), Error> { message_b.verify_proofs_get_alpha(&self.paillier_priv, &self.x1) } } @@ -320,7 +322,7 @@ impl PaillierKeyPair { let encrypted_share = Paillier::encrypt_with_chosen_randomness( &ek, - RawPlaintext::from(keygen.secret_share.to_big_int()), + RawPlaintext::from(keygen.secret_share.to_bigint()), &randomness, ) .0 @@ -343,7 +345,7 @@ impl PaillierKeyPair { let encrypted_share = Paillier::encrypt_with_chosen_randomness( ek, - RawPlaintext::from(keygen.secret_share.to_big_int()), + RawPlaintext::from(keygen.secret_share.to_bigint()), &randomness, ) .0 @@ -357,8 +359,8 @@ impl PaillierKeyPair { } } - pub fn generate_ni_proof_correct_key(paillier_context: &PaillierKeyPair) -> NICorrectKeyProof { - NICorrectKeyProof::proof(&paillier_context.dk, None) + pub fn generate_ni_proof_correct_key(paillier_context: &PaillierKeyPair) -> NiCorrectKeyProof { + NiCorrectKeyProof::proof(&paillier_context.dk, None) } pub fn pdl_proof( @@ -377,11 +379,11 @@ impl PaillierKeyPair { let pdl_w_slack_statement = PDLwSlackStatement { ciphertext: paillier_key_pair.encrypted_share.clone(), ek: paillier_key_pair.ek.clone(), - Q: GE::generator() * &party1_private.x1, - G: GE::generator(), + Q: Point::generator() * &party1_private.x1, + G: Point::generator().to_point(), h1: dlog_statement.g.clone(), h2: dlog_statement.ni.clone(), - N_tilde: dlog_statement.N.clone(), + N_tilde: dlog_statement.N, }; let pdl_w_slack_witness = PDLwSlackWitness { @@ -400,27 +402,26 @@ impl PaillierKeyPair { impl EphKeyGenFirstMsg { pub fn create() -> (EphKeyGenFirstMsg, EphEcKeyPair) { - let base: GE = ECPoint::generator(); - let mut secret_share: FE = ECScalar::new_random(); - let public_share = &base * &secret_share; - let h: GE = GE::base_point2(); - - let c = &h * &secret_share; - let mut x = secret_share; - let w = ECDDHWitness { x }; + let base = Point::generator(); + let secret_share = Scalar::::random(); + let public_share = &*base * &secret_share; + let h = Point::::base_point2(); + + let c = h * &secret_share; + let w = ECDDHWitness { + x: secret_share.clone(), + }; let delta = ECDDHStatement { - g1: base, - h1: public_share, - g2: h, - h2: c, + g1: base.to_point(), + h1: public_share.clone(), + g2: h.clone(), + h2: c.clone(), }; let d_log_proof = ECDDHProof::prove(&w, &delta); let ec_key_pair = EphEcKeyPair { - public_share, + public_share: public_share.clone(), secret_share, }; - secret_share.zeroize(); - x.zeroize(); ( EphKeyGenFirstMsg { d_log_proof, @@ -448,35 +449,33 @@ impl EphKeyGenSecondMsg { let party_two_d_log_proof = &party_two_second_message.comm_witness.d_log_proof; let mut flag = true; if party_two_pk_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &party_two_public_share.bytes_compressed_to_big_int(), - &party_two_pk_commitment_blind_factor, + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(party_two_public_share.to_bytes(true).as_ref()), + party_two_pk_commitment_blind_factor, ) { - flag = flag - } else { flag = false - }; + } if party_two_zk_pok_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &HSha256::create_hash_from_ge(&[ - &party_two_d_log_proof.a1, - &party_two_d_log_proof.a2, - ]) - .to_big_int(), - &party_two_zk_pok_blind_factor, + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &Sha256::new() + .chain_points([&party_two_d_log_proof.a1, &party_two_d_log_proof.a2]) + .result_bigint(), + party_two_zk_pok_blind_factor, ) { - flag = flag - } else { flag = false - }; - assert!(flag); + } + + if !flag { + return Err(ProofError); + } + let delta = ECDDHStatement { - g1: GE::generator(), - h1: *party_two_public_share, - g2: GE::base_point2(), - h2: party_two_second_message.comm_witness.c, + g1: Point::generator().to_point(), + h1: party_two_public_share.clone(), + g2: Point::::base_point2().clone(), + h2: party_two_second_message.comm_witness.c.clone(), }; party_two_d_log_proof.verify(&delta)?; Ok(EphKeyGenSecondMsg {}) @@ -488,28 +487,31 @@ impl Signature { party_one_private: &Party1Private, partial_sig_c3: &BigInt, ephemeral_local_share: &EphEcKeyPair, - ephemeral_other_public_share: &GE, + ephemeral_other_public_share: &Point, ) -> Signature { //compute r = k2* R1 - let r = ephemeral_other_public_share - .scalar_mul(&ephemeral_local_share.secret_share.get_element()); + let r = ephemeral_other_public_share * &ephemeral_local_share.secret_share; - let rx = r.x_coor().unwrap().mod_floor(&FE::q()); + let rx = r + .x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()); - let mut k1_inv = ephemeral_local_share.secret_share.invert(); + let k1_inv = ephemeral_local_share.secret_share.invert().unwrap(); let s_tag = Paillier::decrypt( &party_one_private.paillier_priv, &RawCiphertext::from(partial_sig_c3), ) .0; - let mut s_tag_fe: FE = ECScalar::from(&s_tag); + let s_tag_fe = Scalar::::from(s_tag.as_ref()); let s_tag_tag = s_tag_fe * k1_inv; - k1_inv.zeroize(); - s_tag_fe.zeroize(); - let s_tag_tag_bn = s_tag_tag.to_big_int(); + let s_tag_tag_bn = s_tag_tag.to_bigint(); - let s = cmp::min(s_tag_tag_bn.clone(), FE::q().clone() - s_tag_tag_bn.clone()); + let s = cmp::min( + s_tag_tag_bn.clone(), + Scalar::::group_order().clone() - s_tag_tag_bn, + ); Signature { s, r: rx } } @@ -518,27 +520,33 @@ impl Signature { party_one_private: &Party1Private, partial_sig_c3: &BigInt, ephemeral_local_share: &EphEcKeyPair, - ephemeral_other_public_share: &GE, + ephemeral_other_public_share: &Point, ) -> SignatureRecid { //compute r = k2* R1 - let r = ephemeral_other_public_share - .scalar_mul(&ephemeral_local_share.secret_share.get_element()); - - let rx = r.x_coor().unwrap().mod_floor(&FE::q()); - let ry = r.y_coor().unwrap().mod_floor(&FE::q()); - let mut k1_inv = ephemeral_local_share.secret_share.invert(); + let r = ephemeral_other_public_share * &ephemeral_local_share.secret_share; + + let rx = r + .x_coord() + .unwrap() + .mod_floor(Scalar::::group_order()); + let ry = r + .y_coord() + .unwrap() + .mod_floor(Scalar::::group_order()); + let k1_inv = ephemeral_local_share.secret_share.invert().unwrap(); let s_tag = Paillier::decrypt( &party_one_private.paillier_priv, &RawCiphertext::from(partial_sig_c3), ) .0; - let mut s_tag_fe: FE = ECScalar::from(&s_tag); + let s_tag_fe = Scalar::::from(s_tag.as_ref()); let s_tag_tag = s_tag_fe * k1_inv; - k1_inv.zeroize(); - s_tag_fe.zeroize(); - let s_tag_tag_bn = s_tag_tag.to_big_int(); - let s = cmp::min(s_tag_tag_bn.clone(), FE::q() - &s_tag_tag_bn); + let s_tag_tag_bn = s_tag_tag.to_bigint(); + let s = cmp::min( + s_tag_tag_bn.clone(), + Scalar::::group_order() - &s_tag_tag_bn, + ); /* Calculate recovery id - it is not possible to compute the public key out of the signature @@ -548,29 +556,34 @@ impl Signature { */ let is_ry_odd = ry.test_bit(0); let mut recid = if is_ry_odd { 1 } else { 0 }; - if s_tag_tag_bn.clone() > FE::q() - s_tag_tag_bn.clone() { - recid = recid ^ 1; + if s_tag_tag_bn > Scalar::::group_order() - &s_tag_tag_bn { + recid ^= 1; } SignatureRecid { s, r: rx, recid } } } -pub fn verify(signature: &Signature, pubkey: &GE, message: &BigInt) -> Result<(), Error> { - let s_fe: FE = ECScalar::from(&signature.s); - let rx_fe: FE = ECScalar::from(&signature.r); +pub fn verify( + signature: &Signature, + pubkey: &Point, + message: &BigInt, +) -> Result<(), Error> { + let s_fe = Scalar::::from(&signature.s); + let rx_fe = Scalar::::from(&signature.r); - let s_inv_fe = s_fe.invert(); - let e_fe: FE = ECScalar::from(&message.mod_floor(&FE::q())); - let u1 = GE::generator() * e_fe * s_inv_fe; - let u2 = *pubkey * rx_fe * s_inv_fe; + let s_inv_fe = s_fe.invert().unwrap(); + let e_fe: Scalar = + Scalar::::from(&message.mod_floor(Scalar::::group_order())); + let u1 = Point::generator() * e_fe * &s_inv_fe; + let u2 = &*pubkey * rx_fe * &s_inv_fe; // second condition is against malleability let rx_bytes = &BigInt::to_bytes(&signature.r)[..]; - let u1_plus_u2_bytes = &BigInt::to_bytes(&(u1 + u2).x_coor().unwrap())[..]; + let u1_plus_u2_bytes = &BigInt::to_bytes(&(u1 + u2).x_coord().unwrap())[..]; - if rx_bytes.ct_eq(&u1_plus_u2_bytes).unwrap_u8() == 1 - && signature.s < FE::q() - signature.s.clone() + if rx_bytes.ct_eq(u1_plus_u2_bytes).unwrap_u8() == 1 + && signature.s < Scalar::::group_order() - signature.s.clone() { Ok(()) } else { @@ -585,7 +598,7 @@ pub fn generate_h1_h2_n_tilde() -> (BigInt, BigInt, BigInt, BigInt) { let one = BigInt::one(); let phi = (&dk_tilde.p - &one) * (&dk_tilde.q - &one); let h1 = BigInt::sample_below(&phi); - let s = BigInt::from(2).pow(256 as u32); + let s = BigInt::from(2).pow(256_u32); let xhi = BigInt::sample_below(&s); let h1_inv = BigInt::mod_inv(&h1, &ek_tilde.n).unwrap(); let h2 = BigInt::mod_pow(&h1_inv, &xhi, &ek_tilde.n); diff --git a/src/protocols/two_party_ecdsa/lindell_2017/party_two.rs b/src/protocols/two_party_ecdsa/lindell_2017/party_two.rs index 1ef6ed5d..0c282102 100644 --- a/src/protocols/two_party_ecdsa/lindell_2017/party_two.rs +++ b/src/protocols/two_party_ecdsa/lindell_2017/party_two.rs @@ -19,19 +19,18 @@ use centipede::juggling::segmentation::Msegmentation; use curv::arithmetic::traits::*; use curv::cryptographic_primitives::commitments::hash_commitment::HashCommitment; use curv::cryptographic_primitives::commitments::traits::Commitment; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; use curv::cryptographic_primitives::proofs::sigma_dlog::*; use curv::cryptographic_primitives::proofs::sigma_ec_ddh::*; use curv::cryptographic_primitives::proofs::ProofError; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::Paillier; use paillier::{Add, Encrypt, Mul}; use paillier::{EncryptionKey, RawCiphertext, RawPlaintext}; use serde::{Deserialize, Serialize}; -use zk_paillier::zkproofs::{CorrectKeyProofError, NICorrectKeyProof}; +use sha2::Sha256; +use zk_paillier::zkproofs::{IncorrectProof, NiCorrectKeyProof}; use super::party_one::EphKeyGenFirstMsg as Party1EphKeyGenFirstMsg; use super::party_one::KeyGenFirstMsg as Party1KeyGenFirstMessage; @@ -41,22 +40,28 @@ use crate::utilities::mta::{MessageA, MessageB}; use crate::utilities::zk_pdl_with_slack::PDLwSlackProof; use crate::utilities::zk_pdl_with_slack::PDLwSlackStatement; -use zeroize::Zeroize; +use thiserror::Error; use zk_paillier::zkproofs::{CompositeDLogProof, DLogStatement}; +#[derive(Error, Debug)] +pub enum PartyTwoError { + #[error("party two pdl verify failed (lindell 2017)")] + PdlVerify, +} + const PAILLIER_KEY_SIZE: usize = 2048; //****************** Begin: Party Two structs ******************// #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyGenFirstMsg { - pub d_log_proof: DLogProof, - pub public_share: GE, + pub d_log_proof: DLogProof, + pub public_share: Point, } #[derive(Debug, Serialize, Deserialize)] @@ -75,7 +80,7 @@ pub struct PartialSig { #[derive(Serialize, Deserialize)] pub struct Party2Private { - x2: FE, + x2: Scalar, } #[derive(Debug)] pub struct PDLchallenge { @@ -84,7 +89,7 @@ pub struct PDLchallenge { a: BigInt, b: BigInt, blindness: BigInt, - q_tag: GE, + q_tag: Point, } #[derive(Debug, Serialize, Deserialize)] @@ -106,17 +111,17 @@ pub struct PDLSecondMessage { } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EphEcKeyPair { - pub public_share: GE, - secret_share: FE, + pub public_share: Point, + secret_share: Scalar, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EphCommWitness { pub pk_commitment_blind_factor: BigInt, pub zk_pok_blind_factor: BigInt, - pub public_share: GE, - pub d_log_proof: ECDDHProof, - pub c: GE, //c = secret_share * base_point2 + pub public_share: Point, + pub d_log_proof: ECDDHProof, + pub c: Point, //c = secret_share * base_point2 } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -134,15 +139,14 @@ pub struct EphKeyGenSecondMsg { impl KeyGenFirstMsg { pub fn create() -> (KeyGenFirstMsg, EcKeyPair) { - let base: GE = ECPoint::generator(); - let mut secret_share: FE = ECScalar::new_random(); - let public_share = base * secret_share; + let base = Point::generator(); + let secret_share = Scalar::::random(); + let public_share = base * &secret_share; let d_log_proof = DLogProof::prove(&secret_share); let ec_key_pair = EcKeyPair { - public_share, + public_share: public_share.clone(), secret_share, }; - secret_share.zeroize(); ( KeyGenFirstMsg { d_log_proof, @@ -152,15 +156,16 @@ impl KeyGenFirstMsg { ) } - pub fn create_with_fixed_secret_share(mut secret_share: FE) -> (KeyGenFirstMsg, EcKeyPair) { - let base: GE = ECPoint::generator(); - let public_share = base * secret_share; + pub fn create_with_fixed_secret_share( + secret_share: Scalar, + ) -> (KeyGenFirstMsg, EcKeyPair) { + let base = Point::generator(); + let public_share = base * &secret_share; let d_log_proof = DLogProof::prove(&secret_share); let ec_key_pair = EcKeyPair { - public_share, + public_share: public_share.clone(), secret_share, }; - secret_share.zeroize(); ( KeyGenFirstMsg { d_log_proof, @@ -188,49 +193,55 @@ impl KeyGenSecondMsg { let mut flag = true; if party_one_pk_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &party_one_public_share.bytes_compressed_to_big_int(), - &party_one_pk_commitment_blind_factor, + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(party_one_public_share.to_bytes(true).as_ref()), + party_one_pk_commitment_blind_factor, ) { - flag = flag - } else { flag = false - }; + } if party_one_zk_pok_commitment - == &HashCommitment::create_commitment_with_user_defined_randomness( - &party_one_d_log_proof - .pk_t_rand_commitment - .bytes_compressed_to_big_int(), - &party_one_zk_pok_blind_factor, + != &HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes( + party_one_d_log_proof + .pk_t_rand_commitment + .to_bytes(true) + .as_ref(), + ), + party_one_zk_pok_blind_factor, ) { - flag = flag - } else { flag = false - }; - assert!(flag); - DLogProof::verify(&party_one_d_log_proof)?; + } + + if !flag { + return Err(ProofError); + } + + DLogProof::verify(party_one_d_log_proof)?; Ok(KeyGenSecondMsg {}) } } -pub fn compute_pubkey(local_share: &EcKeyPair, other_share_public_share: &GE) -> GE { +pub fn compute_pubkey( + local_share: &EcKeyPair, + other_share_public_share: &Point, +) -> Point { let pubkey = other_share_public_share; - pubkey.scalar_mul(&local_share.secret_share.get_element()) + pubkey * &local_share.secret_share } impl Party2Private { pub fn set_private_key(ec_key: &EcKeyPair) -> Party2Private { Party2Private { - x2: ec_key.secret_share, + x2: ec_key.secret_share.clone(), } } pub fn update_private_key(party_two_private: &Party2Private, factor: &BigInt) -> Party2Private { - let factor_fe: FE = ECScalar::from(factor); + let factor_fe = Scalar::::from(factor); Party2Private { - x2: party_two_private.x2.mul(&factor_fe.get_element()), + x2: &party_two_private.x2 * &factor_fe, } } @@ -239,19 +250,23 @@ impl Party2Private { &self, segment_size: usize, num_of_segments: usize, - pub_ke_y: &GE, - g: &GE, + pub_ke_y: &Point, + g: &Point, ) -> (Witness, Helgamalsegmented) { Msegmentation::to_encrypted_segments(&self.x2, &segment_size, num_of_segments, pub_ke_y, g) } // used to transform lindell master key to gg18 master key - pub fn to_mta_message_b(&self, ek: &EncryptionKey, ciphertext: &BigInt) -> (MessageB, FE) { + pub fn to_mta_message_b( + &self, + ek: &EncryptionKey, + ciphertext: &BigInt, + ) -> (MessageB, Scalar) { let message_a = MessageA { c: ciphertext.clone(), range_proofs: vec![], }; - let (a, b, _, _) = MessageB::b(&self.x2, &ek, message_a, &[]).unwrap(); + let (a, b, _, _) = MessageB::b(&self.x2, ek, message_a, &[]).unwrap(); (a, b) } } @@ -262,13 +277,13 @@ impl PaillierPublic { pdl_w_slack_statement: &PDLwSlackStatement, pdl_w_slack_proof: &PDLwSlackProof, paillier_public: &PaillierPublic, - q1: &GE, - ) -> Result<(), ()> { - if &pdl_w_slack_statement.ek != &paillier_public.ek - || &pdl_w_slack_statement.ciphertext != &paillier_public.encrypted_secret_share + q1: &Point, + ) -> Result<(), PartyTwoError> { + if pdl_w_slack_statement.ek != paillier_public.ek + || pdl_w_slack_statement.ciphertext != paillier_public.encrypted_secret_share || &pdl_w_slack_statement.Q != q1 { - return Err(()); + return Err(PartyTwoError::PdlVerify); } let dlog_statement = DLogStatement { N: pdl_w_slack_statement.N_tilde.clone(), @@ -276,66 +291,69 @@ impl PaillierPublic { ni: pdl_w_slack_statement.h2.clone(), }; if composite_dlog_proof.verify(&dlog_statement).is_ok() - && pdl_w_slack_proof.verify(&pdl_w_slack_statement).is_ok() + && pdl_w_slack_proof.verify(pdl_w_slack_statement).is_ok() { - return Ok(()); + Ok(()) } else { - return Err(()); + Err(PartyTwoError::PdlVerify) } } pub fn verify_ni_proof_correct_key( - proof: NICorrectKeyProof, + proof: NiCorrectKeyProof, ek: &EncryptionKey, - ) -> Result<(), CorrectKeyProofError> { + ) -> Result<(), IncorrectProof> { // if ek.n.bit_length() < PAILLIER_KEY_SIZE - 1 { - return Err(CorrectKeyProofError); + return Err(IncorrectProof); }; - proof.verify(&ek, zk_paillier::zkproofs::SALT_STRING) + proof.verify(ek, zk_paillier::zkproofs::SALT_STRING) } } impl EphKeyGenFirstMsg { pub fn create_commitments() -> (EphKeyGenFirstMsg, EphCommWitness, EphEcKeyPair) { - let base: GE = ECPoint::generator(); + let base = Point::generator(); - let mut secret_share: FE = ECScalar::new_random(); + let secret_share = Scalar::::random(); - let public_share = base.scalar_mul(&secret_share.get_element()); + let public_share = base * &secret_share; - let h: GE = GE::base_point2(); + let h = Point::::base_point2(); - let c = &h * &secret_share; - let mut x = secret_share; - let w = ECDDHWitness { x }; + let c = h * &secret_share; + let w = ECDDHWitness { + x: secret_share.clone(), + }; let delta = ECDDHStatement { - g1: base, - h1: public_share, - g2: h, - h2: c, + g1: base.to_point(), + h1: public_share.clone(), + g2: h.clone(), + h2: c.clone(), }; let d_log_proof = ECDDHProof::prove(&w, &delta); // we use hash based commitment let pk_commitment_blind_factor = BigInt::sample(SECURITY_BITS); - let pk_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &public_share.bytes_compressed_to_big_int(), - &pk_commitment_blind_factor, - ); + let pk_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(public_share.to_bytes(true).as_ref()), + &pk_commitment_blind_factor, + ); let zk_pok_blind_factor = BigInt::sample(SECURITY_BITS); - let zk_pok_commitment = HashCommitment::create_commitment_with_user_defined_randomness( - &HSha256::create_hash_from_ge(&[&d_log_proof.a1, &d_log_proof.a2]).to_big_int(), - &zk_pok_blind_factor, - ); + let zk_pok_commitment = + HashCommitment::::create_commitment_with_user_defined_randomness( + &Sha256::new() + .chain_points([&d_log_proof.a1, &d_log_proof.a2]) + .result_bigint(), + &zk_pok_blind_factor, + ); let ec_key_pair = EphEcKeyPair { public_share, secret_share, }; - secret_share.zeroize(); - x.zeroize(); ( EphKeyGenFirstMsg { pk_commitment, @@ -344,7 +362,7 @@ impl EphKeyGenFirstMsg { EphCommWitness { pk_commitment_blind_factor, zk_pok_blind_factor, - public_share: ec_key_pair.public_share, + public_share: ec_key_pair.public_share.clone(), d_log_proof, c, }, @@ -359,10 +377,10 @@ impl EphKeyGenSecondMsg { party_one_first_message: &Party1EphKeyGenFirstMsg, ) -> Result { let delta = ECDDHStatement { - g1: GE::generator(), - h1: party_one_first_message.public_share, - g2: GE::base_point2(), - h2: party_one_first_message.c, + g1: Point::generator().to_point(), + h1: party_one_first_message.public_share.clone(), + g2: Point::::base_point2().clone(), + h2: party_one_first_message.c.clone(), }; party_one_first_message.d_log_proof.verify(&delta)?; Ok(EphKeyGenSecondMsg { comm_witness }) @@ -375,27 +393,24 @@ impl PartialSig { encrypted_secret_share: &BigInt, local_share: &Party2Private, ephemeral_local_share: &EphEcKeyPair, - ephemeral_other_public_share: &GE, + ephemeral_other_public_share: &Point, message: &BigInt, ) -> PartialSig { - let q = FE::q(); + let q = Scalar::::group_order(); //compute r = k2* R1 - let r = ephemeral_other_public_share - .scalar_mul(&ephemeral_local_share.secret_share.get_element()); + let r = ephemeral_other_public_share * &ephemeral_local_share.secret_share; - let rx = r.x_coor().unwrap().mod_floor(&q); + let rx = r.x_coord().unwrap().mod_floor(q); let rho = BigInt::sample_below(&q.pow(2)); - let mut k2_inv = - BigInt::mod_inv(&ephemeral_local_share.secret_share.to_big_int(), &q).unwrap(); - let partial_sig = rho * &q + BigInt::mod_mul(&k2_inv, message, &q); + let k2_inv = BigInt::mod_inv(&ephemeral_local_share.secret_share.to_bigint(), q).unwrap(); + let partial_sig = rho * q + BigInt::mod_mul(&k2_inv, message, q); let c1 = Paillier::encrypt(ek, RawPlaintext::from(partial_sig)); let v = BigInt::mod_mul( &k2_inv, - &BigInt::mod_mul(&rx, &local_share.x2.to_big_int(), &q), - &q, + &BigInt::mod_mul(&rx, &local_share.x2.to_bigint(), q), + q, ); - k2_inv.zeroize(); let c2 = Paillier::mul( ek, RawCiphertext::from(encrypted_secret_share.clone()), diff --git a/src/protocols/two_party_ecdsa/lindell_2017/test.rs b/src/protocols/two_party_ecdsa/lindell_2017/test.rs index 27557764..60c142f6 100644 --- a/src/protocols/two_party_ecdsa/lindell_2017/test.rs +++ b/src/protocols/two_party_ecdsa/lindell_2017/test.rs @@ -2,7 +2,7 @@ use crate::protocols::two_party_ecdsa::lindell_2017::{party_one, party_two}; use curv::arithmetic::traits::Samplable; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Scalar}; use curv::BigInt; #[test] @@ -27,13 +27,13 @@ fn test_d_log_proof_party_two_party_one() { fn test_full_key_gen() { let (party_one_first_message, comm_witness, ec_key_pair_party1) = - party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share(ECScalar::from( - &BigInt::sample(253), - )); + party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share( + Scalar::::from(&BigInt::sample(253)), + ); let (party_two_first_message, _ec_key_pair_party2) = - party_two::KeyGenFirstMsg::create_with_fixed_secret_share(ECScalar::from(&BigInt::from( - 10, - ))); + party_two::KeyGenFirstMsg::create_with_fixed_secret_share(Scalar::::from( + &BigInt::from(10), + )); let party_one_second_message = party_one::KeyGenSecondMsg::verify_and_decommit( comm_witness, &party_two_first_message.d_log_proof, diff --git a/src/utilities/mta/mod.rs b/src/utilities/mta/mod.rs index c0fd580f..b5415d87 100644 --- a/src/utilities/mta/mod.rs +++ b/src/utilities/mta/mod.rs @@ -17,8 +17,7 @@ /// MtA is described in https://eprint.iacr.org/2019/114.pdf section 3 use curv::arithmetic::traits::Samplable; use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::traits::EncryptWithChosenRandomness; use paillier::{Add, Decrypt, Mul}; @@ -26,6 +25,7 @@ use paillier::{DecryptionKey, EncryptionKey, Paillier, Randomness, RawCiphertext use zk_paillier::zkproofs::DLogStatement; use serde::{Deserialize, Serialize}; +use sha2::Sha256; use crate::protocols::multi_party_ecdsa::gg_2018::party_i::PartyPrivate; use crate::utilities::mta::range_proofs::AliceProof; @@ -40,8 +40,8 @@ pub struct MessageA { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MessageB { pub c: BigInt, // paillier encryption - pub b_proof: DLogProof, - pub beta_tag_proof: DLogProof, + pub b_proof: DLogProof, + pub beta_tag_proof: DLogProof, } impl MessageA { @@ -50,7 +50,7 @@ impl MessageA { /// If range proofs are not needed (one example is identification of aborts where we /// only want to reconstruct a ciphertext), `dlog_statements` can be an empty slice. pub fn a( - a: &FE, + a: &Scalar, alice_ek: &EncryptionKey, dlog_statements: &[DLogStatement], ) -> (Self, BigInt) { @@ -60,23 +60,23 @@ impl MessageA { } pub fn a_with_predefined_randomness( - a: &FE, + a: &Scalar, alice_ek: &EncryptionKey, randomness: &BigInt, dlog_statements: &[DLogStatement], ) -> Self { let c_a = Paillier::encrypt_with_chosen_randomness( alice_ek, - RawPlaintext::from(a.to_big_int()), + RawPlaintext::from(a.to_bigint()), &Randomness::from(randomness.clone()), ) .0 .clone() .into_owned(); let alice_range_proofs = dlog_statements - .into_iter() + .iter() .map(|dlog_statement| { - AliceProof::generate(&a.to_big_int(), &c_a, alice_ek, dlog_statement, &randomness) + AliceProof::generate(&a.to_bigint(), &c_a, alice_ek, dlog_statement, randomness) }) .collect::>(); @@ -89,11 +89,11 @@ impl MessageA { impl MessageB { pub fn b( - b: &FE, + b: &Scalar, alice_ek: &EncryptionKey, m_a: MessageA, dlog_statements: &[DLogStatement], - ) -> Result<(Self, FE, BigInt, BigInt), Error> { + ) -> Result<(Self, Scalar, BigInt, BigInt), Error> { let beta_tag = BigInt::sample_below(&alice_ek.n); let randomness = BigInt::sample_below(&alice_ek.n); let (m_b, beta) = MessageB::b_with_predefined_randomness( @@ -109,13 +109,13 @@ impl MessageB { } pub fn b_with_predefined_randomness( - b: &FE, + b: &Scalar, alice_ek: &EncryptionKey, m_a: MessageA, randomness: &BigInt, beta_tag: &BigInt, dlog_statements: &[DLogStatement], - ) -> Result<(Self, FE), Error> { + ) -> Result<(Self, Scalar), Error> { if m_a.range_proofs.len() != dlog_statements.len() { return Err(InvalidKey); } @@ -129,21 +129,21 @@ impl MessageB { { return Err(InvalidKey); }; - let beta_tag_fe: FE = ECScalar::from(beta_tag); + let beta_tag_fe = Scalar::::from(beta_tag); let c_beta_tag = Paillier::encrypt_with_chosen_randomness( alice_ek, RawPlaintext::from(beta_tag), &Randomness::from(randomness.clone()), ); - let b_bn = b.to_big_int(); + let b_bn = b.to_bigint(); let b_c_a = Paillier::mul( alice_ek, RawCiphertext::from(m_a.c), RawPlaintext::from(b_bn), ); let c_b = Paillier::add(alice_ek, b_c_a, c_beta_tag); - let beta = FE::zero().sub(&beta_tag_fe.get_element()); + let beta = Scalar::::zero() - &beta_tag_fe; let dlog_proof_b = DLogProof::prove(b); let dlog_proof_beta_tag = DLogProof::prove(&beta_tag_fe); @@ -160,17 +160,17 @@ impl MessageB { pub fn verify_proofs_get_alpha( &self, dk: &DecryptionKey, - a: &FE, - ) -> Result<(FE, BigInt), Error> { + a: &Scalar, + ) -> Result<(Scalar, BigInt), Error> { let alice_share = Paillier::decrypt(dk, &RawCiphertext::from(self.c.clone())); - let g: GE = ECPoint::generator(); - let alpha: FE = ECScalar::from(&alice_share.0); - let g_alpha = g * alpha; - let ba_btag = self.b_proof.pk * a + self.beta_tag_proof.pk; + let g = Point::generator(); + let alpha = Scalar::::from(alice_share.0.as_ref()); + let g_alpha = g * α + let ba_btag = &self.b_proof.pk * a + &self.beta_tag_proof.pk; if DLogProof::verify(&self.b_proof).is_ok() && DLogProof::verify(&self.beta_tag_proof).is_ok() // we prove the correctness of the ciphertext using this check and the proof of knowledge of dlog of beta_tag - && ba_btag.get_element() == g_alpha.get_element() + && ba_btag == g_alpha { Ok((alpha, alice_share.0.into_owned())) } else { @@ -183,17 +183,17 @@ impl MessageB { pub fn verify_proofs_get_alpha_gg18( &self, private: &PartyPrivate, - a: &FE, - ) -> Result { + a: &Scalar, + ) -> Result, Error> { let alice_share = private.decrypt(self.c.clone()); - let g: GE = ECPoint::generator(); - let alpha: FE = ECScalar::from(&alice_share.0); - let g_alpha = g * alpha; - let ba_btag = self.b_proof.pk * a + self.beta_tag_proof.pk; + let g = Point::generator(); + let alpha = Scalar::::from(alice_share.0.as_ref()); + let g_alpha = g * α + let ba_btag = &self.b_proof.pk * a + &self.beta_tag_proof.pk; if DLogProof::verify(&self.b_proof).is_ok() && DLogProof::verify(&self.beta_tag_proof).is_ok() - && ba_btag.get_element() == g_alpha.get_element() + && ba_btag == g_alpha { Ok(alpha) } else { @@ -201,8 +201,11 @@ impl MessageB { } } - pub fn verify_b_against_public(public_gb: &GE, mta_gb: &GE) -> bool { - public_gb.get_element() == mta_gb.get_element() + pub fn verify_b_against_public( + public_gb: &Point, + mta_gb: &Point, + ) -> bool { + public_gb == mta_gb } } diff --git a/src/utilities/mta/range_proofs.rs b/src/utilities/mta/range_proofs.rs index 521d76d9..4610a57f 100644 --- a/src/utilities/mta/range_proofs.rs +++ b/src/utilities/mta/range_proofs.rs @@ -10,13 +10,12 @@ //! 2) A non-interactive version is implemented, with challenge `e` computed via Fiat-Shamir. use curv::arithmetic::traits::*; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::{ECPoint, ECScalar}; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; +use sha2::Sha256; -use paillier::{Add, EncryptionKey, Mul, Randomness, RawCiphertext, RawPlaintext}; +use paillier::{EncryptionKey, Randomness}; use zk_paillier::zkproofs::DLogStatement; use serde::{Deserialize, Serialize}; @@ -50,7 +49,7 @@ impl AliceZkpRound1 { let beta = BigInt::from_paillier_key(alice_ek); let gamma = BigInt::sample_below(&(q.pow(3) * N_tilde)); let ro = BigInt::sample_below(&(q * N_tilde)); - let z = (BigInt::mod_pow(h1, &a, N_tilde) * BigInt::mod_pow(h2, &ro, N_tilde)) % N_tilde; + let z = (BigInt::mod_pow(h1, a, N_tilde) * BigInt::mod_pow(h2, &ro, N_tilde)) % N_tilde; let u = ((alpha.borrow() * &alice_ek.n + 1) * BigInt::mod_pow(&beta, &alice_ek.n, &alice_ek.nn)) % &alice_ek.nn; @@ -84,7 +83,7 @@ impl AliceZkpRound2 { r: &BigInt, ) -> Self { Self { - s: (BigInt::mod_pow(r, &e, &alice_ek.n) * round1.beta.borrow()) % &alice_ek.n, + s: (BigInt::mod_pow(r, e, &alice_ek.n) * round1.beta.borrow()) % &alice_ek.n, s1: (e * a) + round1.alpha.borrow(), s2: (e * round1.ro.borrow()) + round1.gamma.borrow(), } @@ -116,7 +115,7 @@ impl AliceProof { let h2 = &dlog_statement.ni; let Gen = alice_ek.n.borrow() + 1; - if self.s1 > FE::q().pow(3) { + if self.s1 > Scalar::::group_order().pow(3) { return false; } @@ -133,7 +132,7 @@ impl AliceProof { % N_tilde; let gs1 = (self.s1.borrow() * N + 1) % NN; - let cipher_e_inv = BigInt::mod_inv(&BigInt::mod_pow(&cipher, &self.e, NN), NN); + let cipher_e_inv = BigInt::mod_inv(&BigInt::mod_pow(cipher, &self.e, NN), NN); let cipher_e_inv = match cipher_e_inv { None => return false, Some(c) => c, @@ -141,7 +140,14 @@ impl AliceProof { let u = (gs1 * BigInt::mod_pow(&self.s, N, NN) * cipher_e_inv) % NN; - let e = HSha256::create_hash(&[N, &Gen, cipher, &self.z, &u, &w]); + let e = Sha256::new() + .chain_bigint(N) + .chain_bigint(&Gen) + .chain_bigint(cipher) + .chain_bigint(&self.z) + .chain_bigint(&u) + .chain_bigint(&w) + .result_bigint(); if e != self.e { return false; } @@ -158,10 +164,22 @@ impl AliceProof { dlog_statement: &DLogStatement, r: &BigInt, ) -> Self { - let round1 = AliceZkpRound1::from(alice_ek, dlog_statement, a, &FE::q()); + let round1 = AliceZkpRound1::from( + alice_ek, + dlog_statement, + a, + Scalar::::group_order(), + ); let Gen = alice_ek.n.borrow() + 1; - let e = HSha256::create_hash(&[&alice_ek.n, &Gen, cipher, &round1.z, &round1.u, &round1.w]); + let e = Sha256::new() + .chain_bigint(&alice_ek.n) + .chain_bigint(&Gen) + .chain_bigint(cipher) + .chain_bigint(&round1.z) + .chain_bigint(&round1.u) + .chain_bigint(&round1.w) + .result_bigint(); let round2 = AliceZkpRound2::from(alice_ek, &round1, &e, a, r); @@ -200,7 +218,7 @@ impl BobZkpRound1 { fn from( alice_ek: &EncryptionKey, dlog_statement: &DLogStatement, - b: &FE, + b: &Scalar, beta_prim: &BigInt, a_encrypted: &BigInt, q: &BigInt, @@ -208,7 +226,7 @@ impl BobZkpRound1 { let h1 = &dlog_statement.g; let h2 = &dlog_statement.ni; let N_tilde = &dlog_statement.N; - let b_bn = b.to_big_int(); + let b_bn = b.to_bigint(); let alpha = BigInt::sample_below(&q.pow(3)); let beta = BigInt::from_paillier_key(alice_ek); @@ -264,11 +282,11 @@ impl BobZkpRound2 { alice_ek: &EncryptionKey, round1: &BobZkpRound1, e: &BigInt, - b: &FE, + b: &Scalar, beta_prim: &BigInt, r: &Randomness, ) -> Self { - let b_bn = b.to_big_int(); + let b_bn = b.to_bigint(); Self { s: (BigInt::mod_pow(r.0.borrow(), e, &alice_ek.n) * round1.beta.borrow()) % &alice_ek.n, s1: (e * b_bn) + round1.alpha.borrow(), @@ -281,8 +299,8 @@ impl BobZkpRound2 { /// Additional fields in Bob's proof if MtA is run with check pub struct BobCheck { - u: GE, - X: GE, + u: Point, + X: Point, } /// Bob's regular proof @@ -314,7 +332,7 @@ impl BobProof { let h1 = &dlog_statement.g; let h2 = &dlog_statement.ni; - if self.s1 > FE::q().pow(3) { + if self.s1 > Scalar::::group_order().pow(3) { return false; } @@ -367,17 +385,23 @@ impl BobProof { ]; let e = match check { Some(_) => { - let X_x_coor = check.unwrap().X.x_coor().unwrap(); + let X_x_coor = check.unwrap().X.x_coord().unwrap(); values_to_hash.push(&X_x_coor); - let X_y_coor = check.unwrap().X.y_coor().unwrap(); + let X_y_coor = check.unwrap().X.y_coord().unwrap(); values_to_hash.push(&X_y_coor); - let u_x_coor = check.unwrap().u.x_coor().unwrap(); + let u_x_coor = check.unwrap().u.x_coord().unwrap(); values_to_hash.push(&u_x_coor); - let u_y_coor = check.unwrap().u.y_coor().unwrap(); + let u_y_coor = check.unwrap().u.y_coord().unwrap(); values_to_hash.push(&u_y_coor); - HSha256::create_hash(&values_to_hash[..]) + values_to_hash + .into_iter() + .fold(Sha256::new(), |acc, b| acc.chain_bigint(b)) + .result_bigint() } - None => HSha256::create_hash(&values_to_hash[..]), + None => values_to_hash + .into_iter() + .fold(Sha256::new(), |acc, b| acc.chain_bigint(b)) + .result_bigint(), }; if e != self.e { @@ -390,20 +414,20 @@ impl BobProof { pub fn generate( a_encrypted: &BigInt, mta_encrypted: &BigInt, - b: &FE, + b: &Scalar, beta_prim: &BigInt, alice_ek: &EncryptionKey, dlog_statement: &DLogStatement, r: &Randomness, check: bool, - ) -> (BobProof, Option) { + ) -> (BobProof, Option>) { let round1 = BobZkpRound1::from( alice_ek, dlog_statement, b, beta_prim, a_encrypted, - &FE::q(), + Scalar::::group_order(), ); let Gen = alice_ek.n.borrow() + 1; @@ -421,22 +445,28 @@ impl BobProof { let mut check_u = None; let e = if check { let (X, u) = { - let ec_gen: GE = ECPoint::generator(); - let alpha: FE = ECScalar::from(&round1.alpha); + let ec_gen = Point::generator(); + let alpha = Scalar::::from(&round1.alpha); (ec_gen * b, ec_gen * alpha) }; - check_u = Some(u); - let X_x_coor = X.x_coor().unwrap(); + check_u = Some(u.clone()); + let X_x_coor = X.x_coord().unwrap(); values_to_hash.push(&X_x_coor); - let X_y_coor = X.y_coor().unwrap(); + let X_y_coor = X.y_coord().unwrap(); values_to_hash.push(&X_y_coor); - let u_x_coor = u.x_coor().unwrap(); + let u_x_coor = u.x_coord().unwrap(); values_to_hash.push(&u_x_coor); - let u_y_coor = u.y_coor().unwrap(); + let u_y_coor = u.y_coord().unwrap(); values_to_hash.push(&u_y_coor); - HSha256::create_hash(&values_to_hash[..]) + values_to_hash + .into_iter() + .fold(Sha256::new(), |acc, b| acc.chain_bigint(b)) + .result_bigint() } else { - HSha256::create_hash(&values_to_hash[..]) + values_to_hash + .into_iter() + .fold(Sha256::new(), |acc, b| acc.chain_bigint(b)) + .result_bigint() }; let round2 = BobZkpRound2::from(alice_ek, &round1, &e, b, beta_prim, r); @@ -461,7 +491,7 @@ impl BobProof { #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] pub struct BobProofExt { proof: BobProof, - u: GE, + u: Point, } #[allow(clippy::too_many_arguments)] @@ -472,7 +502,7 @@ impl BobProofExt { mta_avc_out: &BigInt, alice_ek: &EncryptionKey, dlog_statement: &DLogStatement, - X: &GE, + X: &Point, ) -> bool { // check basic proof first if !self.proof.verify( @@ -480,17 +510,20 @@ impl BobProofExt { mta_avc_out, alice_ek, dlog_statement, - Some(&BobCheck { u: self.u, X: *X }), + Some(&BobCheck { + u: self.u.clone(), + X: X.clone(), + }), ) { return false; } // fiddle with EC points let (x1, x2) = { - let ec_gen: GE = ECPoint::generator(); - let s1: FE = ECScalar::from(&self.proof.s1); - let e: FE = ECScalar::from(&self.proof.e); - (ec_gen * s1, (X * &e) + self.u) + let ec_gen = Point::generator(); + let s1 = Scalar::::from(&self.proof.s1); + let e = Scalar::::from(&self.proof.e); + (ec_gen * s1, (X * &e) + &self.u) }; if x1 != x2 { @@ -499,33 +532,6 @@ impl BobProofExt { true } - - fn generate( - a_encrypted: &BigInt, - mta_encrypted: &BigInt, - b: &FE, - beta_prim: &BigInt, - alice_ek: &EncryptionKey, - dlog_statement: &DLogStatement, - r: &Randomness, - ) -> BobProofExt { - // proving a basic proof (with modified hash) - let (bob_proof, u) = BobProof::generate( - a_encrypted, - mta_encrypted, - b, - beta_prim, - alice_ek, - dlog_statement, - r, - true, - ); - - BobProofExt { - proof: bob_proof, - u: u.unwrap(), - } - } } /// sample random value of an element of a multiplicative group @@ -554,7 +560,34 @@ impl SampleFromMultiplicativeGroup for BigInt { pub(crate) mod tests { use super::*; use paillier::traits::{Encrypt, EncryptWithChosenRandomness, KeyGeneration}; - use paillier::{DecryptionKey, Paillier}; + use paillier::{Add, DecryptionKey, Mul, Paillier, RawCiphertext, RawPlaintext}; + + fn generate( + a_encrypted: &BigInt, + mta_encrypted: &BigInt, + b: &Scalar, + beta_prim: &BigInt, + alice_ek: &EncryptionKey, + dlog_statement: &DLogStatement, + r: &Randomness, + ) -> BobProofExt { + // proving a basic proof (with modified hash) + let (bob_proof, u) = BobProof::generate( + a_encrypted, + mta_encrypted, + b, + beta_prim, + alice_ek, + dlog_statement, + r, + true, + ); + + BobProofExt { + proof: bob_proof, + u: u.unwrap(), + } + } pub(crate) fn generate_init() -> (DLogStatement, EncryptionKey, DecryptionKey) { let (ek_tilde, dk_tilde) = Paillier::keypair().keys(); @@ -584,7 +617,7 @@ pub(crate) mod tests { let (dlog_statement, ek, _) = generate_init(); // Alice's secret value - let a = FE::new_random().to_big_int(); + let a = Scalar::::random().to_bigint(); let r = BigInt::from_paillier_key(&ek); let cipher = Paillier::encrypt_with_chosen_randomness( &ek, @@ -610,19 +643,19 @@ pub(crate) mod tests { // run MtA protocol with different inputs (0..5).for_each(|_| { // Simulate Alice - let a = FE::new_random().to_big_int(); + let a = Scalar::::random().to_bigint(); let encrypted_a = Paillier::encrypt(alice_public_key, RawPlaintext::from(a)) .0 .clone() .into_owned(); // Bob follows MtA - let b = FE::new_random(); + let b = Scalar::::random(); // E(a) * b let b_times_enc_a = Paillier::mul( alice_public_key, RawCiphertext::from(encrypted_a.clone()), - RawPlaintext::from(&b.to_big_int()), + RawPlaintext::from(&b.to_bigint()), ); let beta_prim = BigInt::sample_below(&alice_public_key.n); let r = Randomness::sample(alice_public_key); @@ -653,9 +686,9 @@ pub(crate) mod tests { )); // Bob follows MtAwc - let ec_gen: GE = ECPoint::generator(); - let X = ec_gen * b; - let bob_proof = BobProofExt::generate( + let ec_gen = Point::generator(); + let X = ec_gen * &b; + let bob_proof = generate( &encrypted_a, &mta_out.0.clone().into_owned(), &b, diff --git a/src/utilities/mta/test.rs b/src/utilities/mta/test.rs index 25d4f733..0602ea9a 100644 --- a/src/utilities/mta/test.rs +++ b/src/utilities/mta/test.rs @@ -1,13 +1,12 @@ use crate::utilities::mta::range_proofs::tests::generate_init; use crate::utilities::mta::{MessageA, MessageB}; -use curv::elliptic::curves::secp256_k1::FE; -use curv::elliptic::curves::traits::ECScalar; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Scalar}; #[test] fn test_mta() { - let alice_input: FE = ECScalar::new_random(); + let alice_input = Scalar::::random(); let (dlog_statement, ek_alice, dk_alice) = generate_init(); - let bob_input: FE = ECScalar::new_random(); + let bob_input = Scalar::::random(); let (m_a, _) = MessageA::a(&alice_input, &ek_alice, &[dlog_statement.clone()]); let (m_b, beta, _, _) = MessageB::b(&bob_input, &ek_alice, m_a, &[dlog_statement]).unwrap(); let alpha = m_b @@ -16,5 +15,5 @@ fn test_mta() { let left = alpha.0 + beta; let right = alice_input * bob_input; - assert_eq!(left.get_element(), right.get_element()); + assert_eq!(left, right); } diff --git a/src/utilities/zk_pdl/mod.rs b/src/utilities/zk_pdl/mod.rs index f4b5fbba..2d703527 100644 --- a/src/utilities/zk_pdl/mod.rs +++ b/src/utilities/zk_pdl/mod.rs @@ -25,27 +25,35 @@ use std::ops::Shl; use curv::arithmetic::traits::*; use curv::cryptographic_primitives::commitments::hash_commitment::HashCommitment; use curv::cryptographic_primitives::commitments::traits::Commitment; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::ECPoint; -use curv::elliptic::curves::traits::ECScalar; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::Paillier; use paillier::{Add, Decrypt, Encrypt, Mul}; use paillier::{DecryptionKey, EncryptionKey, RawCiphertext, RawPlaintext}; use serde::{Deserialize, Serialize}; -use zk_paillier::zkproofs::RangeProofError; +use sha2::Sha256; +use thiserror::Error; +use zk_paillier::zkproofs::IncorrectProof; use zk_paillier::zkproofs::RangeProofNi; +#[derive(Error, Debug)] +pub enum ZkPdlError { + #[error("zk pdl message2 failed")] + Message2, + #[error("zk pdl finalize failed")] + Finalize, +} + #[derive(Clone)] pub struct PDLStatement { pub ciphertext: BigInt, pub ek: EncryptionKey, - pub Q: GE, - pub G: GE, + pub Q: Point, + pub G: Point, } #[derive(Clone)] pub struct PDLWitness { - pub x: FE, + pub x: Scalar, pub r: BigInt, pub dk: DecryptionKey, } @@ -57,7 +65,7 @@ pub struct PDLVerifierState { a: BigInt, b: BigInt, blindness: BigInt, - q_tag: GE, + q_tag: Point, c_hat: BigInt, } @@ -88,7 +96,7 @@ pub struct PDLVerifierSecondMessage { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PDLProverDecommit { - pub q_hat: GE, + pub q_hat: Point, pub blindness: BigInt, } @@ -102,12 +110,12 @@ pub struct Verifier {} impl Verifier { pub fn message1(statement: &PDLStatement) -> (PDLVerifierFirstMessage, PDLVerifierState) { - let a_fe: FE = ECScalar::new_random(); - let a = a_fe.to_big_int(); - let q = FE::q(); + let a_fe = Scalar::::random(); + let a = a_fe.to_bigint(); + let q = Scalar::::group_order(); let q_sq = q.pow(2); let b = BigInt::sample_below(&q_sq); - let b_fe: FE = ECScalar::from(&b); + let b_fe = Scalar::::from(&b); let b_enc = Paillier::encrypt(&statement.ek, RawPlaintext::from(b.clone())); let ac = Paillier::mul( &statement.ek, @@ -116,10 +124,11 @@ impl Verifier { ); let c_tag = Paillier::add(&statement.ek, ac, b_enc).0.into_owned(); let ab_concat = a.clone() + b.clone().shl(a.bit_length()); - let blindness = BigInt::sample_below(&q); - let c_tag_tag = - HashCommitment::create_commitment_with_user_defined_randomness(&ab_concat, &blindness); - let q_tag = &statement.Q * &a_fe + statement.G * b_fe; + let blindness = BigInt::sample_below(q); + let c_tag_tag = HashCommitment::::create_commitment_with_user_defined_randomness( + &ab_concat, &blindness, + ); + let q_tag = &statement.Q * &a_fe + &statement.G * b_fe; ( PDLVerifierFirstMessage { @@ -142,19 +151,19 @@ impl Verifier { prover_first_messasge: &PDLProverFirstMessage, statement: &PDLStatement, state: &mut PDLVerifierState, - ) -> Result { + ) -> Result { let decommit_message = PDLVerifierSecondMessage { a: state.a.clone(), b: state.b.clone(), blindness: state.blindness.clone(), }; let range_proof_is_ok = - verify_range_proof(&statement, &prover_first_messasge.range_proof).is_ok(); + verify_range_proof(statement, &prover_first_messasge.range_proof).is_ok(); state.c_hat = prover_first_messasge.c_hat.clone(); if range_proof_is_ok { Ok(decommit_message) } else { - Err(()) + Err(ZkPdlError::Message2) } } @@ -162,21 +171,18 @@ impl Verifier { prover_first_message: &PDLProverFirstMessage, prover_second_message: &PDLProverSecondMessage, state: &PDLVerifierState, - ) -> Result<(), ()> { - let c_hat_test = HashCommitment::create_commitment_with_user_defined_randomness( - &prover_second_message - .decommit - .q_hat - .bytes_compressed_to_big_int(), + ) -> Result<(), ZkPdlError> { + let c_hat_test = HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(prover_second_message.decommit.q_hat.to_bytes(true).as_ref()), &prover_second_message.decommit.blindness, ); - if &prover_first_message.c_hat == &c_hat_test - && &prover_second_message.decommit.q_hat == &state.q_tag + if prover_first_message.c_hat == c_hat_test + && prover_second_message.decommit.q_hat == state.q_tag { Ok(()) } else { - Err(()) + Err(ZkPdlError::Finalize) } } } @@ -188,12 +194,12 @@ impl Prover { verifier_first_message: &PDLVerifierFirstMessage, ) -> (PDLProverFirstMessage, PDLProverState) { let c_tag = verifier_first_message.c_tag.clone(); - let alpha = Paillier::decrypt(&witness.dk, &RawCiphertext::from(c_tag.clone())); - let alpha_fe: FE = ECScalar::from(&alpha.0); - let q_hat = statement.G * alpha_fe; - let blindness = BigInt::sample_below(&FE::q()); - let c_hat = HashCommitment::create_commitment_with_user_defined_randomness( - &q_hat.bytes_compressed_to_big_int(), + let alpha = Paillier::decrypt(&witness.dk, &RawCiphertext::from(c_tag)); + let alpha_fe = Scalar::::from(alpha.0.as_ref()); + let q_hat = &statement.G * alpha_fe; + let blindness = BigInt::sample_below(Scalar::::group_order()); + let c_hat = HashCommitment::::create_commitment_with_user_defined_randomness( + &BigInt::from_bytes(q_hat.to_bytes(true).as_ref()), &blindness, ); // in parallel generate range proof: @@ -212,24 +218,25 @@ impl Prover { verifier_second_message: &PDLVerifierSecondMessage, witness: &PDLWitness, state: &PDLProverState, - ) -> Result { + ) -> Result { let ab_concat = &verifier_second_message.a + verifier_second_message .b .clone() .shl(verifier_second_message.a.bit_length()); // b|a (in the paper it is a|b) - let c_tag_tag_test = HashCommitment::create_commitment_with_user_defined_randomness( - &ab_concat, - &verifier_second_message.blindness, - ); - let ax1 = &verifier_second_message.a * witness.x.to_big_int(); + let c_tag_tag_test = + HashCommitment::::create_commitment_with_user_defined_randomness( + &ab_concat, + &verifier_second_message.blindness, + ); + let ax1 = &verifier_second_message.a * witness.x.to_bigint(); let alpha_test = ax1 + &verifier_second_message.b; - if &alpha_test == &state.alpha && verifier_first_message.c_tag_tag == c_tag_tag_test { + if alpha_test == state.alpha && verifier_first_message.c_tag_tag == c_tag_tag_test { Ok(PDLProverSecondMessage { decommit: state.decommit.clone(), }) } else { - Err(()) + Err(ZkPdlError::Message2) } } } @@ -237,9 +244,9 @@ impl Prover { fn generate_range_proof(statement: &PDLStatement, witness: &PDLWitness) -> RangeProofNi { RangeProofNi::prove( &statement.ek, - &FE::q(), + Scalar::::group_order(), &statement.ciphertext, - &witness.x.to_big_int(), + &witness.x.to_bigint(), &witness.r, ) } @@ -247,7 +254,7 @@ fn generate_range_proof(statement: &PDLStatement, witness: &PDLWitness) -> Range fn verify_range_proof( statement: &PDLStatement, range_proof: &RangeProofNi, -) -> Result<(), RangeProofError> { +) -> Result<(), IncorrectProof> { range_proof.verify(&statement.ek, &statement.ciphertext) } diff --git a/src/utilities/zk_pdl/test.rs b/src/utilities/zk_pdl/test.rs index 09077012..3f4e6994 100644 --- a/src/utilities/zk_pdl/test.rs +++ b/src/utilities/zk_pdl/test.rs @@ -1,8 +1,7 @@ #![allow(non_snake_case)] use curv::arithmetic::traits::*; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::*; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::core::Randomness; use paillier::traits::{EncryptWithChosenRandomness, KeyGeneration}; @@ -17,14 +16,15 @@ fn test_zk_pdl() { let (ek, dk) = Paillier::keypair().keys(); let randomness = Randomness::sample(&ek); - let x: FE = ECScalar::new_random(); - let x: FE = ECScalar::from(&x.to_big_int().div_floor(&BigInt::from(3))); + let x = Scalar::::random(); + let x: Scalar = + Scalar::::from(&x.to_bigint().div_floor(&BigInt::from(3))); - let Q = GE::generator() * &x; + let Q = Point::generator() * &x; let c = Paillier::encrypt_with_chosen_randomness( &ek, - RawPlaintext::from(x.to_big_int().clone()), + RawPlaintext::from(x.to_bigint()), &randomness, ) .0 @@ -33,7 +33,7 @@ fn test_zk_pdl() { ciphertext: c, ek, Q, - G: GE::generator(), + G: Point::generator().to_point(), }; let witness = PDLWitness { x, diff --git a/src/utilities/zk_pdl_with_slack/mod.rs b/src/utilities/zk_pdl_with_slack/mod.rs index 49395b58..c9d2c70c 100644 --- a/src/utilities/zk_pdl_with_slack/mod.rs +++ b/src/utilities/zk_pdl_with_slack/mod.rs @@ -23,35 +23,40 @@ //! note that because of the range proof, the proof has a slack in the range: x in [-q^3, q^3] use curv::arithmetic::traits::*; -use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; -use curv::cryptographic_primitives::hashing::traits::Hash; -use curv::elliptic::curves::secp256_k1::{FE, GE}; -use curv::elliptic::curves::traits::ECPoint; -use curv::elliptic::curves::traits::ECScalar; +use curv::cryptographic_primitives::hashing::{Digest, DigestExt}; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::EncryptionKey; use serde::{Deserialize, Serialize}; +use sha2::Sha256; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ZkPdlWithSlackError { + #[error("zk pdl with slack verification failed")] + Verify, +} #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PDLwSlackStatement { pub ciphertext: BigInt, pub ek: EncryptionKey, - pub Q: GE, - pub G: GE, + pub Q: Point, + pub G: Point, pub h1: BigInt, pub h2: BigInt, pub N_tilde: BigInt, } #[derive(Clone)] pub struct PDLwSlackWitness { - pub x: FE, + pub x: Scalar, pub r: BigInt, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PDLwSlackProof { z: BigInt, - u1: GE, + u1: Point, u2: BigInt, u3: BigInt, s1: BigInt, @@ -61,8 +66,8 @@ pub struct PDLwSlackProof { impl PDLwSlackProof { pub fn prove(witness: &PDLwSlackWitness, statement: &PDLwSlackStatement) -> Self { - let q3 = FE::q().pow(3); - let q_N_tilde = FE::q() * &statement.N_tilde; + let q3 = Scalar::::group_order().pow(3); + let q_N_tilde = Scalar::::group_order() * &statement.N_tilde; let q3_N_tilde = &q3 * &statement.N_tilde; let alpha = BigInt::sample_below(&q3); @@ -75,10 +80,10 @@ impl PDLwSlackProof { &statement.h1, &statement.h2, &statement.N_tilde, - &witness.x.to_big_int(), + &witness.x.to_bigint(), &rho, ); - let u1 = &statement.G * &ECScalar::from(&alpha); + let u1 = &statement.G * &Scalar::::from(&alpha); let u2 = commitment_unknown_order( &(&statement.ek.n + BigInt::one()), &beta, @@ -94,17 +99,17 @@ impl PDLwSlackProof { &gamma, ); - let e = HSha256::create_hash(&[ - &statement.G.bytes_compressed_to_big_int(), - &statement.Q.bytes_compressed_to_big_int(), - &statement.ciphertext, - &z, - &u1.bytes_compressed_to_big_int(), - &u2, - &u3, - ]); - - let s1 = &e * witness.x.to_big_int() + alpha; + let e = Sha256::new() + .chain_bigint(&BigInt::from_bytes(statement.G.to_bytes(true).as_ref())) + .chain_bigint(&BigInt::from_bytes(statement.Q.to_bytes(true).as_ref())) + .chain_bigint(&statement.ciphertext) + .chain_bigint(&z) + .chain_bigint(&BigInt::from_bytes(u1.to_bytes(true).as_ref())) + .chain_bigint(&u2) + .chain_bigint(&u3) + .result_bigint(); + + let s1 = &e * witness.x.to_bigint() + alpha; let s2 = commitment_unknown_order(&witness.r, &beta, &statement.ek.n, &e, &BigInt::one()); let s3 = &e * rho + gamma; @@ -119,18 +124,20 @@ impl PDLwSlackProof { } } - pub fn verify(&self, statement: &PDLwSlackStatement) -> Result<(), ()> { - let e = HSha256::create_hash(&[ - &statement.G.bytes_compressed_to_big_int(), - &statement.Q.bytes_compressed_to_big_int(), - &statement.ciphertext, - &self.z, - &self.u1.bytes_compressed_to_big_int(), - &self.u2, - &self.u3, - ]); - let g_s1 = statement.G.clone() * &ECScalar::from(&self.s1); - let e_fe_neg: FE = ECScalar::from(&(FE::q() - &e)); + pub fn verify(&self, statement: &PDLwSlackStatement) -> Result<(), ZkPdlWithSlackError> { + let e = Sha256::new() + .chain_bigint(&BigInt::from_bytes(statement.G.to_bytes(true).as_ref())) + .chain_bigint(&BigInt::from_bytes(statement.Q.to_bytes(true).as_ref())) + .chain_bigint(&statement.ciphertext) + .chain_bigint(&self.z) + .chain_bigint(&BigInt::from_bytes(self.u1.to_bytes(true).as_ref())) + .chain_bigint(&self.u2) + .chain_bigint(&self.u3) + .result_bigint(); + + let g_s1 = statement.G.clone() * &Scalar::::from(&self.s1); + let e_fe_neg: Scalar = + Scalar::::from(&(Scalar::::group_order() - &e)); let y_minus_e = &statement.Q * &e_fe_neg; let u1_test = g_s1 + y_minus_e; @@ -164,10 +171,10 @@ impl PDLwSlackProof { &(-&e), ); - if &self.u1 == &u1_test && &self.u2 == &u2_test && &self.u3 == &u3_test { + if self.u1 == u1_test && self.u2 == u2_test && self.u3 == u3_test { Ok(()) } else { - Err(()) + Err(ZkPdlWithSlackError::Verify) } } } @@ -179,17 +186,16 @@ pub fn commitment_unknown_order( x: &BigInt, r: &BigInt, ) -> BigInt { - let h1_x = BigInt::mod_pow(h1, &x, &N_tilde); + let h1_x = BigInt::mod_pow(h1, x, N_tilde); let h2_r = { if r < &BigInt::zero() { - let h2_inv = BigInt::mod_inv(h2, &N_tilde).unwrap(); - BigInt::mod_pow(&h2_inv, &(-r), &N_tilde) + let h2_inv = BigInt::mod_inv(h2, N_tilde).unwrap(); + BigInt::mod_pow(&h2_inv, &(-r), N_tilde) } else { - BigInt::mod_pow(h2, &r, &N_tilde) + BigInt::mod_pow(h2, r, N_tilde) } }; - let com = BigInt::mod_mul(&h1_x, &h2_r, &N_tilde); - com + BigInt::mod_mul(&h1_x, &h2_r, N_tilde) } #[cfg(test)] diff --git a/src/utilities/zk_pdl_with_slack/test.rs b/src/utilities/zk_pdl_with_slack/test.rs index 202d68d7..fabcda4b 100644 --- a/src/utilities/zk_pdl_with_slack/test.rs +++ b/src/utilities/zk_pdl_with_slack/test.rs @@ -1,6 +1,6 @@ #![allow(non_snake_case)] use crate::utilities::zk_pdl_with_slack::*; -use curv::elliptic::curves::secp256_k1::{FE, GE}; +use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar}; use curv::BigInt; use paillier::core::Randomness; use paillier::traits::{EncryptWithChosenRandomness, KeyGeneration}; @@ -17,7 +17,7 @@ fn test_zk_pdl_with_slack() { let one = BigInt::one(); let phi = (&dk_tilde.p - &one) * (&dk_tilde.q - &one); let h1 = BigInt::sample_below(&phi); - let S = BigInt::from(2).pow(256 as u32); + let S = BigInt::from(2).pow(256_u32); let xhi = BigInt::sample_below(&S); let h1_inv = BigInt::mod_inv(&h1, &ek_tilde.n).unwrap(); let h2 = BigInt::mod_pow(&h1_inv, &xhi, &ek_tilde.n); @@ -34,13 +34,13 @@ fn test_zk_pdl_with_slack() { // note: safe primes should be used here as well: // let (ek_tilde, dk_tilde) = Paillier::keypair_safe_primes().keys(); let randomness = Randomness::sample(&ek); - let x: FE = ECScalar::new_random(); + let x = Scalar::::random(); - let Q = GE::generator() * &x; + let Q = Point::generator() * &x; let c = Paillier::encrypt_with_chosen_randomness( &ek, - RawPlaintext::from(x.to_big_int().clone()), + RawPlaintext::from(x.to_bigint()), &randomness, ) .0 @@ -51,7 +51,7 @@ fn test_zk_pdl_with_slack() { ciphertext: c, ek, Q, - G: GE::generator(), + G: Point::generator().to_point(), h1, h2, N_tilde: ek_tilde.n, @@ -77,7 +77,7 @@ fn test_zk_pdl_with_slack_soundness() { let one = BigInt::one(); let phi = (&dk_tilde.p - &one) * (&dk_tilde.q - &one); let h1 = BigInt::sample_below(&phi); - let S = BigInt::from(2).pow(256 as u32); + let S = BigInt::from(2).pow(256_u32); let xhi = BigInt::sample_below(&S); let h1_inv = BigInt::mod_inv(&h1, &ek_tilde.n).unwrap(); let h2 = BigInt::mod_pow(&h1_inv, &xhi, &ek_tilde.n); @@ -94,14 +94,14 @@ fn test_zk_pdl_with_slack_soundness() { // note: safe primes should be used here as well: // let (ek_tilde, dk_tilde) = Paillier::keypair_safe_primes().keys(); let randomness = Randomness::sample(&ek); - let x: FE = ECScalar::new_random(); + let x = Scalar::::random(); - let Q = GE::generator() * &x; + let Q = Point::generator() * &x; // here we encrypt x + 1 instead of x: let c = Paillier::encrypt_with_chosen_randomness( &ek, - RawPlaintext::from(x.to_big_int().clone() + BigInt::one()), + RawPlaintext::from(x.to_bigint() + BigInt::one()), &randomness, ) .0 @@ -112,7 +112,7 @@ fn test_zk_pdl_with_slack_soundness() { ciphertext: c, ek, Q, - G: GE::generator(), + G: Point::generator().to_point(), h1, h2, N_tilde: ek_tilde.n,