Skip to content

Commit

Permalink
Range proofs and moduli sizes checks added (#145)
Browse files Browse the repository at this point in the history
* * feat: range proofs for Bob and Alice in MtA implemented
* fix: added Alice's range proof to MtA messageA
* fix: parties now verify sizes of other parties' public moduli
* test: tests for range proofs and small modulus choice
* fix: when verifying dlog between h2 and h1, parties now construct dlog statement themselves instead of taking it from the prover

* fix: addressing comments

* fix: zeroize Alice too
  • Loading branch information
DmytroTym authored Nov 1, 2021
1 parent 175e492 commit c1fffc5
Show file tree
Hide file tree
Showing 11 changed files with 857 additions and 97 deletions.
10 changes: 7 additions & 3 deletions examples/gg18_sign_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ fn main() {
let xi_com_vec = Keys::get_commitments_to_xi(&vss_scheme_vec);
//////////////////////////////////////////////////////////////////////////////
let (com, decommit) = sign_keys.phase1_broadcast();
let (m_a_k, _) = MessageA::a(&sign_keys.k_i, &party_keys.ek);
let (m_a_k, _) = MessageA::a(&sign_keys.k_i, &party_keys.ek, &[]);
assert!(broadcast(
&client,
party_num_int,
Expand Down Expand Up @@ -159,12 +159,16 @@ fn main() {
&sign_keys.gamma_i,
&paillier_key_vector[signers_vec[(i - 1) as usize]],
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]],
m_a_vec[j].clone(),
);
&[],
)
.unwrap();
m_b_gamma_send_vec.push(m_b_gamma);
m_b_w_send_vec.push(m_b_w);
beta_vec.push(beta_gamma);
Expand Down
16 changes: 12 additions & 4 deletions src/protocols/multi_party_ecdsa/gg_2018/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,11 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec<usize>) {

// each party i sends encryption of k_i under her Paillier key
// m_a_vec = [ma_0;ma_1;,...]
// range proofs are ignored here, as there's no h1, h2, N_tilde setup in this version of GG18
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[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)
Expand All @@ -203,9 +204,16 @@ fn sign(t: u16, n: u16, ttag: u16, s: Vec<usize>) {
&key.gamma_i,
&party_keys_vec[s[ind]].ek,
m_a_vec[ind].clone(),
);
let (m_b_w, beta_wi, _, _) =
MessageB::b(&key.w_i, &party_keys_vec[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,
m_a_vec[ind].clone(),
&[],
)
.unwrap();

m_b_gamma_vec.push(m_b_gamma);
beta_vec.push(beta_gamma);
Expand Down
50 changes: 29 additions & 21 deletions src/protocols/multi_party_ecdsa/gg_2020/blame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,34 +131,41 @@ impl GlobalStatePhase5 {
&self.k_vec[i],
&self.encryption_key_vec[i],
&self.k_randomness_vec[i],
&[],
);

// check message a
if message_a.c != self.m_a_vec[i].c {
bad_signers_vec.push(i)
}

let alpha_beta_vector = (0..len - 1)
.map(|j| {
let ind = if j < i { j } else { j + 1 };
let (message_b, beta) = MessageB::b_with_predefined_randomness(
&self.gamma_vec[ind],
&self.encryption_key_vec[i],
self.m_a_vec[i].clone(),
&self.beta_randomness_vec[i][j],
&self.beta_tag_vec[i][j],
);
// check message_b
if message_b.c != self.m_b_mat[i][j].c {
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());

(alpha, beta)
})
.collect::<Vec<(FE, FE)>>();
let alpha_beta_vector = if bad_signers_vec.is_empty() {
(0..len - 1)
.map(|j| {
let ind = if j < i { j } else { j + 1 };
let (message_b, beta) = MessageB::b_with_predefined_randomness(
&self.gamma_vec[ind],
&self.encryption_key_vec[i],
message_a.clone(),
&self.beta_randomness_vec[i][j],
&self.beta_tag_vec[i][j],
&[],
)
.unwrap();
// check message_b
if message_b.c != self.m_b_mat[i][j].c {
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());

(alpha, beta)
})
.collect::<Vec<(FE, FE)>>()
} else {
vec![]
};

alpha_beta_vector
})
Expand Down Expand Up @@ -333,6 +340,7 @@ impl GlobalStatePhase6 {
&self.k_vec[i],
&self.encryption_key_vec[i],
&self.k_randomness_vec[i],
&[],
)
.c != self.m_a_vec[i].c
{
Expand Down
21 changes: 15 additions & 6 deletions src/protocols/multi_party_ecdsa/gg_2020/party_i.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ use crate::utilities::zk_pdl_with_slack::{PDLwSlackProof, PDLwSlackStatement, PD
use curv::cryptographic_primitives::proofs::sigma_valid_pedersen::PedersenProof;

const SECURITY: usize = 256;
const PAILLIER_MIN_BIT_LENGTH: usize = 2047;
const PAILLIER_MAX_BIT_LENGTH: usize = 2048;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Parameters {
Expand Down Expand Up @@ -82,8 +84,7 @@ pub struct PartyPrivate {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KeyGenBroadcastMessage1 {
pub e: EncryptionKey,
pub dlog_statement_base_h1: DLogStatement,
pub dlog_statement_base_h2: DLogStatement,
pub dlog_statement: DLogStatement,
pub com: BigInt,
pub correct_key_proof: NICorrectKeyProof,
pub composite_dlog_proof_base_h1: CompositeDLogProof,
Expand Down Expand Up @@ -251,8 +252,7 @@ impl Keys {
);
let bcm1 = KeyGenBroadcastMessage1 {
e: self.ek.clone(),
dlog_statement_base_h1,
dlog_statement_base_h2,
dlog_statement: dlog_statement_base_h1,
com,
correct_key_proof,
composite_dlog_proof_base_h1,
Expand All @@ -278,6 +278,11 @@ impl Keys {
// test paillier correct key, h1,h2 correct generation and test decommitments
let correct_key_correct_decom_all = (0..bc1_vec.len())
.map(|i| {
let dlog_statement_base_h2 = DLogStatement {
N: bc1_vec[i].dlog_statement.N.clone(),
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,
Expand All @@ -286,13 +291,17 @@ impl Keys {
.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_base_h1)
.verify(&bc1_vec[i].dlog_statement)
.is_ok()
&& bc1_vec[i]
.composite_dlog_proof_base_h2
.verify(&bc1_vec[i].dlog_statement_base_h2)
.verify(&dlog_statement_base_h2)
.is_ok();
if test_res == false {
bad_actors_vec.push(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ impl Round4 {
let h1_h2_n_tilde_vec = self
.bc_vec
.iter()
.map(|bc1| bc1.dlog_statement_base_h1.clone())
.map(|bc1| bc1.dlog_statement.clone())
.collect::<Vec<DLogStatement>>();

let (head, tail) = self.y_vec.split_at(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl Round0 {
let (bc1, decom1) = sign_keys.phase1_broadcast();

let party_ek = self.local_key.paillier_key_vec[usize::from(self.local_key.i - 1)].clone();
let m_a = MessageA::a(&sign_keys.k_i, &party_ek);
let m_a = MessageA::a(&sign_keys.k_i, &party_ek, &self.local_key.h1_h2_n_tilde_vec);

output.push(Msg {
sender: self.i,
Expand Down Expand Up @@ -149,12 +149,16 @@ impl Round1 {
&self.sign_keys.gamma_i,
&self.local_key.paillier_key_vec[l_s[ind]],
m_a_vec[ind].clone(),
);
&self.local_key.h1_h2_n_tilde_vec,
)
.expect("Incorrect Alice's range proof in MtA");
let (m_b_w, beta_wi, _, _) = MessageB::b(
&self.sign_keys.w_i,
&self.local_key.paillier_key_vec[l_s[ind]],
m_a_vec[ind].clone(),
);
&self.local_key.h1_h2_n_tilde_vec,
)
.expect("Incorrect Alice's range proof in MtA");

m_b_gamma_vec.push(m_b_gamma);
beta_vec.push(beta_gamma);
Expand Down
43 changes: 38 additions & 5 deletions src/protocols/multi_party_ecdsa/gg_2020/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ fn keygen_t_n_parties(
.collect::<Vec<EncryptionKey>>();
let h1_h2_N_tilde_vec = bc1_vec
.iter()
.map(|bc1| bc1.dlog_statement_base_h1.clone())
.map(|bc1| bc1.dlog_statement.clone())
.collect::<Vec<DLogStatement>>();
let y_vec = (0..n).map(|i| decom_vec[i].y_i).collect::<Vec<GE>>();
let mut y_vec_iter = y_vec.iter();
Expand Down Expand Up @@ -308,14 +308,20 @@ fn sign(
let (bc1_vec, decommit_vec1): (Vec<_>, Vec<_>) =
sign_keys_vec.iter().map(|k| k.phase1_broadcast()).unzip();

// each signer's dlog statement. in reality, parties prove statements
// using only other parties' h1,h2,N_tilde. here we also use own parameters for simplicity
let signers_dlog_statements = (0..ttag)
.map(|i| dlog_statement_vec[s[i]].clone())
.collect::<Vec<DLogStatement>>();

// each party i BROADCASTS encryption of k_i under her Paillier key
// m_a_vec = [ma_0;ma_1;,...]
// we assume here that party sends the same encryption to all other parties.
// It should be changed to different encryption (randomness) to each counter party
let m_a_vec: Vec<_> = sign_keys_vec
.iter()
.enumerate()
.map(|(i, k)| MessageA::a(&k.k_i, &party_keys_vec[s[i]].ek))
.map(|(i, k)| MessageA::a(&k.k_i, &party_keys_vec[s[i]].ek, &signers_dlog_statements))
.collect();

// #each party i sends responses to m_a_vec she received (one response with input gamma_i and one with w_i)
Expand Down Expand Up @@ -344,9 +350,16 @@ fn sign(
&sign_keys_vec[ind].gamma_i,
&ek_vec[s[i]],
m_a_vec[i].0.clone(),
);
let (m_b_w, beta_wi, _, _) =
MessageB::b(&sign_keys_vec[ind].w_i, &ek_vec[s[i]], m_a_vec[i].0.clone());
&signers_dlog_statements,
)
.expect("Alice's range proofs in MtA failed");
let (m_b_w, beta_wi, _, _) = MessageB::b(
&sign_keys_vec[ind].w_i,
&ek_vec[s[i]],
m_a_vec[i].0.clone(),
&signers_dlog_statements,
)
.expect("Alice's range proofs in MtA failed");

m_b_gamma_vec.push(m_b_gamma);
beta_vec.push(beta_gamma);
Expand Down Expand Up @@ -743,3 +756,23 @@ fn test_serialize_deserialize() {
let decoded: KeyGenDecommitMessage1 = serde_json::from_str(&encoded).unwrap();
assert_eq!(decommit.y_i, decoded.y_i);
}
#[test]
fn test_small_paillier() {
// parties shouldn't be able to choose small Paillier modulus
let mut k = Keys::create(0);
// creating 2046-bit Paillier
let (ek, dk) = Paillier::keypair_with_modulus_size(2046).keys();
k.dk = dk;
k.ek = ek;
let (commit, decommit) = k.phase1_broadcast_phase3_proof_of_correct_key_proof_of_correct_h1h2();
assert!(k
.phase1_verify_com_phase3_verify_correct_key_verify_dlog_phase2_distribute(
&Parameters {
threshold: 0,
share_count: 1
},
&[decommit],
&[commit],
)
.is_err());
}
3 changes: 2 additions & 1 deletion src/protocols/two_party_ecdsa/lindell_2017/party_two.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,9 @@ impl Party2Private {
pub fn to_mta_message_b(&self, ek: &EncryptionKey, ciphertext: &BigInt) -> (MessageB, FE) {
let message_a = MessageA {
c: ciphertext.clone(),
range_proofs: vec![],
};
let (a, b, _, _) = MessageB::b(&self.x2, &ek, message_a);
let (a, b, _, _) = MessageB::b(&self.x2, &ek, message_a, &[]).unwrap();
(a, b)
}
}
Expand Down
Loading

0 comments on commit c1fffc5

Please sign in to comment.