Skip to main content

frost_bluepallas/
keys.rs

1//! This module contains utilities for FROST key management using the BluePallas curve
2
3use alloc::collections::BTreeMap;
4
5use frost_core::{self as frost};
6use rand_core::{CryptoRng, RngCore};
7
8use crate::{BluePallas, ChallengeMessage, Error, Identifier, SigningKey};
9
10pub type IdentifierList<'a, M> = frost::keys::IdentifierList<'a, BluePallas<M>>;
11
12/// Secret and public key material generated by a dealer performing
13/// [`generate_with_dealer`].
14///
15/// # Security
16///
17/// To derive a FROST(Pallas, Poseidon) keypair, the receiver of the [`SecretShare`] *must* call
18/// .into(), which under the hood also performs validation.
19pub type SecretShare<M> = frost::keys::SecretShare<BluePallas<M>>;
20
21/// A secret scalar value representing a signer's share of the group secret.
22pub type SigningShare<M> = frost::keys::SigningShare<BluePallas<M>>;
23
24/// A public group element that represents a single signer's public verification share.
25pub type VerifyingShare<M> = frost::keys::VerifyingShare<BluePallas<M>>;
26
27/// A FROST(Pallas, Poseidon) keypair, which can be generated either by a trusted dealer or using
28/// a DKG.
29///
30/// When using a central dealer, [`SecretShare`]s are distributed to
31/// participants, who then perform verification, before deriving
32/// [`KeyPackage`]s, which they store to later use during signing.
33pub type KeyPackage<M> = frost::keys::KeyPackage<BluePallas<M>>;
34
35/// Public data that contains all the signers' public keys as well as the
36/// group public key.
37///
38/// Used for verification purposes before publishing a signature.
39pub type PublicKeyPackage<M> = frost::keys::PublicKeyPackage<BluePallas<M>>;
40
41/// Contains the commitments to the coefficients for our secret polynomial _f_,
42/// used to generate participants' key shares.
43///
44/// [`VerifiableSecretSharingCommitment`] contains a set of commitments to the coefficients (which
45/// themselves are scalars) for a secret polynomial f, where f is used to
46/// generate each ith participant's key share f(i). Participants use this set of
47/// commitments to perform verifiable secret sharing.
48///
49/// Note that participants MUST be assured that they have the *same*
50/// [`VerifiableSecretSharingCommitment`], either by performing pairwise comparison, or by using
51/// some agreed-upon public location for publication, where each participant can
52/// ensure that they received the correct (and same) value.
53pub type VerifiableSecretSharingCommitment<M> =
54    frost::keys::VerifiableSecretSharingCommitment<BluePallas<M>>;
55type DealerOutput<M> = (BTreeMap<Identifier<M>, SecretShare<M>>, PublicKeyPackage<M>);
56
57/// Generate a random keypair and split into FROST keyshares.
58pub fn generate_with_dealer<M, RNG: RngCore + CryptoRng>(
59    max_signers: u16,
60    min_signers: u16,
61    identifiers: IdentifierList<'_, M>,
62    mut rng: RNG,
63) -> Result<DealerOutput<M>, Error<M>>
64where
65    M: ChallengeMessage,
66{
67    frost::keys::generate_with_dealer(max_signers, min_signers, identifiers, &mut rng)
68}
69
70/// Splits an existing key into FROST shares.
71///
72/// This is identical to [`generate_with_dealer`] but receives an existing key
73/// instead of generating a fresh one. This is useful in scenarios where
74/// the key needs to be generated externally or must be derived from e.g. a
75/// seed phrase.
76pub fn split<M, R: RngCore + CryptoRng>(
77    key: &SigningKey<M>,
78    max_signers: u16,
79    min_signers: u16,
80    identifiers: IdentifierList<'_, M>,
81    rng: &mut R,
82) -> Result<DealerOutput<M>, Error<M>>
83where
84    M: ChallengeMessage,
85{
86    frost::keys::split(key, max_signers, min_signers, identifiers, rng)
87}
88
89/// Distributed Key Generation (DKG) protocol types and functions.
90pub mod dkg {
91    use super::*;
92    type DkgPart2Output<M> = (
93        round2::SecretPackage<M>,
94        BTreeMap<Identifier<M>, round2::Package<M>>,
95    );
96
97    /// DKG Round 1 structures.
98    pub mod round1 {
99        use super::*;
100
101        /// The secret package that must be kept in memory by the participant
102        /// between the first and second parts of the DKG protocol (round 1).
103        ///
104        /// # Security
105        ///
106        /// This package MUST NOT be sent to other participants!
107        pub type SecretPackage<M> = frost::keys::dkg::round1::SecretPackage<BluePallas<M>>;
108
109        /// The package that must be broadcast by each participant to all other participants
110        /// between the first and second parts of the DKG protocol (round 1).
111        pub type Package<M> = frost::keys::dkg::round1::Package<BluePallas<M>>;
112    }
113
114    /// DKG Round 2 structures.
115    pub mod round2 {
116        use super::*;
117
118        /// The secret package that must be kept in memory by the participant
119        /// between the second and third parts of the DKG protocol (round 2).
120        ///
121        /// # Security
122        ///
123        /// This package MUST NOT be sent to other participants!
124        pub type SecretPackage<M> = frost::keys::dkg::round2::SecretPackage<BluePallas<M>>;
125
126        /// A package that must be sent by each participant to some other participants
127        /// in Round 2 of the DKG protocol. Note that there is one specific package
128        /// for each specific recipient, in contrast to Round 1.
129        ///
130        /// # Security
131        ///
132        /// The package must be sent on an *confidential* and *authenticated* channel.
133        pub type Package<M> = frost::keys::dkg::round2::Package<BluePallas<M>>;
134    }
135
136    /// Performs the first part of the distributed key generation protocol
137    /// for the given participant.
138    ///
139    /// It returns the [`round1::SecretPackage`] that must be kept in memory
140    /// by the participant for the other steps, and the [`round1::Package`] that
141    /// must be sent to other participants.
142    pub fn part1<M, R: RngCore + CryptoRng>(
143        identifier: Identifier<M>,
144        max_signers: u16,
145        min_signers: u16,
146        mut rng: R,
147    ) -> Result<(round1::SecretPackage<M>, round1::Package<M>), Error<M>>
148    where
149        M: ChallengeMessage,
150    {
151        frost::keys::dkg::part1(identifier, max_signers, min_signers, &mut rng)
152    }
153
154    /// Performs the second part of the distributed key generation protocol
155    /// for the participant holding the given [`round1::SecretPackage`],
156    /// given the received [`round1::Package`]s received from the other participants.
157    ///
158    /// It returns the [`round2::SecretPackage`] that must be kept in memory
159    /// by the participant for the final step, and the [`round2::Package`]s that
160    /// must be sent to other participants.
161    pub fn part2<M>(
162        secret_package: round1::SecretPackage<M>,
163        round1_packages: &BTreeMap<Identifier<M>, round1::Package<M>>,
164    ) -> Result<DkgPart2Output<M>, Error<M>>
165    where
166        M: ChallengeMessage,
167    {
168        frost::keys::dkg::part2(secret_package, round1_packages)
169    }
170
171    /// Performs the third and final part of the distributed key generation protocol
172    /// for the participant holding the given [`round2::SecretPackage`],
173    /// given the received [`round1::Package`]s and [`round2::Package`]s received from
174    /// the other participants.
175    ///
176    /// It returns the [`KeyPackage`] that has the long-lived key share for the
177    /// participant, and the [`PublicKeyPackage`]s that has public information
178    /// about all participants; both of which are required to compute FROST
179    /// signatures.
180    pub fn part3<M>(
181        round2_secret_package: &round2::SecretPackage<M>,
182        round1_packages: &BTreeMap<Identifier<M>, round1::Package<M>>,
183        round2_packages: &BTreeMap<Identifier<M>, round2::Package<M>>,
184    ) -> Result<(KeyPackage<M>, PublicKeyPackage<M>), Error<M>>
185    where
186        M: ChallengeMessage,
187    {
188        let (key_package, public_key_package) =
189            frost::keys::dkg::part3(round2_secret_package, round1_packages, round2_packages)?;
190        Ok((key_package, public_key_package))
191    }
192}