Skip to content

Commit 48d1823

Browse files
committed
update to version 3.7
1 parent 6c77824 commit 48d1823

File tree

55 files changed

+3705
-398
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3705
-398
lines changed

Cargo.toml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "multi-party-ecdsa"
3-
version = "0.2.7"
3+
version = "0.3.7"
44
edition = "2018"
55
authors = [
66
"Gary <gary@kzencorp.com>",
@@ -18,7 +18,7 @@ keywords = [
1818
]
1919

2020
homepage = "https://github.com/KZen-networks/multi-party-ecdsa"
21-
repository = "https://github.com/commerceblock/multi-party-ecdsa"
21+
repository = "https://github.com/KZen-networks/multi-party-ecdsa"
2222
license = "GPL-3.0-or-later"
2323
categories = ["cryptography"]
2424

@@ -29,24 +29,24 @@ crate-type = ["lib"]
2929
cclst = ["class_group"]
3030

3131
[dependencies]
32-
paillier = { git = "https://github.com/KZen-networks/rust-paillier", tag = "v0.3.3"}
33-
zk-paillier = { git = "https://github.com/KZen-networks/zk-paillier", tag = "v0.2.4"}
32+
paillier = { git = "https://github.com/KZen-networks/rust-paillier", tag = "v0.3.4"}
33+
zk-paillier = { git = "https://github.com/KZen-networks/zk-paillier", tag = "v0.2.8"}
3434
subtle = { version = "2" }
3535
serde = { version = "1.0", features = ["derive"] }
3636
zeroize = "0.10.1"
3737

3838
[dependencies.curv]
3939
git = "https://github.com/commerceblock/curv"
4040
tag = "v0.2.7"
41-
features = ["ec_secp256k1"]
41+
features = ["ec_secp256k1"]
4242

4343
[dependencies.centipede]
4444
git = "https://github.com/commerceblock/centipede"
4545
tag = "v0.2.7"
4646

4747
[dependencies.class_group]
48-
git = "https://github.com/KZen-networks/class-groups"
49-
tag = "v0.1.5"
48+
git = "https://github.com/KZen-networks/class"
49+
tag = "v0.4.4"
5050
optional = true
5151

5252
[dev-dependencies]
@@ -55,7 +55,7 @@ rust-crypto = "0.2"
5555
hex = "0.4"
5656
rocket = { version = "0.4.5", default-features = false }
5757
rocket_contrib = "0.4.5"
58-
reqwest = { version = "0.10", default-features = false, features = ["socks", "blocking", "json"] }
58+
reqwest = { version = "0.10", default-features = false , features = ["socks", "blocking", "json"]}
5959
uuid = { version = "0.8", features = ["v4"] }
6060
serde_json = "1.0"
6161
libsecp256k1 = "0.3.5"
@@ -77,17 +77,30 @@ name = "common"
7777
crate-type = ["lib"]
7878

7979
[[bench]]
80-
name = "cclst"
80+
name = "cclst_keygen"
8181
path = "benches/two_party_ecdsa/cclst_2019/keygen.rs"
8282
required-features = ["cclst"]
8383
harness = false
8484

85+
[[bench]]
86+
name = "cclst_sign"
87+
path = "benches/two_party_ecdsa/cclst_2019/sign.rs"
88+
required-features = ["cclst"]
89+
harness = false
90+
91+
8592
[[bench]]
8693
name = "gg18"
8794
path = "benches/multi_party_ecdsa/gg18/keygen.rs"
8895
harness = false
8996

9097
[[bench]]
91-
name = "lindel2017"
98+
name = "lindel2017_keygen"
9299
path = "benches/two_party_ecdsa/lindell_2017/keygen.rs"
93100
harness = false
101+
102+
103+
[[bench]]
104+
name = "lindel2017_sign"
105+
path = "benches/two_party_ecdsa/lindell_2017/sign.rs"
106+
harness = false

README.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,27 @@ Threshold ECDSA includes two protocols:
1111
- Signing for using the secret shares to generate a signature.
1212

1313
ECDSA is used extensively for crypto-currencies such as Bitcoin, Ethereum (secp256k1 curve), NEO (NIST P-256 curve) and much more.
14-
This library can be used to create MultiSig and ThresholdSig crypto wallet.
14+
This library can be used to create MultiSig and ThresholdSig crypto wallet. For a full background on threshold signatures please read our Binance academy article [Threshold Signatures Explained](https://www.binance.vision/security/threshold-signatures-explained).
1515

16-
## Project Status
16+
## Library Introduction
17+
The library was built with four core design principles in mind:
18+
1. Multi-protocol support
19+
2. Built for cryptography engineers
20+
3. Foolproof
21+
4. Black box use of cryptographic primitives
1722

18-
- The library supports **2P-ECDSA** based on Lindell's crypto 2017 paper [1]. Project [Gotham-city](https://github.com/KZen-networks/gotham-city) is a proof of concept for a full two-party Bitcoin wallet that uses this library. See benchmarks and white paper there.
23+
To learn about the core principles as well as on the [audit](https://github.com/KZen-networks/multi-party-ecdsa/tree/master/audits) process and security of the library, please read our [Intro to multiparty ecdsa library](https://zengo.com/introducing-multi-party-ecdsa-library/) blog post.
1924

20-
- The library supports Gennaro and Goldfeder CCS 2018 protocol [2] for **{t,n}-threshold ECDSA**.
25+
## Use It
2126

22-
- The library supports **2P-ECDSA** based on Castagnos et. al. crypto 2019 paper [3]. To Enable build with `--features=cclst`.
27+
28+
The library implements three different protocols for threshold ECDSA. The protocols presents differnt tradeoffs in terms of parameters, security assumptions and efficiency.
29+
30+
| Protocol | High Level code |
31+
| -------------------------------------------- | -------------------------------------------- |
32+
| Lindell 17 [1] | [Gotham-city](https://github.com/KZen-networks/gotham-city) (accepted to [CIW19](https://ifca.ai/fc19/ciw/program.html)) is a two party bitcoin wallet, including benchmarks. [KMS](https://github.com/KZen-networks/kms-secp256k1) is a Rust wrapper library that implements a general purpose two party key management system. [thresh-sig-js](https://github.com/KZen-networks/thresh-sig-js) is a Javascript SDK |
33+
| Gennaro, Goldfeder 19 [2] ([video](https://www.youtube.com/watch?v=PdfDZIwuZm0)) | [tss-ecdsa-cli](https://github.com/cryptochill/tss-ecdsa-cli) is a wrapper CLI for full threshold access structure, including network and threshold HD keys ([BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)). See [Demo](https://github.com/KZen-networks/multi-party-ecdsa#run-demo) in this library to get better low level understanding|
34+
|Castagnos et. al. 19 [3]| WIP, Currently enabled as a feature in this library. To Enable build with `--features=cclst`.|
2335

2436
## Run Demo
2537

@@ -43,7 +55,13 @@ Run `./gg18_sign_client`. The application should be in the same folder as the `k
4355

4456
### Full demo
4557

46-
Run `./run.sh` (located in `/demo` folder) in the same folder as the excutables (usually `/target/release/examples`. Move `params` file to the same folder). It will spawn a shared state machine, clients in the number of parties and signing requests for the `threshold + 1` first parties.
58+
Run `./run.sh` (located in `/demo` folder) in the main folder. Move `params` file to the same folder as the excutables (usually `/target/release/examples`). The script will spawn a shared state machine, clients in the number of parties and signing requests for the `threshold + 1` first parties.
59+
60+
`sm_manager` rocket server runs in _production_ mode by default. You may modify the `./run.sh` to config it to run in different environments. For example, to run rocket server in _development_:
61+
62+
```
63+
ROCKET_ENV=development ./target/release/examples/sm_manager
64+
```
4765

4866
| !["Multiparty ECDSA Demo"][demo] |
4967
| :------------------------------------------------: |

Rocket.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[development]
2-
address = "127.0.0.1"
2+
address = "0.0.0.0"
33
port = 8001
44
workers = 12
55
keep_alive = 5
@@ -8,7 +8,7 @@ hi = "Hello!" # this is an unused extra; maybe application specific?
88
is_extra = true # this is an unused extra; maybe application specific?
99

1010
[staging]
11-
address = "127.0.0.1"
11+
address = "0.0.0.0"
1212
port = 8001
1313
workers = 8
1414
keep_alive = 5
@@ -17,7 +17,7 @@ log = "normal"
1717
secret_key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg="
1818

1919
[production]
20-
address = "127.0.0.1"
20+
address = "0.0.0.0"
2121
port = 8001
2222
workers = 12
2323
keep_alive = 5

benches/two_party_ecdsa/cclst_2019/keygen.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,43 @@ mod bench {
1010
pub fn bench_full_keygen_party_one_two(c: &mut Criterion) {
1111
c.bench_function("keygen", move |b| {
1212
b.iter(|| {
13+
1314
let (party_one_first_message, comm_witness, ec_key_pair_party1) =
14-
party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share(
15-
ECScalar::from(&BigInt::sample(253)),
16-
);
17-
let (party_two_first_message, _ec_key_pair_party2) =
18-
party_two::KeyGenFirstMsg::create_with_fixed_secret_share(ECScalar::from(
19-
&BigInt::from(10),
15+
party_one::KeyGenFirstMsg::create_commitments_with_fixed_secret_share(ECScalar::from(
16+
&BigInt::sample(253),
2017
));
18+
let (party_two_first_message, _ec_key_pair_party2) =
19+
party_two::KeyGenFirstMsg::create_with_fixed_secret_share(ECScalar::from(&BigInt::from(
20+
10,
21+
)));
2122
let party_one_second_message = party_one::KeyGenSecondMsg::verify_and_decommit(
2223
comm_witness,
2324
&party_two_first_message.d_log_proof,
2425
)
25-
.expect("failed to verify and decommit");
26+
.expect("failed to verify and decommit");
2627

27-
let _party_two_second_message =
28-
party_two::KeyGenSecondMsg::verify_commitments_and_dlog_proof(
29-
&party_one_first_message,
30-
&party_one_second_message,
31-
)
28+
let _party_two_second_message = party_two::KeyGenSecondMsg::verify_commitments_and_dlog_proof(
29+
&party_one_first_message,
30+
&party_one_second_message,
31+
)
3232
.expect("failed to verify commitments and DLog proof");
3333

3434
// init HSMCL keypair:
35-
let hsmcl_key_pair = party_one::HSMCLKeyPair::generate_keypair_and_encrypted_share(
36-
&ec_key_pair_party1,
37-
);
35+
let seed :BigInt = str::parse(
36+
"314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
37+
).unwrap();
38+
let hsmcl_key_pair =
39+
party_one::HSMCLKeyPair::generate_keypair_and_encrypted_share(&ec_key_pair_party1, seed.clone());
3840

3941
let party_one_private =
4042
party_one::Party1Private::set_private_key(&ec_key_pair_party1, &hsmcl_key_pair);
4143

42-
let cldl_proof = party_one::HSMCLKeyPair::generate_zkcldl_proof(
43-
&hsmcl_key_pair,
44-
&party_one_private,
45-
);
44+
let cldl_proof =
45+
party_one::HSMCLKeyPair::generate_zkcldl_proof(&hsmcl_key_pair, &party_one_private, seed.clone());
4646
let _party_two_hsmcl_pub =
4747
party_two::HSMCLPublic::verify_zkcldl_proof(cldl_proof).expect("proof error");
48+
49+
4850
})
4951
});
5052
}

benches/two_party_ecdsa/cclst_2019/sign.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,48 @@ mod bench {
66
use multi_party_ecdsa::protocols::two_party_ecdsa::cclst_2019::party_two::HSMCLPublic;
77
use multi_party_ecdsa::protocols::two_party_ecdsa::cclst_2019::*;
88

9-
pub fn bench_full_keygen_party_one_two(c: &mut Criterion) {
10-
c.bench_function("keygen", move |b| {
9+
pub fn bench_full_sign_party_one_two(c: &mut Criterion) {
10+
c.bench_function("sign", move |b| {
1111
b.iter(|| {
12+
// assume party1 and party2 engaged with KeyGen in the past resulting in
13+
// party1 owning private share and HSMCL key-pair
14+
// party2 owning private share and HSMCL encryption of party1 share
1215
let (_party_one_private_share_gen, _comm_witness, ec_key_pair_party1) =
1316
party_one::KeyGenFirstMsg::create_commitments();
14-
let (party_two_private_share_gen, ec_key_pair_party2) =
15-
party_two::KeyGenFirstMsg::create();
17+
let (party_two_private_share_gen, ec_key_pair_party2) = party_two::KeyGenFirstMsg::create();
18+
19+
let seed: BigInt = str::parse(
20+
"314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
21+
).unwrap();
1622

1723
let party_one_hsmcl_key_pair =
18-
party_one::HSMCLKeyPair::generate_keypair_and_encrypted_share(
19-
&ec_key_pair_party1,
20-
);
24+
party_one::HSMCLKeyPair::generate_keypair_and_encrypted_share(&ec_key_pair_party1, seed);
25+
26+
let party1_private =
27+
party_one::Party1Private::set_private_key(&ec_key_pair_party1, &party_one_hsmcl_key_pair);
2128

22-
let party_two_hsmcl_public = HSMCLPublic {
23-
ek: party_one_hsmcl_key_pair.keypair.pk.clone(),
24-
encrypted_secret_share: party_one_hsmcl_key_pair.encrypted_share.clone(),
25-
};
29+
let party_two_hsmcl_public = HSMCLPublic::set(
30+
&party_one_hsmcl_key_pair.keypair.pk,
31+
&party_one_hsmcl_key_pair.encrypted_share,
32+
);
2633
// creating the ephemeral private shares:
2734

2835
let (eph_party_two_first_message, eph_comm_witness, eph_ec_key_pair_party2) =
2936
party_two::EphKeyGenFirstMsg::create_commitments();
3037
let (eph_party_one_first_message, eph_ec_key_pair_party1) =
3138
party_one::EphKeyGenFirstMsg::create();
32-
let eph_party_two_second_message =
33-
party_two::EphKeyGenSecondMsg::verify_and_decommit(
34-
eph_comm_witness,
35-
&eph_party_one_first_message,
36-
)
39+
let eph_party_two_second_message = party_two::EphKeyGenSecondMsg::verify_and_decommit(
40+
eph_comm_witness,
41+
&eph_party_one_first_message,
42+
)
3743
.expect("party1 DLog proof failed");
3844

3945
let _eph_party_one_second_message =
4046
party_one::EphKeyGenSecondMsg::verify_commitments_and_dlog_proof(
4147
&eph_party_two_first_message,
4248
&eph_party_two_second_message,
4349
)
44-
.expect("failed to verify commitments and DLog proof");
50+
.expect("failed to verify commitments and DLog proof");
4551
let party2_private = party_two::Party2Private::set_private_key(&ec_key_pair_party2);
4652
let message = BigInt::from(1234);
4753

@@ -53,31 +59,24 @@ mod bench {
5359
&message,
5460
);
5561

56-
let party1_private = party_one::Party1Private::set_private_key(
57-
&ec_key_pair_party1,
58-
&party_one_hsmcl_key_pair,
59-
);
60-
6162
let signature = party_one::Signature::compute(
6263
&party1_private,
6364
partial_sig.c3,
6465
&eph_ec_key_pair_party1,
6566
&eph_party_two_second_message.comm_witness.public_share,
6667
);
6768

68-
let pubkey = party_one::compute_pubkey(
69-
&party1_private,
70-
&party_two_private_share_gen.public_share,
71-
);
69+
let pubkey =
70+
party_one::compute_pubkey(&party1_private, &party_two_private_share_gen.public_share);
7271
party_one::verify(&signature, &pubkey, &message).expect("Invalid signature")
7372
})
7473
});
7574
}
7675

7776
criterion_group! {
78-
name = keygen;
77+
name = sign;
7978
config = Criterion::default().sample_size(10);
80-
targets =self::bench_full_keygen_party_one_two}
79+
targets =self::bench_full_sign_party_one_two}
8180
}
8281

83-
criterion_main!(bench::keygen);
82+
criterion_main!(bench::sign);

benches/two_party_ecdsa/lindell_2017/keygen.rs

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,50 +47,39 @@ mod bench {
4747
encrypted_secret_share: paillier_key_pair.encrypted_share.clone(),
4848
};
4949

50+
// zk proof of correct paillier key
5051
let correct_key_proof =
5152
party_one::PaillierKeyPair::generate_ni_proof_correct_key(&paillier_key_pair);
5253
party_two::PaillierPublic::verify_ni_proof_correct_key(
5354
correct_key_proof,
5455
&party_two_paillier.ek,
5556
)
56-
.expect("bad paillier key");
57-
// zk proof of correct paillier key
57+
.expect("bad paillier key");
5858

59-
// zk range proof
60-
let range_proof = party_one::PaillierKeyPair::generate_range_proof(
61-
&paillier_key_pair,
62-
&party_one_private,
63-
);
64-
party_two::PaillierPublic::verify_range_proof(&party_two_paillier, &range_proof)
65-
.expect("range proof error");
59+
//zk_pdl
6660

67-
// pdl proof minus range proof
68-
let (party_two_pdl_first_message, pdl_chal_party2) = party_two_paillier
69-
.pdl_challenge(&party_one_second_message.comm_witness.public_share);
61+
let (party_two_pdl_first_message,mut party_two_pdl_state, party_two_pdl_statement) =
62+
party_two_paillier.pdl_first_message(&party_one_second_message.comm_witness.public_share);
7063

71-
let (party_one_pdl_first_message, pdl_decommit_party1, alpha) =
72-
party_one::PaillierKeyPair::pdl_first_stage(
73-
&party_one_private,
74-
&party_two_pdl_first_message,
75-
);
64+
let (party_one_pdl_first_message, party_one_pdl_state, _party_one_pdl_statment, party_one_pdl_witness) =
65+
party_one::PaillierKeyPair::pdl_first_message(&party_one_private, &party_two_pdl_first_message, &paillier_key_pair );
7666

7767
let party_two_pdl_second_message =
78-
party_two::PaillierPublic::pdl_decommit_c_tag_tag(&pdl_chal_party2);
79-
let party_one_pdl_second_message = party_one::PaillierKeyPair::pdl_second_stage(
80-
&party_two_pdl_first_message,
81-
&party_two_pdl_second_message,
82-
party_one_private,
83-
pdl_decommit_party1,
84-
alpha,
85-
)
86-
.expect("pdl error party2");
68+
party_two::PaillierPublic::pdl_second_message(&party_one_pdl_first_message, &party_two_pdl_statement , &mut party_two_pdl_state).expect("range proof error");
69+
70+
let party_one_pdl_second_message =
71+
party_one::PaillierKeyPair::pdl_second_message(&party_two_pdl_first_message,
72+
&party_two_pdl_second_message,
73+
&party_one_pdl_witness,
74+
&party_one_pdl_state).expect("pdl error from party2 pdl");
75+
8776

88-
party_two::PaillierPublic::verify_pdl(
89-
&pdl_chal_party2,
77+
party_two::PaillierPublic::pdl_finalize(
9078
&party_one_pdl_first_message,
9179
&party_one_pdl_second_message,
92-
)
93-
.expect("pdl error party1")
80+
&party_two_pdl_state)
81+
.expect("pdl_error");
82+
9483
})
9584
});
9685
}

0 commit comments

Comments
 (0)