Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cggmp24-keygen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,14 @@ enum Bug {
ZeroShare,
#[displaydoc("shared public key is zero - probability of that is negligible")]
ZeroPk,
#[displaydoc("too few parties: n must be at least 2")]
TooFewParties,
#[displaydoc("threshold too small: t must be at least 2")]
ThresholdTooSmall,
#[displaydoc("threshold too large: t must not exceed n")]
ThresholdTooLarge,
#[displaydoc("party index out of range: i must be less than n")]
PartyIndexOutOfRange,
}

/// Distributed key generation protocol
Expand Down
13 changes: 13 additions & 0 deletions cggmp24-keygen/src/threshold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ where
R: RngCore + CryptoRng,
M: Mpc<ProtocolMessage = Msg<E, L, D>>,
{
if n < 2 {
return Err(Bug::TooFewParties.into());
}
if t < 2 {
return Err(Bug::ThresholdTooSmall.into());
}
if t > n {
return Err(Bug::ThresholdTooLarge.into());
}
if i >= n {
return Err(Bug::PartyIndexOutOfRange.into());
}

tracer.protocol_begins();

tracer.stage("Setup networking");
Expand Down
66 changes: 66 additions & 0 deletions tests/tests/it/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,72 @@ where
validate_keygen_output::<E, Hd>(&mut rng, &key_shares);
}

cggmp24_tests::test_suite! {
test: threshold_keygen_rejects_invalid_params,
generics: all_curves,
suites: {
t_greater_than_n: (5, 3),
t_too_small: (1, 3),
n_too_small: (2, 1),
}
}
fn threshold_keygen_rejects_invalid_params<E>(t: u16, n: u16)
where
E: Curve + cggmp24_tests::CurveParams,
{
let mut rng = DevRng::new();

let eid: [u8; 32] = rng.gen();
let eid = ExecutionId::new(&eid);

let sim_n = n.max(1);
let results = round_based::sim::run(sim_n, |i, party| {
let party = cggmp24_tests::buffer_outgoing(party);
let mut party_rng = rng.fork();

async move {
cggmp24::keygen::<E>(eid, i, n)
.set_security_level::<E::SecurityLevel>()
.set_digest::<E::Digest>()
.set_threshold(t)
.start(&mut party_rng, party)
.await
}
})
.unwrap()
.into_vec();

for result in &results {
assert!(result.is_err(), "expected error for t={t}, n={n}, got Ok");
}
}

#[test]
fn threshold_keygen_rejects_i_out_of_range() {
let mut rng = DevRng::new();

let eid: [u8; 32] = rng.gen();
let eid = ExecutionId::new(&eid);

let (t, n) = (2, 3);
let bad_i = n;
let result = round_based::sim::run(1, |_sim_i, party| {
let party = cggmp24_tests::buffer_outgoing(party);
let mut party_rng = rng.fork();

async move {
cggmp24::keygen::<cggmp24::supported_curves::Secp256k1>(eid, bad_i, n)
.set_threshold(t)
.start(&mut party_rng, party)
.await
}
})
.unwrap()
.into_vec();

assert!(result[0].is_err(), "expected error for i >= n, got Ok");
}

fn validate_keygen_output<E: generic_ec::Curve, Hd: cggmp24_tests::OptionalHd<E>>(
rng: &mut impl rand::RngCore,
key_shares: &[cggmp24::IncompleteKeyShare<E>],
Expand Down