dkg_dealer/
lib.rs

1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![doc = include_str!("../README.md")]
3#![no_std]
4
5use core::ops::Deref;
6use std_shims::{vec::Vec, collections::HashMap};
7
8use zeroize::{Zeroize, Zeroizing};
9use rand_core::{RngCore, CryptoRng};
10
11use ciphersuite::{
12  group::ff::{Field, PrimeField},
13  Ciphersuite,
14};
15pub use dkg::*;
16
17/// Create a key via a dealer key generation protocol.
18pub fn key_gen<R: RngCore + CryptoRng, C: Ciphersuite>(
19  rng: &mut R,
20  threshold: u16,
21  participants: u16,
22) -> Result<HashMap<Participant, ThresholdKeys<C>>, DkgError> {
23  let mut coefficients = Vec::with_capacity(usize::from(participants));
24  // `.max(1)` so we always generate the 0th coefficient which we'll share
25  for _ in 0 .. threshold.max(1) {
26    coefficients.push(Zeroizing::new(C::F::random(&mut *rng)));
27  }
28
29  fn polynomial<F: PrimeField + Zeroize>(
30    coefficients: &[Zeroizing<F>],
31    l: Participant,
32  ) -> Zeroizing<F> {
33    let l = F::from(u64::from(u16::from(l)));
34    // This should never be reached since Participant is explicitly non-zero
35    assert!(l != F::ZERO, "zero participant passed to polynomial");
36    let mut share = Zeroizing::new(F::ZERO);
37    for (idx, coefficient) in coefficients.iter().rev().enumerate() {
38      *share += coefficient.deref();
39      if idx != (coefficients.len() - 1) {
40        *share *= l;
41      }
42    }
43    share
44  }
45
46  let group_key = C::generator() * coefficients[0].deref();
47  let mut secret_shares = HashMap::with_capacity(participants as usize);
48  let mut verification_shares = HashMap::with_capacity(participants as usize);
49  for i in 1 ..= participants {
50    let i = Participant::new(i).expect("non-zero u16 wasn't a valid Participant index");
51    let secret_share = polynomial(&coefficients, i);
52    secret_shares.insert(i, secret_share.clone());
53    verification_shares.insert(i, C::generator() * *secret_share);
54  }
55
56  let mut res = HashMap::with_capacity(participants as usize);
57  for (i, secret_share) in secret_shares {
58    let keys = ThresholdKeys::new(
59      ThresholdParams::new(threshold, participants, i)?,
60      Interpolation::Lagrange,
61      secret_share,
62      verification_shares.clone(),
63    )?;
64    debug_assert_eq!(keys.group_key(), group_key);
65    res.insert(i, keys);
66  }
67  Ok(res)
68}