Skip to content

Commit c8a5dd0

Browse files
committed
Completed reconstruct secret shares
1 parent 9861e7d commit c8a5dd0

File tree

5 files changed

+227
-9
lines changed

5 files changed

+227
-9
lines changed

README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,19 @@ Thus PVSS can be used to share a secret among a group of participants so that ei
1515
## Build
1616

1717
```bash
18-
cargo build
18+
cargo build --release
1919
```
2020

2121
## Test
2222

2323
```bash
24-
cargo test
24+
cargo test --release
25+
```
26+
27+
## Example
28+
29+
```rust
30+
cargo run --release --example mpvss
2531
```
2632

2733
### Usage
@@ -115,7 +121,26 @@ assert_eq!(
115121
Once a participant collected at least `threshold` shares the secret can be reconstructed.
116122

117123
```rust
124+
let share_boxs = [s1, s2, s3];
125+
let r1 = p1
126+
.mpvss
127+
.reconstruct(&share_boxs, &distribute_shares_box)
128+
.unwrap();
129+
let r2 = p2
130+
.mpvss
131+
.reconstruct(&share_boxs, &distribute_shares_box)
132+
.unwrap();
133+
let r3 = p3
134+
.mpvss
135+
.reconstruct(&share_boxs, &distribute_shares_box)
136+
.unwrap();
118137

138+
let r1_str = String::from_utf8(r1.to_biguint().unwrap().to_bytes_be()).unwrap();
139+
assert_eq!(secret_message.clone(), r1_str);
140+
let r2_str = String::from_utf8(r2.to_biguint().unwrap().to_bytes_be()).unwrap();
141+
assert_eq!(secret_message.clone(), r2_str);
142+
let r3_str = String::from_utf8(r3.to_biguint().unwrap().to_bytes_be()).unwrap();
143+
assert_eq!(secret_message.clone(), r3_str);
119144
```
120145

121146
## Related References:

examples/mpvss.rs

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,103 @@
22
//
33
// Code is licensed under AGPL License, Version 3.0.
44

5-
use mpvss_rs::MPVSS;
5+
use mpvss_rs::Participant;
6+
use num_bigint::{BigUint, ToBigInt};
67

78
fn main() {
8-
let mpvss = MPVSS::new();
9-
let secret_message = String::from("Hello MPVSS.");
10-
drop(mpvss);
11-
drop(secret_message);
9+
let secret_message = String::from("Hello MPVSS Example.");
10+
let secret = BigUint::from_bytes_be(&secret_message.as_bytes());
11+
let mut dealer = Participant::new();
12+
dealer.initialize();
13+
let mut p1 = Participant::new();
14+
let mut p2 = Participant::new();
15+
let mut p3 = Participant::new();
16+
p1.initialize();
17+
p2.initialize();
18+
p3.initialize();
19+
20+
let distribute_shares_box = dealer.distribute_secret(
21+
secret.to_bigint().unwrap(),
22+
vec![
23+
p1.publickey.clone(),
24+
p2.publickey.clone(),
25+
p3.publickey.clone(),
26+
],
27+
3,
28+
);
29+
30+
assert_eq!(
31+
p1.mpvss.verify_distribution_shares(&distribute_shares_box),
32+
true
33+
);
34+
35+
assert_eq!(
36+
p2.mpvss.verify_distribution_shares(&distribute_shares_box),
37+
true
38+
);
39+
40+
assert_eq!(
41+
p3.mpvss.verify_distribution_shares(&distribute_shares_box),
42+
true
43+
);
44+
45+
// p1 extracts the share. [p2 and p3 do this as well.]
46+
let s1 = p1
47+
.extract_secret_share(&distribute_shares_box, &p1.privatekey)
48+
.unwrap();
49+
50+
// p1, p2 and p3 exchange their descrypted shares.
51+
// ...
52+
let s2 = p2
53+
.extract_secret_share(&distribute_shares_box, &p2.privatekey)
54+
.unwrap();
55+
let s3 = p3
56+
.extract_secret_share(&distribute_shares_box, &p3.privatekey)
57+
.unwrap();
58+
59+
// p1 verifies the share received from p2. [Actually everybody verifies every received share.]
60+
61+
assert_eq!(
62+
p1.mpvss
63+
.verify(&s2, &distribute_shares_box.shares[&p2.publickey]),
64+
true
65+
);
66+
67+
assert_eq!(
68+
p2.mpvss
69+
.verify(&s3, &distribute_shares_box.shares[&p3.publickey]),
70+
true
71+
);
72+
73+
assert_eq!(
74+
p3.mpvss
75+
.verify(&s1, &distribute_shares_box.shares[&s1.publickey]),
76+
true
77+
);
78+
79+
let share_boxs = [s1, s2, s3];
80+
let r1 = p1
81+
.mpvss
82+
.reconstruct(&share_boxs, &distribute_shares_box)
83+
.unwrap();
84+
let r2 = p2
85+
.mpvss
86+
.reconstruct(&share_boxs, &distribute_shares_box)
87+
.unwrap();
88+
let r3 = p3
89+
.mpvss
90+
.reconstruct(&share_boxs, &distribute_shares_box)
91+
.unwrap();
92+
93+
let r1_str = String::from_utf8(r1.to_biguint().unwrap().to_bytes_be()).unwrap();
94+
assert_eq!(secret_message.clone(), r1_str);
95+
let r2_str = String::from_utf8(r2.to_biguint().unwrap().to_bytes_be()).unwrap();
96+
assert_eq!(secret_message.clone(), r2_str);
97+
let r3_str = String::from_utf8(r3.to_biguint().unwrap().to_bytes_be()).unwrap();
98+
assert_eq!(secret_message.clone(), r3_str);
99+
100+
println!("secret message: {}", secret_message);
101+
println!("r1 str: {}", r1_str);
102+
println!("r2 str: {}", r2_str);
103+
println!("r3 str: {}", r3_str);
12104
}

src/mpvss.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ impl MPVSS {
249249
}
250250

251251
// Reconstruct the secret = H(G^s) xor U
252-
let secret_hash = sha2::Sha256::digest(&secret.to_biguint().unwrap().to_bytes_le());
252+
let secret_hash =
253+
sha2::Sha256::digest(&secret.to_biguint().unwrap().to_str_radix(10).as_bytes());
253254
let hash_big_uint =
254255
BigUint::from_bytes_be(&secret_hash[..]).mod_floor(&self.q.to_biguint().unwrap());
255256
let decrypted_secret = hash_big_uint ^ distribute_share_box.U.clone().to_biguint().unwrap();

src/participant.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ mod tests {
371371
use super::Polynomial;
372372
use super::MPVSS;
373373
use super::{DistributionSharesBox, ShareBox};
374+
use num_traits::{One, Zero};
374375

375376
struct Setup {
376377
pub mpvss: MPVSS,
@@ -519,4 +520,82 @@ mod tests {
519520
true
520521
);
521522
}
523+
524+
#[test]
525+
fn test_reconstruction_with_all_participants() {
526+
let distribution_shares_box = get_distribute_shares_box();
527+
let share_box1 = get_share_box();
528+
let mut share_box2 = ShareBox::new();
529+
share_box2.init(
530+
BigInt::from(132222922),
531+
BigInt::from(157312059),
532+
BigInt::zero(),
533+
BigInt::zero(),
534+
);
535+
let mut share_box3 = ShareBox::new();
536+
share_box3.init(
537+
BigInt::from(65136827),
538+
BigInt::from(63399333),
539+
BigInt::zero(),
540+
BigInt::zero(),
541+
);
542+
543+
let setup = Setup::new();
544+
let share_boxs = [share_box1, share_box2, share_box3];
545+
let reconstructed_secret = setup
546+
.mpvss
547+
.reconstruct(&share_boxs, &distribution_shares_box)
548+
.unwrap();
549+
assert_eq!(reconstructed_secret, setup.secret);
550+
}
551+
552+
// (3,4) threshhold reconstruct, participant 3 is not available, 1,2,4 is available
553+
#[test]
554+
fn test_reconstruction_with_sub_group() {
555+
let share_box1 = get_share_box();
556+
let mut share_box2 = ShareBox::new();
557+
share_box2.init(
558+
BigInt::from(132222922),
559+
BigInt::from(157312059),
560+
BigInt::zero(),
561+
BigInt::zero(),
562+
);
563+
564+
let public_key4 = BigInt::from(42);
565+
let mut share_box4 = ShareBox::new();
566+
share_box4.init(
567+
public_key4.clone(),
568+
BigInt::from(59066181),
569+
BigInt::zero(),
570+
BigInt::zero(),
571+
);
572+
573+
let mut positions = HashMap::new();
574+
positions.insert(share_box1.clone().publickey, 1_i64);
575+
positions.insert(share_box2.clone().publickey, 2_i64);
576+
positions.insert(share_box4.clone().publickey, 4_i64);
577+
// remove participant 3 public key
578+
positions.remove(&BigInt::from(65136827));
579+
*positions.get_mut(&public_key4).unwrap() = 4_i64;
580+
581+
let mut distribution_shares_box = DistributionSharesBox::new();
582+
distribution_shares_box.init(
583+
vec![BigInt::zero(), BigInt::one(), BigInt::from(2)],
584+
positions,
585+
HashMap::new(),
586+
vec![],
587+
BigInt::zero(),
588+
HashMap::new(),
589+
BigInt::from(1284073502),
590+
);
591+
592+
let setup = Setup::new();
593+
let share_boxs = [share_box1, share_box2, share_box4];
594+
let reconstructed_secret = setup
595+
.mpvss
596+
.reconstruct(&share_boxs, &distribution_shares_box)
597+
.unwrap();
598+
assert_eq!(reconstructed_secret, setup.secret);
599+
600+
}
522601
}

tests/mpvss_tests.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn test_secret_str_utf8() {
1616
}
1717

1818
#[test]
19-
fn test_mpvss_distribute_verify() {
19+
fn test_mpvss_distribute_verify_reconstruct() {
2020
let secret_message = String::from("Hello MPVSS.");
2121
let secret = BigUint::from_bytes_be(&secret_message.as_bytes());
2222
let mut dealer = Participant::new();
@@ -86,4 +86,25 @@ fn test_mpvss_distribute_verify() {
8686
.verify(&s1, &distribute_shares_box.shares[&s1.publickey]),
8787
true
8888
);
89+
90+
let share_boxs = [s1, s2, s3];
91+
let r1 = p1
92+
.mpvss
93+
.reconstruct(&share_boxs, &distribute_shares_box)
94+
.unwrap();
95+
let r2 = p2
96+
.mpvss
97+
.reconstruct(&share_boxs, &distribute_shares_box)
98+
.unwrap();
99+
let r3 = p3
100+
.mpvss
101+
.reconstruct(&share_boxs, &distribute_shares_box)
102+
.unwrap();
103+
104+
let r1_str = String::from_utf8(r1.to_biguint().unwrap().to_bytes_be()).unwrap();
105+
assert_eq!(secret_message.clone(), r1_str);
106+
let r2_str = String::from_utf8(r2.to_biguint().unwrap().to_bytes_be()).unwrap();
107+
assert_eq!(secret_message.clone(), r2_str);
108+
let r3_str = String::from_utf8(r3.to_biguint().unwrap().to_bytes_be()).unwrap();
109+
assert_eq!(secret_message.clone(), r3_str);
89110
}

0 commit comments

Comments
 (0)