Skip to content

Commit 4c95859

Browse files
committed
Working.
1 parent 98a8b79 commit 4c95859

File tree

3 files changed

+134
-16
lines changed

3 files changed

+134
-16
lines changed

src/encoding.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ fn generate_shares(
8585

8686
for (group_index, group) in spec.groups().iter().enumerate() {
8787
let group_secret = &group_secrets[group_index];
88-
let member_secrets = split_secret(group.threshold(), group.count(), group_secret, random_generator)
88+
let member_secrets = split_secret(group.member_threshold(), group.member_count(), group_secret, random_generator)
8989
.map_err(Error::ShamirError)?
9090
.into_iter().map(Secret::new)
9191
.collect::<Result<Vec<Secret>, _>>()?;
@@ -96,7 +96,7 @@ fn generate_shares(
9696
spec.group_threshold(),
9797
spec.group_count(),
9898
member_index,
99-
group.threshold(),
99+
group.member_threshold(),
100100
member_secret,
101101
)
102102
}).collect();

src/lib.rs

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub const MIN_SECRET_LEN: usize = bc_shamir::MIN_SECRET_LEN;
22
pub const MAX_SECRET_LEN: usize = bc_shamir::MAX_SECRET_LEN;
33
pub const MAX_SHARE_COUNT: usize = bc_shamir::MAX_SHARE_COUNT;
4+
pub const MAX_GROUPS_COUNT: usize = MAX_SHARE_COUNT;
45
pub const METADATA_LENGTH_BYTES: usize = 5;
56
pub const MIN_SERIALIZE_LENGTH_BYTES: usize = METADATA_LENGTH_BYTES + MIN_SECRET_LEN;
67

