Expand description
Committed Pedersen’s distributed key generation (DKG).
DKG allows to securely generate shared secret without a need for a trusted
dealer. Compare with Feldman’s verifiable secret sharing implemented in the sharing
module
which requires a trusted dealer.
This implementation is based on Pedersen’s DKG, which was shown by Gennaro et al. to contain a flaw allowing an adversary to bias distribution of the shared public key. We try to prevent this kind of possible attacks by forcing the parties to commit to their public key shares before receiving public shares from other parties.
§Examples
Decentralized key generation for 2-of-3 threshold encryption.
let mut rng = thread_rng();
let params = Params::new(3, 2);
// Initialize participants.
let participants = (0..3).map(|i| {
ParticipantCollectingCommitments::<Ristretto>::new(params, i, &mut rng)
});
let mut participants: Vec<_> = participants.collect();
// Publish commitments from all participants...
let commitments: Vec<_> = participants
.iter()
.map(|participant| participant.commitment())
.collect();
// ...and consume them from each participant's perspective.
for (i, participant) in participants.iter_mut().enumerate() {
for (j, &commitment) in commitments.iter().enumerate() {
if i != j {
participant.insert_commitment(j, commitment);
}
}
}
// Transition all participants to the next stage: exchanging polynomials.
let mut participants: Vec<_> = participants
.into_iter()
.map(|participant| participant.finish_commitment_phase())
.collect();
// Publish each participant's polynomial...
let infos: Vec<_> = participants
.iter()
.map(|participant| participant.public_info().into_owned())
.collect();
// ...and consume them from each participant's perspective.
for (i, participant) in participants.iter_mut().enumerate() {
for (j, info) in infos.iter().enumerate() {
if i != j {
participant.insert_public_polynomial(j, info.clone())?;
}
}
}
// Transition all participants to the final phase: exchanging secrets.
let mut participants: Vec<_> = participants
.into_iter()
.map(|participant| participant.finish_polynomials_phase())
.collect();
// Exchange shares (this should happen over secure peer-to-peer channels).
for i in 0..3 {
for j in 0..3 {
if i == j { continue; }
let share = participants[i].secret_share_for_participant(j);
participants[j].insert_secret_share(i, share)?;
}
}
// Finalize all participants.
let participants = participants
.into_iter()
.map(|participant| participant.complete())
.collect::<Result<Vec<_>, _>>()?;
// Check that the shared key is the same for all participants.
let expected_key = participants[0].key_set().shared_key();
for participant in &participants {
assert_eq!(participant.key_set().shared_key(), expected_key);
}
// Participants can then jointly decrypt messages as showcased
// in the example for the `sharing` module.
Structs§
- Opening for a hash commitment used in Pedersen’s distributed key generation.
- Participant state during the first stage of the committed Pedersen’s distributed key generation.
- Participant state during the second stage of the committed Pedersen’s distributed key generation.
- Participant state during the third and final stage of the committed Pedersen’s distributed key generation.
- Public participant information in the distributed key generation protocol. Returned by
ParticipantCollectingPolynomials::public_info()
.
Enums§
- Errors that can occur during the distributed key generation.