mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Add dealer key generation crate
This commit is contained in:
@@ -41,6 +41,7 @@ schnorr = { package = "schnorr-signatures", path = "../schnorr", version = "^0.5
|
||||
|
||||
dkg = { path = "../dkg", version = "0.6", default-features = false, features = ["std"] }
|
||||
dkg-recovery = { path = "../dkg/recovery", default-features = false, features = ["std"], optional = true }
|
||||
dkg-dealer = { path = "../dkg/dealer", default-features = false, features = ["std"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4"
|
||||
@@ -48,6 +49,7 @@ serde_json = { version = "1", default-features = false, features = ["std"] }
|
||||
|
||||
dkg = { path = "../dkg", default-features = false, features = ["std"] }
|
||||
dkg-recovery = { path = "../dkg/recovery", default-features = false, features = ["std"] }
|
||||
dkg-dealer = { path = "../dkg/dealer", default-features = false, features = ["std"] }
|
||||
|
||||
[features]
|
||||
ed25519 = ["dalek-ff-group", "ciphersuite/ed25519"]
|
||||
@@ -58,4 +60,4 @@ p256 = ["ciphersuite/p256"]
|
||||
|
||||
ed448 = ["minimal-ed448", "ciphersuite/ed448"]
|
||||
|
||||
tests = ["hex", "rand_core/getrandom", "dkg-recovery"]
|
||||
tests = ["hex", "rand_core/getrandom", "dkg-dealer" ,"dkg-recovery"]
|
||||
|
||||
@@ -12,6 +12,10 @@ This library offers ciphersuites compatible with the
|
||||
[IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version
|
||||
15 is supported.
|
||||
|
||||
A variety of testing utilities are provided under the `tests` feature. These
|
||||
are provided with no guarantees and may have completely arbitrary behavior,
|
||||
including panicking for completely well-reasoned input.
|
||||
|
||||
This library was
|
||||
[audited by Cypher Stack in March 2023](https://github.com/serai-dex/serai/raw/e1bb2c191b7123fd260d008e31656d090d559d21/audits/Cypher%20Stack%20crypto%20March%202023/Audit.pdf),
|
||||
culminating in commit
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
use core::ops::Deref;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use ciphersuite::{
|
||||
group::ff::{Field, PrimeField},
|
||||
Ciphersuite,
|
||||
};
|
||||
use dkg::Interpolation;
|
||||
use ciphersuite::Ciphersuite;
|
||||
pub use dkg_recovery::recover_key;
|
||||
|
||||
use crate::{
|
||||
Curve, Participant, ThresholdParams, ThresholdKeys, FrostError,
|
||||
Curve, Participant, ThresholdKeys, FrostError,
|
||||
algorithm::{Algorithm, Hram, IetfSchnorr},
|
||||
sign::{Writable, PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine},
|
||||
};
|
||||
@@ -37,49 +31,11 @@ pub const THRESHOLD: u16 = ((PARTICIPANTS * 2) / 3) + 1;
|
||||
pub fn key_gen<R: RngCore + CryptoRng, C: Ciphersuite>(
|
||||
rng: &mut R,
|
||||
) -> HashMap<Participant, ThresholdKeys<C>> {
|
||||
let coefficients: [_; THRESHOLD as usize] =
|
||||
core::array::from_fn(|_| Zeroizing::new(C::F::random(&mut *rng)));
|
||||
|
||||
fn polynomial<F: PrimeField + Zeroize>(
|
||||
coefficients: &[Zeroizing<F>],
|
||||
l: Participant,
|
||||
) -> Zeroizing<F> {
|
||||
let l = F::from(u64::from(u16::from(l)));
|
||||
// This should never be reached since Participant is explicitly non-zero
|
||||
assert!(l != F::ZERO, "zero participant passed to polynomial");
|
||||
let mut share = Zeroizing::new(F::ZERO);
|
||||
for (idx, coefficient) in coefficients.iter().rev().enumerate() {
|
||||
*share += coefficient.deref();
|
||||
if idx != (coefficients.len() - 1) {
|
||||
*share *= l;
|
||||
}
|
||||
}
|
||||
share
|
||||
}
|
||||
|
||||
let group_key = C::generator() * *coefficients[0];
|
||||
let mut secret_shares = HashMap::with_capacity(PARTICIPANTS as usize);
|
||||
let mut verification_shares = HashMap::with_capacity(PARTICIPANTS as usize);
|
||||
for i in 1 ..= PARTICIPANTS {
|
||||
let i = Participant::new(i).unwrap();
|
||||
let secret_share = polynomial(&coefficients, i);
|
||||
secret_shares.insert(i, secret_share.clone());
|
||||
verification_shares.insert(i, C::generator() * *secret_share);
|
||||
}
|
||||
|
||||
let mut res = HashMap::with_capacity(PARTICIPANTS as usize);
|
||||
for i in 1 ..= PARTICIPANTS {
|
||||
let i = Participant::new(i).unwrap();
|
||||
let keys = ThresholdKeys::new(
|
||||
ThresholdParams::new(THRESHOLD, PARTICIPANTS, i).unwrap(),
|
||||
Interpolation::Lagrange,
|
||||
secret_shares.remove(&i).unwrap(),
|
||||
verification_shares.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(keys.group_key(), group_key);
|
||||
res.insert(i, keys);
|
||||
}
|
||||
let res = dkg_dealer::key_gen::<R, C>(rng, THRESHOLD, PARTICIPANTS).unwrap();
|
||||
assert_eq!(
|
||||
C::generator() * *recover_key(&res.values().cloned().collect::<Vec<_>>()).unwrap(),
|
||||
res.values().next().unwrap().group_key()
|
||||
);
|
||||
res
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user