frost_bluepallas/
signing_utilities.rs1use alloc::collections::BTreeMap;
4
5use crate::{BluePallas, ChallengeMessage};
6use rand_core::{CryptoRng, RngCore};
7
8type SignResult<M> = Result<
9 (
10 frost_core::Signature<BluePallas<M>>,
11 frost_core::VerifyingKey<BluePallas<M>>,
12 ),
13 frost_core::Error<BluePallas<M>>,
14>;
15
16pub fn sign_from_packages<M, R: RngCore + CryptoRng>(
18 message: &[u8],
19 shares: BTreeMap<
20 frost_core::Identifier<BluePallas<M>>,
21 frost_core::keys::SecretShare<BluePallas<M>>,
22 >,
23 pubkey_package: frost_core::keys::PublicKeyPackage<BluePallas<M>>,
24 mut rng: R,
25) -> SignResult<M>
26where
27 M: ChallengeMessage,
28{
29 let min_signers = pubkey_package.verifying_shares().len().min(3);
30
31 let mut key_packages: BTreeMap<_, _> = BTreeMap::new();
35
36 for (identifier, secret_share) in shares {
37 let key_package = frost_core::keys::KeyPackage::try_from(secret_share)?;
38 key_packages.insert(identifier, key_package);
39 }
40
41 let mut nonces_map = BTreeMap::new();
42 let mut commitments_map = BTreeMap::new();
43
44 for participant_index in 1..=min_signers {
50 let participant_identifier = frost_core::Identifier::try_from(participant_index as u16)
51 .map_err(|_| frost_core::Error::MalformedIdentifier)?;
52 let key_package = &key_packages[&participant_identifier];
53 let (nonces, commitments) =
56 frost_core::round1::commit(key_package.signing_share(), &mut rng);
57 nonces_map.insert(participant_identifier, nonces);
62 commitments_map.insert(participant_identifier, commitments);
63 }
64
65 let mut signature_shares = BTreeMap::new();
69 let signing_package = frost_core::SigningPackage::new(commitments_map, message);
70
71 for participant_identifier in nonces_map.keys() {
77 let key_package = &key_packages[participant_identifier];
78
79 let nonces = &nonces_map[participant_identifier];
80
81 let signature_share = frost_core::round2::sign(&signing_package, nonces, key_package)?;
83
84 signature_shares.insert(*participant_identifier, signature_share);
87 }
88
89 let group_signature =
96 frost_core::aggregate(&signing_package, &signature_shares, &pubkey_package)?;
97 let pk = pubkey_package.verifying_key();
98
99 Ok((group_signature, *pk))
100}
101
102pub fn generate_signature_random<M, R: RngCore + CryptoRng>(
105 message: &[u8],
106 mut rng: R,
107) -> SignResult<M>
108where
109 M: ChallengeMessage,
110{
111 let max_signers = 5;
112 let min_signers = 3;
113 let (shares, pubkey_package) = frost_core::keys::generate_with_dealer(
114 max_signers,
115 min_signers,
116 frost_core::keys::IdentifierList::Default,
117 &mut rng,
118 )?;
119
120 sign_from_packages(message, shares, pubkey_package, rng)
121}
122
123pub fn generate_signature_from_sk<M, R: RngCore + CryptoRng>(
126 message: &[u8],
127 signing_key: &frost_core::SigningKey<BluePallas<M>>,
128 mut rng: R,
129) -> SignResult<M>
130where
131 M: ChallengeMessage,
132{
133 let max_signers = 5;
134 let min_signers = 3;
135 let (shares, pubkey_package) = frost_core::keys::split(
136 signing_key,
137 max_signers,
138 min_signers,
139 frost_core::keys::IdentifierList::Default,
140 &mut rng,
141 )?;
142
143 sign_from_packages(message, shares, pubkey_package, rng)
144}