Skip to content

Commit a6046dd

Browse files
psiveselyromac
authored andcommitted
Validate shares have the same data length
1 parent df091b0 commit a6046dd

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

src/errors.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ error_chain! {
6464
display("The shares are incompatible with each other because they do not all have the same threshold.")
6565
}
6666

67+
IncompatibleDataLengths(sets: Vec<HashSet<u8>>) {
68+
description("The shares are incompatible with each other because they do not all have the same share data length.")
69+
display("The shares are incompatible with each other because they do not all have the same share data length.")
70+
}
71+
6772
MissingShares(provided: usize, required: u8) {
6873
description("The number of shares provided is insufficient to recover the secret.")
6974
display("{} shares are required to recover the secret, found only {}.", required, provided)

src/share/validation.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,17 @@ pub(crate) fn validate_shares<S: IsShare>(shares: Vec<S>) -> Result<(u8, Vec<S>)
3333
let mut result: Vec<S> = Vec::with_capacity(shares_count);
3434

3535
let mut k_compatibility_sets = HashMap::new();
36+
let mut data_len_compatibility_sets = HashMap::new();
3637

3738
for share in shares {
38-
let (id, threshold) = (share.get_id(), share.get_threshold());
39+
let (id, threshold, data_len) = (share.get_id(), share.get_threshold(), share.get_data().len());
3940

4041
if id < 1 {
4142
bail!(ErrorKind::ShareParsingInvalidShareId(id))
4243
} else if threshold < 2 {
4344
bail!(ErrorKind::ShareParsingInvalidShareThreshold(threshold, id))
45+
} else if data_len < 1 {
46+
bail!(ErrorKind::ShareParsingErrorEmptyShare(id))
4447
}
4548

4649
k_compatibility_sets
@@ -53,9 +56,12 @@ pub(crate) fn validate_shares<S: IsShare>(shares: Vec<S>) -> Result<(u8, Vec<S>)
5356
bail!(ErrorKind::DuplicateShareId(id));
5457
}
5558

56-
if share.get_data().is_empty() {
57-
bail!(ErrorKind::ShareParsingErrorEmptyShare(id))
58-
}
59+
data_len_compatibility_sets
60+
.entry(data_len)
61+
.or_insert_with(HashSet::new);
62+
let data_len_set = data_len_compatibility_sets.get_mut(&data_len).unwrap();
63+
data_len_set.insert(id);
64+
5965

6066
result.push(share);
6167
}
@@ -84,6 +90,23 @@ pub(crate) fn validate_shares<S: IsShare>(shares: Vec<S>) -> Result<(u8, Vec<S>)
8490
bail!(ErrorKind::MissingShares(shares_count, threshold));
8591
}
8692

93+
// Validate share length consistency
94+
let data_len_sets = data_len_compatibility_sets.keys().count();
95+
96+
match data_len_sets {
97+
1 => {} // All shares have the same `data` field len
98+
_ => {
99+
bail! {
100+
ErrorKind::IncompatibleDataLengths(
101+
data_len_compatibility_sets
102+
.values()
103+
.map(|x| x.to_owned())
104+
.collect(),
105+
)
106+
}
107+
}
108+
}
109+
87110
Ok((threshold, result))
88111
}
89112

tests/recovery_errors.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ fn test_recover_duplicate_shares_number() {
6666
recover_secret(&shares, false).unwrap();
6767
}
6868

69+
#[test]
70+
#[should_panic(expected = "IncompatibleDataLengths")]
71+
fn test_recover_incompatible_data_lengths() {
72+
let share1 = "2-1-CgnlCxRNtnkzENE".to_string();
73+
let share2 = "2-2-ChbG46L1zRszs0PPn63XnnupmZTcgYJ3".to_string();
74+
75+
let shares = vec![share1, share2];
76+
77+
recover_secret(&shares, false).unwrap();
78+
}
79+
6980
#[test]
7081
#[should_panic(expected = "MissingShares")]
7182
fn test_recover_too_few_shares() {

0 commit comments

Comments
 (0)