Skip to content

Commit fd92128

Browse files
authored
Known issues (#81)
* fixes * typo + remove debug * audit report
1 parent ce97091 commit fd92128

File tree

9 files changed

+99
-47
lines changed

9 files changed

+99
-47
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "multi-party-ecdsa"
3-
version = "0.2.3"
3+
version = "0.2.4"
44
authors = [
55
66
@@ -25,12 +25,12 @@ crate-type = ["lib"]
2525

2626

2727
[dependencies]
28-
paillier = { git = "https://github.com/KZen-networks/rust-paillier", tag = "v0.3.2" }
29-
zk-paillier = { git = "https://github.com/KZen-networks/zk-paillier", tag = "v0.2.3" }
28+
paillier = { git = "https://github.com/KZen-networks/rust-paillier", tag = "v0.3.3" }
29+
zk-paillier = { git = "https://github.com/KZen-networks/zk-paillier", tag = "v0.2.4" }
3030
subtle = {version = "2", features = ["nightly"]}
3131
serde = "1.0"
3232
serde_derive = "1.0"
33-
33+
zeroize = "0.10"
3434

3535
[features]
3636
cclst = ["class_group"]

audits/REPORT_final_2019-10-22.pdf

299 KB
Binary file not shown.

examples/gg18_keygen_client.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,7 @@ fn main() {
165165
let decom_j: KeyGenDecommitMessage1 = serde_json::from_str(&round2_ans_vec[j]).unwrap();
166166
y_vec.push(decom_j.y_i.clone());
167167
decom_vec.push(decom_j.clone());
168-
enc_keys.push(
169-
(party_keys.y_i.clone() + decom_j.y_i.clone())
170-
.x_coor()
171-
.unwrap(),
172-
);
168+
enc_keys.push((decom_j.y_i.clone() * party_keys.u_i).x_coor().unwrap());
173169
j = j + 1;
174170
}
175171
}

examples/gg18_sign_client.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,6 @@ fn main() {
348348

349349
// we assume the message is already hashed (by the signer).
350350
let message_bn = BigInt::from(message);
351-
let two = BigInt::from(2);
352-
let message_bn = message_bn.modulus(&two.pow(256));
353351
let local_sig =
354352
LocalSignature::phase5_local_sig(&sign_keys.k_i, &message_bn, &R, &sigma, &y_sum);
355353

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ extern crate centipede;
2424
extern crate class_group;
2525
extern crate curv;
2626
extern crate paillier;
27+
extern crate zeroize;
2728
extern crate zk_paillier;
2829
pub mod protocols;
2930

src/protocols/multi_party_ecdsa/gg_2018/mta.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,15 @@ impl MessageB {
8080
let ba_btag = &self.b_proof.pk * a + &self.beta_tag_proof.pk;
8181
match DLogProof::verify(&self.b_proof).is_ok()
8282
&& DLogProof::verify(&self.beta_tag_proof).is_ok()
83+
// we prove the correctness of the ciphertext using this check and the proof of knowledge of dlog of beta_tag
8384
&& ba_btag.get_element() == g_alpha.get_element()
8485
{
8586
true => Ok(alpha),
8687
false => Err(InvalidKey),
8788
}
8889
}
8990

90-
// another version, supportion PartyPrivate therefore binding mta to gg18.
91+
// another version, supporting PartyPrivate therefore binding mta to gg18.
9192
// with the regular version mta can be used in general
9293
pub fn verify_proofs_get_alpha_gg18(
9394
&self,

src/protocols/multi_party_ecdsa/gg_2018/party_i.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,21 @@ impl Keys {
158158
}
159159
}
160160

161+
// we recommend using safe primes if the code is used in production
162+
pub fn create_safe_prime(index: usize) -> Keys {
163+
let u: FE = ECScalar::new_random();
164+
let y = &ECPoint::generator() * &u;
165+
166+
let (ek, dk) = Paillier::keypair_safe_primes().keys();
167+
168+
Keys {
169+
u_i: u,
170+
y_i: y,
171+
dk,
172+
ek,
173+
party_index: index.clone(),
174+
}
175+
}
161176
pub fn create_from(u: FE, index: usize) -> Keys {
162177
let y = &ECPoint::generator() * &u;
163178
let (ek, dk) = Paillier::keypair().keys();
@@ -334,6 +349,21 @@ impl PartyPrivate {
334349
}
335350
}
336351

352+
// we recommend using safe primes if the code is used in production
353+
pub fn refresh_private_key_safe_prime(&self, factor: &FE, index: usize) -> Keys {
354+
let u: FE = self.u_i + factor;
355+
let y = &ECPoint::generator() * &u;
356+
let (ek, dk) = Paillier::keypair_safe_primes().keys();
357+
358+
Keys {
359+
u_i: u,
360+
y_i: y,
361+
dk,
362+
ek,
363+
party_index: index.clone(),
364+
}
365+
}
366+
337367
// used for verifiable recovery
338368
pub fn to_encrypted_segment(
339369
&self,
@@ -425,10 +455,11 @@ impl SignKeys {
425455
delta_inv: &FE,
426456
b_proof_vec: &Vec<&DLogProof>,
427457
phase1_decommit_vec: Vec<SignDecommitPhase1>,
428-
// blind_vec: &Vec<BigInt>,
429-
// g_gamma_i_vec: &Vec<GE>,
430458
bc1_vec: &Vec<SignBroadcastPhase1>,
431459
) -> Result<GE, Error> {
460+
// note: b_proof_vec is populated using the results
461+
//from the MtAwc, which is handling the proof of knowledge verification of gamma_i such that
462+
// Gamme_i = gamma_i * G in the verify_proofs_get_alpha()
432463
let test_b_vec_and_com = (0..b_proof_vec.len())
433464
.map(|i| {
434465
b_proof_vec[i].pk.get_element() == phase1_decommit_vec[i].g_gamma_i.get_element()

src/protocols/two_party_ecdsa/lindell_2017/party_one.rs

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use curv::BigInt;
4545
use curv::FE;
4646
use curv::GE;
4747

48+
use zeroize::Zeroize;
4849
use Error::{self, InvalidSig};
4950

5051
use subtle::ConstantTimeEq;
@@ -141,10 +142,10 @@ impl KeyGenFirstMsg {
141142
pub fn create_commitments() -> (KeyGenFirstMsg, CommWitness, EcKeyPair) {
142143
let base: GE = ECPoint::generator();
143144

144-
let secret_share: FE = ECScalar::new_random();
145+
let mut scalar: FE = ECScalar::new_random();
145146
//in Lindell's protocol range proof works only for x1<q/3
146-
let secret_share: FE =
147-
ECScalar::from(&secret_share.to_big_int().div_floor(&BigInt::from(3)));
147+
let mut secret_share: FE = ECScalar::from(&scalar.to_big_int().div_floor(&BigInt::from(3)));
148+
scalar.zeroize();
148149

149150
let public_share = base.scalar_mul(&secret_share.get_element());
150151

@@ -167,6 +168,7 @@ impl KeyGenFirstMsg {
167168
public_share,
168169
secret_share,
169170
};
171+
secret_share.zeroize();
170172
(
171173
KeyGenFirstMsg {
172174
pk_commitment,
@@ -183,7 +185,7 @@ impl KeyGenFirstMsg {
183185
}
184186

185187
pub fn create_commitments_with_fixed_secret_share(
186-
secret_share: FE,
188+
mut secret_share: FE,
187189
) -> (KeyGenFirstMsg, CommWitness, EcKeyPair) {
188190
//in Lindell's protocol range proof works only for x1<q/3
189191
let sk_bigint = secret_share.to_big_int();
@@ -212,6 +214,7 @@ impl KeyGenFirstMsg {
212214
public_share,
213215
secret_share,
214216
};
217+
secret_share.zeroize();
215218
(
216219
KeyGenFirstMsg {
217220
pk_commitment,
@@ -411,7 +414,7 @@ impl PaillierKeyPair {
411414
let b = pdl_party_two_second_message.decommit.b.clone();
412415
let blindness = pdl_party_two_second_message.decommit.blindness.clone();
413416

414-
let ab_concat = a.clone() + b.clone().shl(a.bit_length());
417+
let ab_concat = a.clone() + b.clone().shl(a.bit_length()); // b|a (in the paper it is a|b)
415418
let c_tag_tag_test =
416419
HashCommitment::create_commitment_with_user_defined_randomness(&ab_concat, &blindness);
417420
let ax1 = a.clone() * party_one_private.x1.to_big_int();
@@ -429,13 +432,13 @@ impl PaillierKeyPair {
429432
impl EphKeyGenFirstMsg {
430433
pub fn create() -> (EphKeyGenFirstMsg, EphEcKeyPair) {
431434
let base: GE = ECPoint::generator();
432-
let secret_share: FE = ECScalar::new_random();
435+
let mut secret_share: FE = ECScalar::new_random();
433436
let public_share = &base * &secret_share;
434437
let h: GE = GE::base_point2();
435-
let w = ECDDHWitness {
436-
x: secret_share.clone(),
437-
};
438+
438439
let c = &h * &secret_share;
440+
let mut x = secret_share;
441+
let w = ECDDHWitness { x };
439442
let delta = ECDDHStatement {
440443
g1: base.clone(),
441444
h1: public_share.clone(),
@@ -447,6 +450,8 @@ impl EphKeyGenFirstMsg {
447450
public_share: public_share.clone(),
448451
secret_share,
449452
};
453+
secret_share.zeroize();
454+
x.zeroize();
450455
(
451456
EphKeyGenFirstMsg {
452457
d_log_proof,
@@ -517,17 +522,22 @@ impl Signature {
517522
r = r.scalar_mul(&ephemeral_local_share.secret_share.get_element());
518523

519524
let rx = r.x_coor().unwrap().mod_floor(&FE::q());
520-
let k1_inv = &ephemeral_local_share
521-
.secret_share
522-
.to_big_int()
523-
.invert(&FE::q())
524-
.unwrap();
525+
526+
let mut k1_inv = ephemeral_local_share.secret_share.invert();
527+
525528
let s_tag = Paillier::decrypt(
526529
&party_one_private.paillier_priv,
527530
&RawCiphertext::from(partial_sig_c3),
528-
);
529-
let s_tag_tag = BigInt::mod_mul(&k1_inv, &s_tag.0, &FE::q());
530-
let s = cmp::min(s_tag_tag.clone(), FE::q().clone() - s_tag_tag.clone());
531+
)
532+
.0;
533+
let mut s_tag_fe: FE = ECScalar::from(&s_tag);
534+
let s_tag_tag = s_tag_fe * k1_inv;
535+
k1_inv.zeroize();
536+
s_tag_fe.zeroize();
537+
let s_tag_tag_bn = s_tag_tag.to_big_int();
538+
539+
let s = cmp::min(s_tag_tag_bn.clone(), FE::q().clone() - s_tag_tag_bn.clone());
540+
531541
Signature { s, r: rx }
532542
}
533543

@@ -543,17 +553,19 @@ impl Signature {
543553

544554
let rx = r.x_coor().unwrap().mod_floor(&FE::q());
545555
let ry = r.y_coor().unwrap().mod_floor(&FE::q());
546-
let k1_inv = &ephemeral_local_share
547-
.secret_share
548-
.to_big_int()
549-
.invert(&FE::q())
550-
.unwrap();
556+
let mut k1_inv = ephemeral_local_share.secret_share.invert();
557+
551558
let s_tag = Paillier::decrypt(
552559
&party_one_private.paillier_priv,
553560
&RawCiphertext::from(partial_sig_c3),
554-
);
555-
let s_tag_tag = BigInt::mod_mul(&k1_inv, &s_tag.0, &FE::q());
556-
let s = cmp::min(s_tag_tag.clone(), FE::q().clone() - s_tag_tag.clone());
561+
)
562+
.0;
563+
let mut s_tag_fe: FE = ECScalar::from(&s_tag);
564+
let s_tag_tag = s_tag_fe * k1_inv;
565+
k1_inv.zeroize();
566+
s_tag_fe.zeroize();
567+
let s_tag_tag_bn = s_tag_tag.to_big_int();
568+
let s = cmp::min(s_tag_tag_bn.clone(), FE::q().clone() - s_tag_tag_bn.clone());
557569

558570
/*
559571
Calculate recovery id - it is not possible to compute the public key out of the signature
@@ -563,7 +575,7 @@ impl Signature {
563575
*/
564576
let is_ry_odd = ry.tstbit(0);
565577
let mut recid = if is_ry_odd { 1 } else { 0 };
566-
if s_tag_tag.clone() > FE::q() - s_tag_tag.clone() {
578+
if s_tag_tag_bn.clone() > FE::q() - s_tag_tag_bn.clone() {
567579
recid = recid ^ 1;
568580
}
569581

src/protocols/two_party_ecdsa/lindell_2017/party_two.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ use centipede::juggling::proof_system::{Helgamalsegmented, Witness};
4747
use centipede::juggling::segmentation::Msegmentation;
4848
use protocols::multi_party_ecdsa::gg_2018::mta::{MessageA, MessageB};
4949

50+
use zeroize::Zeroize;
51+
52+
const PAILLIER_KEY_SIZE: usize = 2048;
5053
//****************** Begin: Party Two structs ******************//
5154

5255
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -137,13 +140,14 @@ pub struct EphKeyGenSecondMsg {
137140
impl KeyGenFirstMsg {
138141
pub fn create() -> (KeyGenFirstMsg, EcKeyPair) {
139142
let base: GE = ECPoint::generator();
140-
let secret_share: FE = ECScalar::new_random();
143+
let mut secret_share: FE = ECScalar::new_random();
141144
let public_share = base * &secret_share;
142145
let d_log_proof = DLogProof::prove(&secret_share);
143146
let ec_key_pair = EcKeyPair {
144147
public_share: public_share.clone(),
145148
secret_share,
146149
};
150+
secret_share.zeroize();
147151
(
148152
KeyGenFirstMsg {
149153
d_log_proof,
@@ -153,14 +157,15 @@ impl KeyGenFirstMsg {
153157
)
154158
}
155159

156-
pub fn create_with_fixed_secret_share(secret_share: FE) -> (KeyGenFirstMsg, EcKeyPair) {
160+
pub fn create_with_fixed_secret_share(mut secret_share: FE) -> (KeyGenFirstMsg, EcKeyPair) {
157161
let base: GE = ECPoint::generator();
158162
let public_share = base * &secret_share;
159163
let d_log_proof = DLogProof::prove(&secret_share);
160164
let ec_key_pair = EcKeyPair {
161165
public_share: public_share.clone(),
162166
secret_share,
163167
};
168+
secret_share.zeroize();
164169
(
165170
KeyGenFirstMsg {
166171
d_log_proof,
@@ -333,6 +338,10 @@ impl PaillierPublic {
333338
proof: NICorrectKeyProof,
334339
ek: &EncryptionKey,
335340
) -> Result<(), CorrectKeyProofError> {
341+
//
342+
if ek.n.bit_length() < PAILLIER_KEY_SIZE - 1 {
343+
return Err(CorrectKeyProofError);
344+
};
336345
proof.verify(&ek)
337346
}
338347
}
@@ -341,15 +350,15 @@ impl EphKeyGenFirstMsg {
341350
pub fn create_commitments() -> (EphKeyGenFirstMsg, EphCommWitness, EphEcKeyPair) {
342351
let base: GE = ECPoint::generator();
343352

344-
let secret_share: FE = ECScalar::new_random();
353+
let mut secret_share: FE = ECScalar::new_random();
345354

346355
let public_share = base.scalar_mul(&secret_share.get_element());
347356

348357
let h: GE = GE::base_point2();
349-
let w = ECDDHWitness {
350-
x: secret_share.clone(),
351-
};
358+
352359
let c = &h * &secret_share;
360+
let mut x = secret_share;
361+
let w = ECDDHWitness { x };
353362
let delta = ECDDHStatement {
354363
g1: base.clone(),
355364
h1: public_share.clone(),
@@ -375,6 +384,8 @@ impl EphKeyGenFirstMsg {
375384
public_share,
376385
secret_share,
377386
};
387+
secret_share.zeroize();
388+
x.zeroize();
378389
(
379390
EphKeyGenFirstMsg {
380391
pk_commitment,
@@ -424,18 +435,20 @@ impl PartialSig {
424435

425436
let rx = r.x_coor().unwrap().mod_floor(&q);
426437
let rho = BigInt::sample_below(&q.pow(2));
427-
let k2_inv = &ephemeral_local_share
438+
let mut k2_inv = ephemeral_local_share
428439
.secret_share
429440
.to_big_int()
430441
.invert(&q)
431442
.unwrap();
432443
let partial_sig = rho * &q + BigInt::mod_mul(&k2_inv, message, &q);
444+
433445
let c1 = Paillier::encrypt(ek, RawPlaintext::from(partial_sig));
434446
let v = BigInt::mod_mul(
435447
&k2_inv,
436448
&BigInt::mod_mul(&rx, &local_share.x2.to_big_int(), &q),
437449
&q,
438450
);
451+
k2_inv.zeroize_bn();
439452
let c2 = Paillier::mul(
440453
ek,
441454
RawCiphertext::from(encrypted_secret_share.clone()),

0 commit comments

Comments
 (0)