Skip to content

Commit 4f78b6c

Browse files
committed
Fixed #1.
1 parent 1483867 commit 4f78b6c

File tree

2 files changed

+87
-32
lines changed

2 files changed

+87
-32
lines changed

src/encoding.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ fn generate_shares(
171171
struct Group {
172172
group_index: usize,
173173
member_threshold: usize,
174-
count: usize,
175174
member_indexes: Vec<usize>,
176175
member_shares: Vec<Secret>,
177176
}
@@ -181,7 +180,6 @@ impl Group {
181180
Self {
182181
group_index,
183182
member_threshold,
184-
count: 0,
185183
member_indexes: Vec::with_capacity(16),
186184
member_shares: Vec::with_capacity(16),
187185
}
@@ -227,13 +225,15 @@ fn combine_shares(shares: &[SSKRShare]) -> Result<Secret, SSKRError> {
227225
if share.member_threshold() != group.member_threshold {
228226
return Err(SSKRError::MemberThresholdInvalid);
229227
}
230-
for k in 0..group.count {
228+
for k in 0..group.member_indexes.len() {
231229
if share.member_index() == group.member_indexes[k] {
232230
return Err(SSKRError::DuplicateMemberIndex);
233231
}
234232
}
235-
group.member_indexes.push(share.member_index());
236-
group.member_shares.push(share.value().clone());
233+
if group.member_indexes.len() < group.member_threshold {
234+
group.member_indexes.push(share.member_index());
235+
group.member_shares.push(share.value().clone());
236+
}
237237
}
238238
}
239239

src/lib.rs

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ pub const METADATA_SIZE_BYTES: usize = 5;
7272
pub const MIN_SERIALIZE_SIZE_BYTES: usize = METADATA_SIZE_BYTES + MIN_SECRET_LEN;
7373

7474
mod encoding;
75-
pub use encoding::{sskr_generate, sskr_generate_using, sskr_combine};
75+
pub use encoding::{ sskr_generate, sskr_generate_using, sskr_combine };
7676

7777
mod share;
7878

7979
mod secret;
8080
pub use secret::Secret;
8181

8282
mod spec;
83-
pub use spec::{Spec, GroupSpec};
83+
pub use spec::{ Spec, GroupSpec };
8484

8585
mod error;
8686
pub use error::SSKRError;
@@ -129,15 +129,20 @@ mod tests {
129129
}
130130

131131
let recovered_share_indexes = [1, 2, 4];
132-
let recovered_shares = recovered_share_indexes.iter().map(|index| flattened_shares[*index].clone()).collect::<Vec<_>>();
132+
let recovered_shares = recovered_share_indexes
133+
.iter()
134+
.map(|index| flattened_shares[*index].clone())
135+
.collect::<Vec<_>>();
133136
let recovered_secret = sskr_combine(&recovered_shares).unwrap();
134137
assert_eq!(recovered_secret, secret);
135138
}
136139

137140
#[test]
138141
fn test_split_2_7() {
139142
let mut rng = FakeRandomNumberGenerator;
140-
let secret = Secret::new(hex!("204188bfa6b440a1bdfd6753ff55a8241e07af5c5be943db917e3efabc184b1a")).unwrap();
143+
let secret = Secret::new(
144+
hex!("204188bfa6b440a1bdfd6753ff55a8241e07af5c5be943db917e3efabc184b1a")
145+
).unwrap();
141146
let group = GroupSpec::new(2, 7).unwrap();
142147
let spec = Spec::new(1, vec![group]).unwrap();
143148
let shares = sskr_generate_using(&spec, &secret, &mut rng).unwrap();
@@ -152,15 +157,20 @@ mod tests {
152157
}
153158

154159
let recovered_share_indexes = [3, 4];
155-
let recovered_shares = recovered_share_indexes.iter().map(|index| flattened_shares[*index].clone()).collect::<Vec<_>>();
160+
let recovered_shares = recovered_share_indexes
161+
.iter()
162+
.map(|index| flattened_shares[*index].clone())
163+
.collect::<Vec<_>>();
156164
let recovered_secret = sskr_combine(&recovered_shares).unwrap();
157165
assert_eq!(recovered_secret, secret);
158166
}
159167

160168
#[test]
161169
fn test_split_2_3_2_3() {
162170
let mut rng = FakeRandomNumberGenerator;
163-
let secret = Secret::new(hex!("204188bfa6b440a1bdfd6753ff55a8241e07af5c5be943db917e3efabc184b1a")).unwrap();
171+
let secret = Secret::new(
172+
hex!("204188bfa6b440a1bdfd6753ff55a8241e07af5c5be943db917e3efabc184b1a")
173+
).unwrap();
164174
let group1 = GroupSpec::new(2, 3).unwrap();
165175
let group2 = GroupSpec::new(2, 3).unwrap();
166176
let spec = Spec::new(2, vec![group1, group2]).unwrap();
@@ -177,7 +187,10 @@ mod tests {
177187
}
178188

179189
let recovered_share_indexes = [0, 1, 3, 5];
180-
let recovered_shares = recovered_share_indexes.iter().map(|index| flattened_shares[*index].clone()).collect::<Vec<_>>();
190+
let recovered_shares = recovered_share_indexes
191+
.iter()
192+
.map(|index| flattened_shares[*index].clone())
193+
.collect::<Vec<_>>();
181194
let recovered_secret = sskr_combine(&recovered_shares).unwrap();
182195
assert_eq!(recovered_secret, secret);
183196
}
@@ -197,16 +210,16 @@ mod tests {
197210
let mut v = (0..100).collect::<Vec<_>>();
198211
fisher_yates_shuffle(&mut v, &mut rng);
199212
assert_eq!(v.len(), 100);
200-
assert_eq!(v, [79, 70, 40, 53, 25, 30, 31, 88, 10, 1,
201-
45, 54, 81, 58, 55, 59, 69, 78, 65, 47,
202-
75, 61, 0, 72, 20, 9, 80, 13, 73, 11,
203-
60, 56, 19, 42, 33, 12, 36, 38, 6, 35,
204-
68, 77, 50, 18, 97, 49, 98, 85, 89, 91,
205-
15, 71, 99, 67, 84, 23, 64, 14, 57, 48,
206-
62, 29, 28, 94, 44, 8, 66, 34, 43, 21,
207-
63, 16, 92, 95, 27, 51, 26, 86, 22, 41,
208-
93, 82, 7, 87, 74, 37, 46, 3, 96, 24,
209-
90, 39, 32, 17, 76, 4, 83, 2, 52, 5]);
213+
assert_eq!(
214+
v,
215+
[
216+
79, 70, 40, 53, 25, 30, 31, 88, 10, 1, 45, 54, 81, 58, 55, 59, 69, 78, 65, 47, 75, 61,
217+
0, 72, 20, 9, 80, 13, 73, 11, 60, 56, 19, 42, 33, 12, 36, 38, 6, 35, 68, 77, 50, 18,
218+
97, 49, 98, 85, 89, 91, 15, 71, 99, 67, 84, 23, 64, 14, 57, 48, 62, 29, 28, 94, 44, 8,
219+
66, 34, 43, 21, 63, 16, 92, 95, 27, 51, 26, 86, 22, 41, 93, 82, 7, 87, 74, 37, 46, 3,
220+
96, 24, 90, 39, 32, 17, 76, 4, 83, 2, 52, 5,
221+
]
222+
);
210223
}
211224

212225
struct RecoverSpec {
@@ -219,7 +232,12 @@ mod tests {
219232
}
220233

221234
impl RecoverSpec {
222-
fn new(secret: Secret, spec: Spec, shares: Vec<Vec<Vec<u8>>>, rng: &mut impl RandomNumberGenerator) -> Self {
235+
fn new(
236+
secret: Secret,
237+
spec: Spec,
238+
shares: Vec<Vec<Vec<u8>>>,
239+
rng: &mut impl RandomNumberGenerator
240+
) -> Self {
223241
let mut group_indexes = (0..spec.group_count()).collect::<Vec<_>>();
224242
fisher_yates_shuffle(&mut group_indexes, rng);
225243
let recovered_group_indexes = group_indexes[..spec.group_threshold()].to_vec();
@@ -228,7 +246,8 @@ mod tests {
228246
let group = &spec.groups()[*group_index];
229247
let mut member_indexes = (0..group.member_count()).collect::<Vec<_>>();
230248
fisher_yates_shuffle(&mut member_indexes, rng);
231-
let recovered_member_indexes_for_group = member_indexes[..group.member_threshold()].to_vec();
249+
let recovered_member_indexes_for_group =
250+
member_indexes[..group.member_threshold()].to_vec();
232251
recovered_member_indexes.push(recovered_member_indexes_for_group);
233252
}
234253

@@ -268,7 +287,7 @@ mod tests {
268287
Err(e) => {
269288
println!("error: {:?}", e);
270289
false
271-
},
290+
}
272291
};
273292

274293
if !success {
@@ -282,11 +301,13 @@ mod tests {
282301
let secret_len = rng.next_in_closed_range(&(MIN_SECRET_LEN..=MAX_SECRET_LEN)) & !1;
283302
let secret = Secret::new(rng.random_data(secret_len)).unwrap();
284303
let group_count = rng.next_in_closed_range(&(1..=MAX_GROUPS_COUNT));
285-
let group_specs = (0..group_count).map(|_| {
286-
let member_count = rng.next_in_closed_range(&(1..=MAX_SHARE_COUNT));
287-
let member_threshold = rng.next_in_closed_range(&(1..=member_count));
288-
GroupSpec::new(member_threshold, member_count).unwrap()
289-
}).collect::<Vec<_>>();
304+
let group_specs = (0..group_count)
305+
.map(|_| {
306+
let member_count = rng.next_in_closed_range(&(1..=MAX_SHARE_COUNT));
307+
let member_threshold = rng.next_in_closed_range(&(1..=member_count));
308+
GroupSpec::new(member_threshold, member_count).unwrap()
309+
})
310+
.collect::<Vec<_>>();
290311
let group_threshold = rng.next_in_closed_range(&(1..=group_count));
291312
let spec = Spec::new(group_threshold, group_specs).unwrap();
292313
let shares = sskr_generate_using(&spec, &secret, rng).unwrap();
@@ -316,7 +337,7 @@ mod tests {
316337

317338
#[test]
318339
fn example_encode() {
319-
use crate::{Secret, GroupSpec, Spec, sskr_generate, sskr_combine};
340+
use crate::{ Secret, GroupSpec, Spec, sskr_generate, sskr_combine };
320341

321342
let secret_string = b"my secret belongs to me.";
322343
let secret = Secret::new(secret_string).unwrap();
@@ -348,10 +369,44 @@ mod tests {
348369
// Three shares from the second group.
349370
shares[1][0].clone(),
350371
shares[1][1].clone(),
351-
shares[1][4].clone(),
372+
shares[1][4].clone()
352373
];
353374

354375
let recovered_secret = sskr_combine(&recovered_shares).unwrap();
355376
assert_eq!(recovered_secret, secret);
356377
}
378+
379+
/// Test fix for [#1](https://github.com/BlockchainCommons/bc-sskr-rust/issues/1).
380+
#[test]
381+
fn example_encode_3() {
382+
use crate::{ SSKRError, Secret, GroupSpec, Spec, sskr_generate, sskr_combine };
383+
use std::str::from_utf8;
384+
385+
const TEXT: &str = "my secret belongs to me.";
386+
387+
fn roundtrip(m: usize, n: usize) -> Result<Secret, SSKRError> {
388+
let secret = Secret::new(TEXT).unwrap();
389+
let spec = Spec::new(1, vec![GroupSpec::new(m, n).unwrap()]).unwrap();
390+
let shares: Vec<Vec<Vec<u8>>> = sskr_generate(&spec, &secret).unwrap();
391+
sskr_combine(&shares.iter().flatten().collect::<Vec<&Vec<u8>>>())
392+
}
393+
394+
// Good, uses a 2/3 group
395+
{
396+
let result = roundtrip(2, 3);
397+
assert_eq!(from_utf8(result.unwrap().data()).unwrap(), TEXT);
398+
}
399+
400+
// Still ok, uses a 1/1 group
401+
{
402+
let result = roundtrip(1, 1);
403+
assert_eq!(from_utf8(result.unwrap().data()).unwrap(), TEXT);
404+
}
405+
406+
// Fixed, uses a 1/3 group
407+
{
408+
let result = roundtrip(1, 3);
409+
assert_eq!(from_utf8(result.unwrap().data()).unwrap(), TEXT);
410+
}
411+
}
357412
}

0 commit comments

Comments
 (0)