1#![no_std]
16#![allow(non_snake_case)]
17
18extern crate alloc;
19
20#[cfg(any(test, feature = "test-impl"))]
21pub mod tests;
22
23use alloc::{collections::BTreeMap, string::ToString, vec::Vec};
24
25use derive_getters::Getters;
26pub use frost_core;
27
28#[cfg(feature = "serialization")]
29use frost_core::SigningPackage;
30use frost_core::{
31 self as frost,
32 keys::{KeyPackage, PublicKeyPackage, SigningShare, VerifyingShare},
33 round1::{encode_group_commitments, SigningCommitments},
34 serialization::SerializableScalar,
35 CheaterDetection, Ciphersuite, Error, Field, Group, Identifier, Scalar, VerifyingKey,
36};
37
38#[cfg(feature = "serde")]
39use frost_core::serde;
40
41use rand_core::{CryptoRng, RngCore};
44
45trait Randomize<C> {
48 fn randomize(&self, params: &RandomizedParams<C>) -> Result<Self, Error<C>>
49 where
50 Self: Sized,
51 C: Ciphersuite;
52}
53
54pub trait RandomizedCiphersuite: Ciphersuite {
56 fn hash_randomizer(m: &[u8]) -> Option<<<Self::Group as Group>::Field as Field>::Scalar>;
58}
59
60impl<C: Ciphersuite> Randomize<C> for KeyPackage<C> {
61 fn randomize(&self, randomized_params: &RandomizedParams<C>) -> Result<Self, Error<C>>
69 where
70 Self: Sized,
71 C: Ciphersuite,
72 {
73 let verifying_share = self.verifying_share();
74 let randomized_verifying_share = VerifyingShare::<C>::new(
75 verifying_share.to_element() + randomized_params.randomizer_element,
76 );
77
78 let signing_share = self.signing_share();
79 let randomized_signing_share =
80 SigningShare::new(signing_share.to_scalar() + randomized_params.randomizer.to_scalar());
81
82 let randomized_key_package = KeyPackage::new(
83 *self.identifier(),
84 randomized_signing_share,
85 randomized_verifying_share,
86 randomized_params.randomized_verifying_key,
87 *self.min_signers(),
88 );
89 Ok(randomized_key_package)
90 }
91}
92
93impl<C: Ciphersuite> Randomize<C> for PublicKeyPackage<C> {
94 fn randomize(&self, randomized_params: &RandomizedParams<C>) -> Result<Self, Error<C>>
100 where
101 Self: Sized,
102 C: Ciphersuite,
103 {
104 let verifying_shares = self.verifying_shares().clone();
105 let randomized_verifying_shares = verifying_shares
106 .iter()
107 .map(|(identifier, verifying_share)| {
108 (
109 *identifier,
110 VerifyingShare::<C>::new(
111 verifying_share.to_element() + randomized_params.randomizer_element,
112 ),
113 )
114 })
115 .collect();
116
117 Ok(PublicKeyPackage::new_internal(
118 randomized_verifying_shares,
119 randomized_params.randomized_verifying_key,
120 self.min_signers(),
121 ))
122 }
123}
124
125#[deprecated(
130 note = "switch to sign_with_randomizer_seed(), passing a seed generated with RandomizedParams::new_from_commitments()"
131)]
132pub fn sign<C: RandomizedCiphersuite>(
133 signing_package: &frost::SigningPackage<C>,
134 signer_nonces: &frost::round1::SigningNonces<C>,
135 key_package: &frost::keys::KeyPackage<C>,
136 randomizer: Randomizer<C>,
137) -> Result<frost::round2::SignatureShare<C>, Error<C>> {
138 let randomized_params =
139 RandomizedParams::from_randomizer(key_package.verifying_key(), randomizer);
140 let randomized_key_package = key_package.randomize(&randomized_params)?;
141 frost::round2::sign(signing_package, signer_nonces, &randomized_key_package)
142}
143
144pub fn sign_with_randomizer_seed<C: RandomizedCiphersuite>(
149 signing_package: &frost::SigningPackage<C>,
150 signer_nonces: &frost::round1::SigningNonces<C>,
151 key_package: &frost::keys::KeyPackage<C>,
152 randomizer_seed: &[u8],
153) -> Result<frost::round2::SignatureShare<C>, Error<C>> {
154 let randomized_params = RandomizedParams::regenerate_from_seed_and_commitments(
155 key_package.verifying_key(),
156 randomizer_seed,
157 signing_package.signing_commitments(),
158 )?;
159 let randomized_key_package = key_package.randomize(&randomized_params)?;
160 frost::round2::sign(signing_package, signer_nonces, &randomized_key_package)
161}
162
163pub fn aggregate<C>(
168 signing_package: &frost::SigningPackage<C>,
169 signature_shares: &BTreeMap<frost::Identifier<C>, frost::round2::SignatureShare<C>>,
170 pubkeys: &frost::keys::PublicKeyPackage<C>,
171 randomized_params: &RandomizedParams<C>,
172) -> Result<frost_core::Signature<C>, Error<C>>
173where
174 C: Ciphersuite,
175{
176 let randomized_public_key_package = pubkeys.randomize(randomized_params)?;
177 frost::aggregate(
178 signing_package,
179 signature_shares,
180 &randomized_public_key_package,
181 )
182}
183
184pub fn aggregate_custom<C>(
189 signing_package: &frost::SigningPackage<C>,
190 signature_shares: &BTreeMap<frost::Identifier<C>, frost::round2::SignatureShare<C>>,
191 pubkeys: &frost::keys::PublicKeyPackage<C>,
192 cheater_detection: CheaterDetection,
193 randomized_params: &RandomizedParams<C>,
194) -> Result<frost_core::Signature<C>, Error<C>>
195where
196 C: Ciphersuite,
197{
198 let randomized_public_key_package = pubkeys.randomize(randomized_params)?;
199 frost::aggregate_custom(
200 signing_package,
201 signature_shares,
202 &randomized_public_key_package,
203 cheater_detection,
204 )
205}
206
207#[derive(Copy, Clone, PartialEq, Eq)]
209#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
210#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))]
211#[cfg_attr(feature = "serde", serde(transparent))]
212#[cfg_attr(feature = "serde", serde(crate = "self::serde"))]
213pub struct Randomizer<C: Ciphersuite>(SerializableScalar<C>);
214
215impl<C> Randomizer<C>
216where
217 C: Ciphersuite,
218{
219 pub(crate) fn to_scalar(self) -> Scalar<C> {
220 self.0 .0
221 }
222}
223
224impl<C> Randomizer<C>
225where
226 C: RandomizedCiphersuite,
227{
228 #[cfg(feature = "serialization")]
234 #[deprecated(
235 note = "switch to new_from_commitments(), passing the commitments from SigningPackage"
236 )]
237 pub fn new<R: RngCore + CryptoRng>(
238 mut rng: R,
239 signing_package: &SigningPackage<C>,
240 ) -> Result<Self, Error<C>> {
241 let rng_randomizer = <<C::Group as Group>::Field as Field>::random(&mut rng);
242 Self::from_randomizer_and_signing_package(rng_randomizer, signing_package)
243 }
244
245 #[cfg(feature = "serialization")]
248 fn from_randomizer_and_signing_package(
249 rng_randomizer: <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar,
250 signing_package: &SigningPackage<C>,
251 ) -> Result<Randomizer<C>, Error<C>>
252 where
253 C: RandomizedCiphersuite,
254 {
255 let randomizer = C::hash_randomizer(
256 &[
257 <<C::Group as Group>::Field>::serialize(&rng_randomizer).as_ref(),
258 &signing_package.serialize()?,
259 ]
260 .concat(),
261 )
262 .ok_or(Error::SerializationError)?;
263 Ok(Self(SerializableScalar(randomizer)))
264 }
265
266 pub fn new_from_commitments<R: RngCore + CryptoRng>(
277 mut rng: R,
278 signing_commitments: &BTreeMap<Identifier<C>, SigningCommitments<C>>,
279 ) -> Result<(Self, Vec<u8>), Error<C>> {
280 let zero = <<C::Group as Group>::Field as Field>::zero();
282 let ns = <<C::Group as Group>::Field as Field>::serialize(&zero)
283 .as_ref()
284 .len();
285 let mut randomizer_seed = alloc::vec![0; ns];
286 rng.fill_bytes(&mut randomizer_seed);
287 Ok((
288 Self::regenerate_from_seed_and_commitments(&randomizer_seed, signing_commitments)?,
289 randomizer_seed,
290 ))
291 }
292
293 pub fn regenerate_from_seed_and_commitments(
308 randomizer_seed: &[u8],
309 signing_commitments: &BTreeMap<Identifier<C>, SigningCommitments<C>>,
310 ) -> Result<Randomizer<C>, Error<C>>
311 where
312 C: RandomizedCiphersuite,
313 {
314 let randomizer = C::hash_randomizer(
315 &[
316 randomizer_seed,
317 &encode_group_commitments(signing_commitments)?,
318 ]
319 .concat(),
320 )
321 .ok_or(Error::SerializationError)?;
322 Ok(Self(SerializableScalar(randomizer)))
323 }
324}
325
326impl<C> Randomizer<C>
327where
328 C: Ciphersuite,
329{
330 pub fn from_scalar(scalar: Scalar<C>) -> Self {
337 Self(SerializableScalar(scalar))
338 }
339
340 pub fn serialize(&self) -> Vec<u8> {
342 self.0.serialize()
343 }
344
345 pub fn deserialize(buf: &[u8]) -> Result<Self, Error<C>> {
348 Ok(Self(SerializableScalar::deserialize(buf)?))
349 }
350}
351
352impl<C> core::fmt::Debug for Randomizer<C>
353where
354 C: Ciphersuite,
355{
356 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
357 f.debug_tuple("Randomizer")
358 .field(&hex::encode(self.0.serialize()))
359 .finish()
360 }
361}
362
363#[derive(Clone, PartialEq, Eq, Getters)]
365pub struct RandomizedParams<C: Ciphersuite> {
366 randomizer: Randomizer<C>,
368 randomizer_element: <C::Group as Group>::Element,
370 randomized_verifying_key: frost_core::VerifyingKey<C>,
372}
373
374impl<C> RandomizedParams<C>
375where
376 C: RandomizedCiphersuite,
377{
378 #[cfg(feature = "serialization")]
381 #[deprecated(
382 note = "switch to new_from_commitments(), passing the commitments from SigningPackage"
383 )]
384 pub fn new<R: RngCore + CryptoRng>(
385 group_verifying_key: &VerifyingKey<C>,
386 signing_package: &SigningPackage<C>,
387 rng: R,
388 ) -> Result<Self, Error<C>> {
389 #[allow(deprecated)]
390 Ok(Self::from_randomizer(
391 group_verifying_key,
392 Randomizer::new(rng, signing_package)?,
393 ))
394 }
395
396 pub fn new_from_commitments<R: RngCore + CryptoRng>(
408 group_verifying_key: &VerifyingKey<C>,
409 signing_commitments: &BTreeMap<Identifier<C>, SigningCommitments<C>>,
410 rng: R,
411 ) -> Result<(Self, Vec<u8>), Error<C>> {
412 let (randomizer, randomizer_seed) =
413 Randomizer::new_from_commitments(rng, signing_commitments)?;
414 Ok((
415 Self::from_randomizer(group_verifying_key, randomizer),
416 randomizer_seed,
417 ))
418 }
419
420 pub fn regenerate_from_seed_and_commitments(
441 group_verifying_key: &VerifyingKey<C>,
442 randomizer_seed: &[u8],
443 signing_commitments: &BTreeMap<Identifier<C>, SigningCommitments<C>>,
444 ) -> Result<Self, Error<C>> {
445 let randomizer =
446 Randomizer::regenerate_from_seed_and_commitments(randomizer_seed, signing_commitments)?;
447 Ok(Self::from_randomizer(group_verifying_key, randomizer))
448 }
449}
450
451impl<C> RandomizedParams<C>
452where
453 C: Ciphersuite,
454{
455 pub fn from_randomizer(
461 group_verifying_key: &VerifyingKey<C>,
462 randomizer: Randomizer<C>,
463 ) -> Self {
464 let randomizer_element = <C::Group as Group>::generator() * randomizer.to_scalar();
465 let verifying_key_element = group_verifying_key.to_element();
466 let randomized_verifying_key_element = verifying_key_element + randomizer_element;
467 let randomized_verifying_key = VerifyingKey::<C>::new(randomized_verifying_key_element);
468
469 Self {
470 randomizer,
471 randomizer_element,
472 randomized_verifying_key,
473 }
474 }
475}
476
477impl<C> core::fmt::Debug for RandomizedParams<C>
478where
479 C: Ciphersuite,
480{
481 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
482 f.debug_struct("RandomizedParams")
483 .field("randomizer", &self.randomizer)
484 .field(
485 "randomizer_element",
486 &<C::Group as Group>::serialize(&self.randomizer_element)
487 .map(hex::encode)
488 .unwrap_or("<invalid>".to_string()),
489 )
490 .field("randomized_verifying_key", &self.randomized_verifying_key)
491 .finish()
492 }
493}