Skip to content

Commit 4fb4062

Browse files
committed
Fix testbed shamir seed
1 parent bec9c9e commit 4fb4062

5 files changed

Lines changed: 36 additions & 2 deletions

File tree

.cspell/custom-words.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ secretkeybytes
367367
secretservice
368368
sectionauthor
369369
seealso
370+
seedable
370371
seedbytes
371372
Sellsy
372373
SEPA

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libparsec/crates/testbed/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ serde = { workspace = true, features = ["derive", "rc"] }
2121
serde_with = { workspace = true }
2222
rmp-serde = { workspace = true }
2323
lazy_static = { workspace = true }
24+
# Used to deterministically generate shamir recovery shares (see `events.rs`)
25+
rand = { workspace = true, features = ["std", "std_rng"] }
2426
reqwest = { workspace = true, features = ["native-tls", "query"] }
2527
regex = { workspace = true, features = ["std", "perf", "unicode"] }
2628
log = { workspace = true }

libparsec/crates/testbed/src/template/events.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2168,11 +2168,23 @@ impl TestbedEventNewShamirRecovery {
21682168
NonZeroU8::try_from(total_share_count).expect("Share must be > 0")
21692169
};
21702170

2171+
// The shares must be generated deterministically: the testbed materializes
2172+
// this shamir recovery setup independently on the client and on the server,
2173+
// and recovering the secret only works if every party's share belongs to
2174+
// the same secret sharing polynomial. Seeding the RNG from `data_key` (which
2175+
// is itself deterministically derived from the template builder counters)
2176+
// guarantees byte-identical share certificates across processes.
2177+
let mut rng = {
2178+
let mut seed = <rand::rngs::StdRng as rand::SeedableRng>::Seed::default();
2179+
seed.copy_from_slice(self.data_key.as_ref());
2180+
<rand::rngs::StdRng as rand::SeedableRng>::from_seed(seed)
2181+
};
2182+
21712183
let mut shark_shares = ShamirRecoverySecret {
21722184
data_key: self.data_key.clone(),
21732185
reveal_token: self.reveal_token,
21742186
}
2175-
.dump_and_encrypt_into_shares(self.threshold, total_share_count)
2187+
.dump_and_encrypt_into_shares_with_rng(self.threshold, total_share_count, &mut rng)
21762188
.into_iter();
21772189

21782190
for (recipient, shares_count) in &self.per_recipient_shares {

libparsec/crates/types/src/shamir.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,30 @@ impl ShamirRecoverySecret {
4545
&self,
4646
threshold: NonZeroU8,
4747
shares: NonZeroU8,
48+
) -> Vec<ShamirShare> {
49+
self.dump_and_encrypt_into_shares_with_rng(threshold, shares, &mut rand::thread_rng())
50+
}
51+
52+
/// Same as [`Self::dump_and_encrypt_into_shares`], but the share generation is
53+
/// driven by the provided RNG.
54+
///
55+
/// This is only useful for testing purpose: passing a seeded RNG makes the
56+
/// output deterministic, so that a given shamir recovery setup yields
57+
/// byte-identical share certificates across processes (e.g. the testbed
58+
/// generates the certificates independently on the client and on the server,
59+
/// and combining shares obtained from different parties only works if both
60+
/// sides used the same secret sharing polynomial).
61+
pub fn dump_and_encrypt_into_shares_with_rng(
62+
&self,
63+
threshold: NonZeroU8,
64+
shares: NonZeroU8,
65+
rng: &mut impl rand::Rng,
4866
) -> Vec<ShamirShare> {
4967
let secret = self.dump();
5068

5169
let blahaj = blahaj::Sharks(threshold.get());
5270
blahaj
53-
.dealer(&secret)
71+
.dealer_rng(&secret, rng)
5472
.map(ShamirShare)
5573
// Note, unlike what Sharks's documentation claims, at most
5674
// 255 shares can be generated !

0 commit comments

Comments
 (0)