The diagram below shows the distributed key generation process. Dashed lines represent data being sent through an authenticated and confidential communication channel. Note that the first dashed line requires a broadcast channel
To start the DKG, each participant calls
passing its identifier, the desired threshold and total number of participants.
(Thus, they need to agree on those parameters via some mechanism which is up to
the application.) It returns a
round1::SecretPackage and a
use rand::thread_rng; use std::collections::BTreeMap; use frost_ristretto255 as frost; let mut rng = thread_rng(); let max_signers = 5; let min_signers = 3; // Ask the user which identifier they would like to use. You can create // an identifier from a non-zero u16 or derive from an arbitrary string. // Some fixed examples follow (each participant must choose a different identifier) let participant_identifier = Identifier::try_from(7u16)?; let participant_identifier = Identifier::derive("firstname.lastname@example.org".as_bytes())?; let (round1_secret_package, round1_package) = frost::keys::dkg::part1( participant_identifier, max_signers, min_signers, &mut rng, )?;
Check the crate documentation for a full working example; keep in mind it's an artificial one since everything runs in the same program.
round1::SecretPackage must be kept in memory to use in the next round. The
round1::Package must be sent to all other participants using a broadcast
channel to ensure
that all participants receive the same value.
A broadcast channel in this context is not simply broadcasting the value to all participants. It requires running a protocol to ensure that all participants have the same value or that the protocol is aborted. Check the linked Terminology section for more details.
Failure in using a proper broadcast channel will make the key generation insecure.
Upon receiving the other participants'
round1::Packages, each participant then
passing their own previously created
round1::SecretPackage and the list of
round1::Packages. It returns a
round2::SecretPackage and a
BTreeMap mapping other participants's
let (round2_secret_package, round2_packages) = frost::keys::dkg::part2(round1_secret_package, round1_packages)?;
round2::SecretPackage must be kept in memory for the next part; the
round1::SecretPackage is consumed and is not required anymore.
round2::Packages must be sent to their respective participants with the
Identifiers, using an authenticated and confidential communication
Finally, upon receiving the other participant's
round2::Package, the DKG is
concluded by calling
passing the same
round1::Packages received in Part 2, the
just received, and the previously stored
round2::SecretPackage for the
participant. It returns a
KeyPackage, with the participant's secret share,
PublicKeyPackage containing the group verifying key:
let (key_package, pubkey_package) = frost::keys::dkg::part3( round2_secret_package, round1_packages, round2_packages, )?;