@@ -102,20 +103,137 @@ mod tests {
102103
let group2 = GroupSpec::new(2, 3).unwrap();
103104
let spec = Spec::new(2, vec![group1, group2]).unwrap();
104105
let shares = sskr_generate_using(&spec, &secret, &mut rng).unwrap();
105-
println!("shares: {:?}", shares);
106+
// println!("shares: {:?}", shares);
106107
assert_eq!(shares.len(), 2);
107108
assert_eq!(shares[0].len(), 3);
108109
assert_eq!(shares[1].len(), 3);
109110
let flattened_shares = shares.into_iter().flatten().collect::<Vec<_>>();
110111
assert_eq!(flattened_shares.len(), 6);
111112
for share in &flattened_shares {
112113
assert_eq!(share.len(), METADATA_LENGTH_BYTES + secret.len());
113-
println!("share: {}", hex::encode(share));
114+
// println!("share: {}", hex::encode(share));
114115
}
115116

116117
let recovered_share_indexes = vec![0, 1, 3, 5];
117118
let recovered_shares = recovered_share_indexes.iter().map(|index| flattened_shares[*index].clone()).collect::<Vec<_>>();
118119
let recovered_secret = sskr_combine(&recovered_shares).unwrap();
119120
assert_eq!(recovered_secret, secret);
120121
}
122+
123+
fn fisher_yates_shuffle<T>(slice: &mut [T], rng: &mut impl RandomNumberGenerator) {
124+
let mut i = slice.len();
125+
while i > 1 {
126+
i -= 1;
127+
let j = rng.next_in_closed_range(&(0..=i));
128+
slice.swap(i, j);
129+
}
130+
}
131+
132+
#[test]
133+
fn test_shuffle() {
134+
let mut rng = bc_crypto::make_fake_random_number_generator();
135+
let mut v = (0..100).collect::<Vec<_>>();
136+
fisher_yates_shuffle(&mut v, &mut rng);
137+
assert_eq!(v.len(), 100);
138+
assert_eq!(v, [79, 70, 40, 53, 25, 30, 31, 88, 10, 1,
139+
45, 54, 81, 58, 55, 59, 69, 78, 65, 47,
140+
75, 61, 0, 72, 20, 9, 80, 13, 73, 11,
141+
60, 56, 19, 42, 33, 12, 36, 38, 6, 35,
142+
68, 77, 50, 18, 97, 49, 98, 85, 89, 91,
143+
15, 71, 99, 67, 84, 23, 64, 14, 57, 48,
144+
62, 29, 28, 94, 44, 8, 66, 34, 43, 21,
145+
63, 16, 92, 95, 27, 51, 26, 86, 22, 41,
146+
93, 82, 7, 87, 74, 37, 46, 3, 96, 24,
147+
90, 39, 32, 17, 76, 4, 83, 2, 52, 5]);
148+
}
149+
150+
struct RecoverSpec {
151+
secret: Secret,
152+
spec: Spec,
153+
shares: Vec<Vec<Vec<u8>>>,
154+
recovered_group_indexes: Vec<usize>,
155+
recovered_member_indexes: Vec<Vec<usize>>,
156+
recovered_shares: Vec<Vec<u8>>,
157+
}
158+
159+
impl RecoverSpec {
160+
fn new(secret: Secret, spec: Spec, shares: Vec<Vec<Vec<u8>>>, rng: &mut impl RandomNumberGenerator) -> Self {
161+
let mut group_indexes = (0..spec.group_count()).collect::<Vec<_>>();
162+
fisher_yates_shuffle(&mut group_indexes, rng);
163+
let recovered_group_indexes = group_indexes[..spec.group_threshold()].to_vec();
164+
let mut recovered_member_indexes = Vec::new();
165+
for group_index in &recovered_group_indexes {
166+
let group = &spec.groups()[*group_index];
167+
let mut member_indexes = (0..group.member_count()).collect::<Vec<_>>();
168+
fisher_yates_shuffle(&mut member_indexes, rng);
169+
let recovered_member_indexes_for_group = member_indexes[..group.member_threshold()].to_vec();
170+
recovered_member_indexes.push(recovered_member_indexes_for_group);
171+
}
172+
173+
let mut recovered_shares = Vec::new();
174+
for (i, recovered_group_index) in recovered_group_indexes.iter().enumerate() {
175+
let group_shares = &shares[*recovered_group_index];
176+
for recovered_member_index in &recovered_member_indexes[i] {
177+
let member_share = &group_shares[*recovered_member_index];
178+
recovered_shares.push(member_share.clone());
179+
}
180+
}
181+
fisher_yates_shuffle(&mut recovered_shares, rng);
182+
183+
Self {
184+
secret,
185+
spec,
186+
shares,
187+
recovered_group_indexes,
188+
recovered_member_indexes,
189+
recovered_shares,
190+
}
191+
}
192+
193+
fn recover(&self) {
194+
let success = match sskr_combine(&self.recovered_shares) {
195+
Ok(recovered_secret) => recovered_secret == self.secret,
196+
Err(e) => {
197+
println!("error: {:?}", e);
198+
false
199+
},
200+
};
201+
202+
if !success {
203+
println!("secret: {}", hex::encode(self.secret.data()));
204+
println!("spec: {:?}", self.spec);
205+
println!("shares: {:?}", self.shares);
206+
println!("recovered_group_indexes: {:?}", self.recovered_group_indexes);
207+
println!("recovered_member_indexes: {:?}", self.recovered_member_indexes);
208+
println!("recovered_shares: {:?}", &self.recovered_shares);
209+
panic!();
210+
}
211+
}
212+
}
213+
214+
fn one_fuzz_test(rng: &mut impl RandomNumberGenerator) {
215+
let secret_len = rng.next_in_closed_range(&(MIN_SECRET_LEN..=MAX_SECRET_LEN)) & !1;
216+
let secret = Secret::new(rng.random_data(secret_len)).unwrap();
217+
let group_count = rng.next_in_closed_range(&(1..=MAX_GROUPS_COUNT));
218+
let group_specs = (0..group_count).map(|_| {
219+
let member_count = rng.next_in_closed_range(&(1..=MAX_SHARE_COUNT));
220+
let member_threshold = rng.next_in_closed_range(&(1..=member_count));
221+
GroupSpec::new(member_threshold, member_count).unwrap()
222+
}).collect::<Vec<_>>();
223+
let group_threshold = rng.next_in_closed_range(&(1..=group_count));
224+
let spec = Spec::new(group_threshold, group_specs).unwrap();
225+
let shares = sskr_generate_using(&spec, &secret, rng).unwrap();
226+
227+
let recover_spec = RecoverSpec::new(secret, spec, shares, rng);
228+
recover_spec.recover();
229+
}
230+
231+
#[test]
232+
fn fuzz_test() {
233+
let mut rng = bc_crypto::make_fake_random_number_generator();
234+
// let mut rng = bc_crypto::SecureRandomNumberGenerator;
235+
for _ in 0..100 {
236+
one_fuzz_test(&mut rng);
237+
}
238+
}
121239
}

src/spec.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,35 +38,35 @@ impl Spec {
3838
}
3939

4040
pub fn share_count(&self) -> usize {
41-
self.groups.iter().map(|g| g.count()).sum()
41+
self.groups.iter().map(|g| g.member_count()).sum()
4242
}
4343
}
4444

4545
#[derive(Debug, PartialEq)]
4646
pub struct GroupSpec {
47-
threshold: usize,
48-
count: usize,
47+
member_threshold: usize,
48+
member_count: usize,
4949
}
5050

5151
impl GroupSpec {
52-
pub fn new(threshold: usize, count: usize) -> Result<Self, Error> {
53-
if count == 0 {
52+
pub fn new(member_threshold: usize, member_count: usize) -> Result<Self, Error> {
53+
if member_count == 0 {
5454
return Err(Error::NotEnoughShares);
5555
}
56-
if count > MAX_SHARE_COUNT {
56+
if member_count > MAX_SHARE_COUNT {
5757
return Err(Error::TooManyShares);
5858
}
59-
if threshold > count {
59+
if member_threshold > member_count {
6060
return Err(Error::InvalidGroupThreshold);
6161
}
62-
Ok(Self { threshold, count })
62+
Ok(Self { member_threshold, member_count })
6363
}
6464

65-
pub fn threshold(&self) -> usize {
66-
self.threshold
65+
pub fn member_threshold(&self) -> usize {
66+
self.member_threshold
6767
}
6868

69-
pub fn count(&self) -> usize {
70-
self.count
69+
pub fn member_count(&self) -> usize {
70+
self.member_count
7171
}
7272
}

0 commit comments

Comments
 (0)