mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-23 03:59:22 +00:00
Update to FROST v10
Further expands documentation to near-completion.
This commit is contained in:
parent
7870084b9e
commit
2b7c9378c0
16 changed files with 95 additions and 65 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4541,7 +4541,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "modular-frost"
|
name = "modular-frost"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dalek-ff-group",
|
"dalek-ff-group",
|
||||||
"dleq",
|
"dleq",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "modular-frost"
|
name = "modular-frost"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
description = "Modular implementation of FROST over ff/group"
|
description = "Modular implementation of FROST over ff/group"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/serai-dex/serai"
|
repository = "https://github.com/serai-dex/serai"
|
||||||
|
|
|
@ -10,4 +10,4 @@ integrating with existing systems.
|
||||||
|
|
||||||
This library offers ciphersuites compatible with the
|
This library offers ciphersuites compatible with the
|
||||||
[IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version
|
[IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version
|
||||||
8 is supported.
|
10 is supported.
|
||||||
|
|
|
@ -8,8 +8,10 @@ use transcript::Transcript;
|
||||||
use crate::{Curve, FrostError, FrostView, schnorr};
|
use crate::{Curve, FrostError, FrostView, schnorr};
|
||||||
pub use schnorr::SchnorrSignature;
|
pub use schnorr::SchnorrSignature;
|
||||||
|
|
||||||
/// Algorithm to use FROST with.
|
/// Algorithm trait usable by the FROST signing machine to produce signatures..
|
||||||
pub trait Algorithm<C: Curve>: Clone {
|
pub trait Algorithm<C: Curve>: Clone {
|
||||||
|
/// The transcript format this algorithm uses. This likely should NOT be the IETF-compatible
|
||||||
|
/// transcript included in this crate.
|
||||||
type Transcript: Transcript + Clone + Debug;
|
type Transcript: Transcript + Clone + Debug;
|
||||||
/// The resulting type of the signatures this algorithm will produce.
|
/// The resulting type of the signatures this algorithm will produce.
|
||||||
type Signature: Clone + PartialEq + Debug;
|
type Signature: Clone + PartialEq + Debug;
|
||||||
|
@ -58,7 +60,8 @@ pub trait Algorithm<C: Curve>: Clone {
|
||||||
fn verify_share(&self, verification_share: C::G, nonces: &[Vec<C::G>], share: C::F) -> bool;
|
fn verify_share(&self, verification_share: C::G, nonces: &[Vec<C::G>], share: C::F) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transcript which will create an IETF compliant serialization for the binding factor
|
/// IETF-compliant transcript. This is incredibly naive and should not be used within larger
|
||||||
|
/// protocols.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct IetfTranscript(Vec<u8>);
|
pub struct IetfTranscript(Vec<u8>);
|
||||||
impl Transcript for IetfTranscript {
|
impl Transcript for IetfTranscript {
|
||||||
|
@ -83,13 +86,15 @@ impl Transcript for IetfTranscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HRAm usable by the included Schnorr signature algorithm to generate challenges.
|
||||||
pub trait Hram<C: Curve>: Clone {
|
pub trait Hram<C: Curve>: Clone {
|
||||||
/// HRAM function to generate a challenge.
|
/// HRAm function to generate a challenge.
|
||||||
/// H2 from the IETF draft, despite having a different argument set (not being pre-formatted).
|
/// H2 from the IETF draft, despite having a different argument set (not being pre-formatted).
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F;
|
fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// IETF-compliant Schnorr signature algorithm ((R, s) where s = r + cx).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Schnorr<C: Curve, H: Hram<C>> {
|
pub struct Schnorr<C: Curve, H: Hram<C>> {
|
||||||
transcript: IetfTranscript,
|
transcript: IetfTranscript,
|
||||||
|
@ -109,7 +114,6 @@ impl<C: Curve, H: Hram<C>> Schnorr<C, H> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of Schnorr signatures for use with FROST.
|
|
||||||
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
|
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
|
||||||
type Transcript = IetfTranscript;
|
type Transcript = IetfTranscript;
|
||||||
type Signature = SchnorrSignature<C>;
|
type Signature = SchnorrSignature<C>;
|
||||||
|
|
|
@ -74,7 +74,7 @@ dalek_curve!(
|
||||||
IetfRistrettoHram,
|
IetfRistrettoHram,
|
||||||
RistrettoPoint,
|
RistrettoPoint,
|
||||||
b"ristretto",
|
b"ristretto",
|
||||||
b"FROST-RISTRETTO255-SHA512-v8",
|
b"FROST-RISTRETTO255-SHA512-v10",
|
||||||
b"chal",
|
b"chal",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -85,6 +85,6 @@ dalek_curve!(
|
||||||
IetfEd25519Hram,
|
IetfEd25519Hram,
|
||||||
EdwardsPoint,
|
EdwardsPoint,
|
||||||
b"edwards25519",
|
b"edwards25519",
|
||||||
b"FROST-ED25519-SHA512-v8",
|
b"FROST-ED25519-SHA512-v10",
|
||||||
b"",
|
b"",
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,7 @@ use minimal_ed448::{scalar::Scalar, point::Point};
|
||||||
|
|
||||||
use crate::{curve::Curve, algorithm::Hram};
|
use crate::{curve::Curve, algorithm::Hram};
|
||||||
|
|
||||||
const CONTEXT: &[u8] = b"FROST-ED448-SHAKE256-v8";
|
const CONTEXT: &[u8] = b"FROST-ED448-SHAKE256-v10";
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||||
pub struct Ed448;
|
pub struct Ed448;
|
||||||
|
|
|
@ -92,7 +92,7 @@ macro_rules! kp_curve {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "p256")]
|
#[cfg(feature = "p256")]
|
||||||
kp_curve!("p256", p256, P256, IetfP256Hram, b"P-256", b"FROST-P256-SHA256-v8");
|
kp_curve!("p256", p256, P256, IetfP256Hram, b"P-256", b"FROST-P256-SHA256-v10");
|
||||||
|
|
||||||
#[cfg(feature = "secp256k1")]
|
#[cfg(feature = "secp256k1")]
|
||||||
kp_curve!(
|
kp_curve!(
|
||||||
|
@ -101,5 +101,5 @@ kp_curve!(
|
||||||
Secp256k1,
|
Secp256k1,
|
||||||
IetfSecp256k1Hram,
|
IetfSecp256k1Hram,
|
||||||
b"secp256k1",
|
b"secp256k1",
|
||||||
b"FROST-secp256k1-SHA256-v8"
|
b"FROST-secp256k1-SHA256-v10"
|
||||||
);
|
);
|
||||||
|
|
|
@ -249,12 +249,14 @@ fn complete_r2<Re: Read, R: RngCore + CryptoRng, C: Curve>(
|
||||||
Ok(FrostCore { params, secret_share, group_key: stripes[0], verification_shares })
|
Ok(FrostCore { params, secret_share, group_key: stripes[0], verification_shares })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State machine to begin the key generation protocol.
|
||||||
pub struct KeyGenMachine<C: Curve> {
|
pub struct KeyGenMachine<C: Curve> {
|
||||||
params: FrostParams,
|
params: FrostParams,
|
||||||
context: String,
|
context: String,
|
||||||
_curve: PhantomData<C>,
|
_curve: PhantomData<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advancement of the key generation state machine.
|
||||||
#[derive(Zeroize)]
|
#[derive(Zeroize)]
|
||||||
pub struct SecretShareMachine<C: Curve> {
|
pub struct SecretShareMachine<C: Curve> {
|
||||||
#[zeroize(skip)]
|
#[zeroize(skip)]
|
||||||
|
@ -272,6 +274,7 @@ impl<C: Curve> Drop for SecretShareMachine<C> {
|
||||||
}
|
}
|
||||||
impl<C: Curve> ZeroizeOnDrop for SecretShareMachine<C> {}
|
impl<C: Curve> ZeroizeOnDrop for SecretShareMachine<C> {}
|
||||||
|
|
||||||
|
/// Final step of the key generation protocol.
|
||||||
#[derive(Zeroize)]
|
#[derive(Zeroize)]
|
||||||
pub struct KeyMachine<C: Curve> {
|
pub struct KeyMachine<C: Curve> {
|
||||||
#[zeroize(skip)]
|
#[zeroize(skip)]
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//!
|
//!
|
||||||
//! This library offers ciphersuites compatible with the
|
//! This library offers ciphersuites compatible with the
|
||||||
//! [IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version
|
//! [IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version
|
||||||
//! 8 is supported.
|
//! 10 is supported.
|
||||||
|
|
||||||
use core::fmt::{self, Debug};
|
use core::fmt::{self, Debug};
|
||||||
use std::{io::Read, sync::Arc, collections::HashMap};
|
use std::{io::Read, sync::Arc, collections::HashMap};
|
||||||
|
@ -111,6 +111,7 @@ impl FrostParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Various errors possible during key generation/signing.
|
||||||
#[derive(Copy, Clone, Error, Debug)]
|
#[derive(Copy, Clone, Error, Debug)]
|
||||||
pub enum FrostError {
|
pub enum FrostError {
|
||||||
#[error("a parameter was 0 (required {0}, participants {1})")]
|
#[error("a parameter was 0 (required {0}, participants {1})")]
|
||||||
|
|
|
@ -60,6 +60,7 @@ fn transcript<G: GroupEncoding>(key: G, i: u16) -> RecommendedTranscript {
|
||||||
transcript
|
transcript
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Proof of valid promotion to another generator.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct GeneratorProof<C: Curve> {
|
pub struct GeneratorProof<C: Curve> {
|
||||||
share: C::G,
|
share: C::G,
|
||||||
|
@ -80,18 +81,21 @@ impl<C: Curve> GeneratorProof<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Promote a set of keys from one curve to another, where the elliptic curve is the same.
|
||||||
|
/// Since the Curve trait additionally specifies a generator, this provides an O(n) way to update
|
||||||
|
/// the generator used with keys. The key generation protocol itself is exponential.
|
||||||
pub struct GeneratorPromotion<C1: Curve, C2: Curve> {
|
pub struct GeneratorPromotion<C1: Curve, C2: Curve> {
|
||||||
base: FrostKeys<C1>,
|
base: FrostKeys<C1>,
|
||||||
proof: GeneratorProof<C1>,
|
proof: GeneratorProof<C1>,
|
||||||
_c2: PhantomData<C2>,
|
_c2: PhantomData<C2>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Promote a set of keys from one generator to another.
|
|
||||||
// The linear DLEq proofs are much more efficient than an exponential key gen
|
|
||||||
impl<C1: Curve, C2: Curve> GeneratorPromotion<C1, C2>
|
impl<C1: Curve, C2: Curve> GeneratorPromotion<C1, C2>
|
||||||
where
|
where
|
||||||
C2: Curve<F = C1::F, G = C1::G>,
|
C2: Curve<F = C1::F, G = C1::G>,
|
||||||
{
|
{
|
||||||
|
/// Begin promoting keys from one curve to another. Returns a proof this share was properly
|
||||||
|
/// promoted.
|
||||||
pub fn promote<R: RngCore + CryptoRng>(
|
pub fn promote<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
base: FrostKeys<C1>,
|
base: FrostKeys<C1>,
|
||||||
|
@ -110,6 +114,7 @@ where
|
||||||
(GeneratorPromotion { base, proof, _c2: PhantomData::<C2> }, proof)
|
(GeneratorPromotion { base, proof, _c2: PhantomData::<C2> }, proof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Complete promotion by taking in the proofs from all other participants.
|
||||||
pub fn complete(
|
pub fn complete(
|
||||||
self,
|
self,
|
||||||
proofs: &HashMap<u16, GeneratorProof<C1>>,
|
proofs: &HashMap<u16, GeneratorProof<C1>>,
|
||||||
|
|
|
@ -11,6 +11,7 @@ use multiexp::BatchVerifier;
|
||||||
|
|
||||||
use crate::Curve;
|
use crate::Curve;
|
||||||
|
|
||||||
|
/// A Schnorr signature of the form (R, s) where s = r + cx.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub struct SchnorrSignature<C: Curve> {
|
pub struct SchnorrSignature<C: Curve> {
|
||||||
|
|
|
@ -191,7 +191,10 @@ fn sign_with_share<Re: Read, C: Curve, A: Algorithm<C>>(
|
||||||
// Parse the commitments
|
// Parse the commitments
|
||||||
for l in ¶ms.view.included {
|
for l in ¶ms.view.included {
|
||||||
{
|
{
|
||||||
params.algorithm.transcript().append_message(b"participant", &l.to_be_bytes());
|
params
|
||||||
|
.algorithm
|
||||||
|
.transcript()
|
||||||
|
.append_message(b"participant", C::F::from(u64::from(*l)).to_repr().as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
// While this doesn't note which nonce/basepoint this is for, those are expected to be
|
// While this doesn't note which nonce/basepoint this is for, those are expected to be
|
||||||
|
@ -274,7 +277,7 @@ fn sign_with_share<Re: Read, C: Curve, A: Algorithm<C>>(
|
||||||
// Generate the per-signer binding factors
|
// Generate the per-signer binding factors
|
||||||
for (l, commitments) in B.iter_mut() {
|
for (l, commitments) in B.iter_mut() {
|
||||||
let mut rho_transcript = rho_transcript.clone();
|
let mut rho_transcript = rho_transcript.clone();
|
||||||
rho_transcript.append_message(b"participant", &l.to_be_bytes());
|
rho_transcript.append_message(b"participant", C::F::from(u64::from(*l)).to_repr().as_ref());
|
||||||
commitments.1 = C::hash_binding_factor(rho_transcript.challenge(b"rho").as_ref());
|
commitments.1 = C::hash_binding_factor(rho_transcript.challenge(b"rho").as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,6 +368,7 @@ fn complete<Re: Read, C: Curve, A: Algorithm<C>>(
|
||||||
Err(FrostError::InternalError("everyone had a valid share yet the signature was still invalid"))
|
Err(FrostError::InternalError("everyone had a valid share yet the signature was still invalid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for the initial state machine of a two-round signing protocol.
|
||||||
pub trait PreprocessMachine {
|
pub trait PreprocessMachine {
|
||||||
type Signature: Clone + PartialEq + fmt::Debug;
|
type Signature: Clone + PartialEq + fmt::Debug;
|
||||||
type SignMachine: SignMachine<Self::Signature>;
|
type SignMachine: SignMachine<Self::Signature>;
|
||||||
|
@ -374,6 +378,7 @@ pub trait PreprocessMachine {
|
||||||
fn preprocess<R: RngCore + CryptoRng>(self, rng: &mut R) -> (Self::SignMachine, Vec<u8>);
|
fn preprocess<R: RngCore + CryptoRng>(self, rng: &mut R) -> (Self::SignMachine, Vec<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for the second machine of a two-round signing protocol.
|
||||||
pub trait SignMachine<S> {
|
pub trait SignMachine<S> {
|
||||||
type SignatureMachine: SignatureMachine<S>;
|
type SignatureMachine: SignatureMachine<S>;
|
||||||
|
|
||||||
|
@ -387,6 +392,7 @@ pub trait SignMachine<S> {
|
||||||
) -> Result<(Self::SignatureMachine, Vec<u8>), FrostError>;
|
) -> Result<(Self::SignatureMachine, Vec<u8>), FrostError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for the final machine of a two-round signing protocol.
|
||||||
pub trait SignatureMachine<S> {
|
pub trait SignatureMachine<S> {
|
||||||
/// Complete signing.
|
/// Complete signing.
|
||||||
/// Takes in everyone elses' shares. Returns the signature.
|
/// Takes in everyone elses' shares. Returns the signature.
|
||||||
|
@ -398,11 +404,13 @@ pub struct AlgorithmMachine<C: Curve, A: Algorithm<C>> {
|
||||||
params: Params<C, A>,
|
params: Params<C, A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Next step of the state machine for the signing process.
|
||||||
pub struct AlgorithmSignMachine<C: Curve, A: Algorithm<C>> {
|
pub struct AlgorithmSignMachine<C: Curve, A: Algorithm<C>> {
|
||||||
params: Params<C, A>,
|
params: Params<C, A>,
|
||||||
preprocess: PreprocessPackage<C>,
|
preprocess: PreprocessPackage<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Final step of the state machine for the signing process.
|
||||||
pub struct AlgorithmSignatureMachine<C: Curve, A: Algorithm<C>> {
|
pub struct AlgorithmSignatureMachine<C: Curve, A: Algorithm<C>> {
|
||||||
params: Params<C, A>,
|
params: Params<C, A>,
|
||||||
sign: Package<C>,
|
sign: Package<C>,
|
||||||
|
|
|
@ -24,20 +24,20 @@ fn ristretto_vectors() {
|
||||||
included: &[1, 3],
|
included: &[1, 3],
|
||||||
nonces: &[
|
nonces: &[
|
||||||
[
|
[
|
||||||
"1eaee906e0554a5e533415e971eefa909f3c614c7c75e27f381b0270a9afe308",
|
"de3e8f526dcb51a1b9b48cc284aeca27c385aa3ba1a92a0c8440d51e1a1d2f00",
|
||||||
"16175fc2e7545baf7180e8f5b6e1e73c4f2769323cc76754bdd79fe93ab0bd0b",
|
"fa8dca5ec7a05d5a7b782be847ba3dde1509de1dbcf0569fc980cff795db5404",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"48d78b8c2de1a515513f9d3fc464a19a72304fac522f17cc647706cb22c21403",
|
"e07061a9ab6735de9a75b0c64f086c5b999894611d0cdc03f85c4e87c8aae602",
|
||||||
"5c0f10966b3f1386660a87de0fafd69decbe9ffae1a152a88b7d83bb4fb1c908",
|
"38b17578e8e6ad4077071ce6b0bf9cb85ac35fee7868dcb6d9bfa97f0e153e0e",
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
sig_shares: &[
|
sig_shares: &[
|
||||||
"5ae13621ebeef844e39454eb3478a50c4531d25939e1065f44f5b04a8535090e",
|
"a5f046916a6a111672111e47f9825586e1188da8a0f3b7c61f2b6b432c636e07",
|
||||||
"aa432dcf274a9441c205e76fe43497be99efe374f9853477bd5add2075f6970c",
|
"4c175c7e43bd197980c2021774036eb288f54179f079fbf21b7d2f9f52846401",
|
||||||
],
|
],
|
||||||
sig: "9c407badb8cacf10f306d94e31fb2a71d6a8398039802b4d80a1278472397206".to_owned() +
|
sig: "94b11def3f919503c3544452ad2a59f198f64cc323bd758bb1c65b42032a7473".to_owned() +
|
||||||
"17516e93f8d57a2ecffd43b83ab35db6de20b6ce32673bd601508e6bfa2ba10a",
|
"f107a30fae272b8ff2d3205e6d86c3386a0ecf21916db3b93ba89ae27ee7d208",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -61,20 +61,20 @@ fn ed25519_vectors() {
|
||||||
included: &[1, 3],
|
included: &[1, 3],
|
||||||
nonces: &[
|
nonces: &[
|
||||||
[
|
[
|
||||||
"1c406170127e33142b8611bc02bf14d5909e49d5cb87150eff3ec9804212920c",
|
"4e64f59e90a3b9cdce346fae68eb0e459532c8ca1ad59a566c3ee2c67bf0100b",
|
||||||
"5be4edde8b7acd79528721191626810c94fbc2bcc814b7a67d301fbd7fc16e07",
|
"470c660895c6db164ee6564120eec71023fa5297f09c663bb8171646c5632d00",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"795f87122f05b7efc4b1a52f435c3d28597411b1a6fec198ce9c818c5451c401",
|
"6fc516495dbb364b807cdd0c2e5e3f58aa4914a53fed33cc340033979bb07304",
|
||||||
"c9193aaef37bc074ea3286d0361c815f7201bf764cd9e7d8bb4eb5ecca840a09",
|
"0837e770a88147d41ff39138ca23b35d6cf303a4f148294755ede4b7e760d701",
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
sig_shares: &[
|
sig_shares: &[
|
||||||
"1f16a3989b4aa2cc3782a503331b9a21d7ba56c9c5455d06981b5425306c9d01",
|
"3f2eb12735e5b39da97e884a6caadf6bb83f1efcec709d6f66333d0d67ebe707",
|
||||||
"4c8f33c301c05871b434a686847d5818417a01e50a59e9e7fddaefde7d244207",
|
"79e572b8632fbb928519dd2eff793de8784a56d582ae48c807d39b0dc5b93509",
|
||||||
],
|
],
|
||||||
sig: "1aff2259ecb59cfcbb36ae77e02a9b134422abeae47cf7ff56c85fdf90932b18".to_owned() +
|
sig: "e31e69a4e10d5ca2307c4a0d12cd86e3fceee550e55cb5b3f47c7ad6dbb38884".to_owned() +
|
||||||
"6ba5d65b9d0afb3decb64b8ab798f239183558aed09e46ee95f64304ae90df08",
|
"cb3f2e837eb15cd858fb6dd68c2a3e3f318a74d16f1fe6376e06d91a2ca51d01",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,47 +86,47 @@ fn ed448_non_ietf() {
|
||||||
nonces: &[
|
nonces: &[
|
||||||
[
|
[
|
||||||
concat!(
|
concat!(
|
||||||
"f770bcb22f3c0acac7f09d3b757f13f31b53489776ede2cff944b4c0",
|
"06f2e15b05d29a50f0686a890259f4dcf66147a80809ed9e50926f5f",
|
||||||
"cd28bb7dfbd33809e87201e152beeb552292eb748efa5267fa2dcd20",
|
"173fe23a0627561efa003724dc270effc47a30bc4d80aba30725401d",
|
||||||
"00"
|
"00"
|
||||||
),
|
),
|
||||||
concat!(
|
concat!(
|
||||||
"d3196c7f14b1a99f1715053c00fa3a30b0fe9cbeb461068c262b1714",
|
"e0482e611c34f191d1c13a09bc8bbf4bda68db4de32aa7908849b02b",
|
||||||
"78458a15598cc1c33cd415a766577996a6efcc520c411abf0280c816",
|
"a912cfba46c805e2d8560ab9437e343e1dde6b481a2bae527e111b2c",
|
||||||
"00"
|
"00"
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
concat!(
|
concat!(
|
||||||
"9172a7cea56b7f564ed93116adf078ee013e4160e2687489ea580bc6",
|
"295c56447c070157e6bc3c83ed2afca194569e07d0ad27d28a40dec2",
|
||||||
"f034f10e58db0b0cdf98bf1d3c85b2eb1f30b8b6df57b3611d205d2e",
|
"c4107c07d507db20da1be62ea6976b8e53ab5d26e225c663f2e71511",
|
||||||
"00"
|
"00"
|
||||||
),
|
),
|
||||||
concat!(
|
concat!(
|
||||||
"3b60b4dc036b21441620a36c84b0ec780267a9275b411a495b182dc6",
|
"b97303a6c5ab12b6ad310834361033a19d99dfdf93109da721da35c3",
|
||||||
"bfc812d1a21d93142d375b7ed80314d1693b61c1f42e20c575a4530e",
|
"abbc5f29df33b3402692bef9f005bb8ea00af5ba20cc688360fd8831",
|
||||||
"00"
|
"00"
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
sig_shares: &[
|
sig_shares: &[
|
||||||
concat!(
|
concat!(
|
||||||
"95aeb18a46bac9e239d8eb51a7168da25a000d8a6938e26446c36e5d",
|
"5b65641e27007ec71509c6af5cf8527eb01fee5b2b07d8beecf6646e",
|
||||||
"b88eff9523e0b09934558ddc8b2679bf2f10ed66415df1eb6e38a507",
|
"b7e7e27d85119b74f895b56ba7561834a1b0c42639b122160a0b6208",
|
||||||
"00"
|
"00"
|
||||||
),
|
),
|
||||||
concat!(
|
concat!(
|
||||||
"521672ae547cd95b94a9be55b72a0dfb6938715230304d39017f5a54",
|
"821b7ac04d7c01d970b0b3ba4ae8f737a5bac934aed1600b1cad7601",
|
||||||
"f1333a96da50a0759eea78bdb6b670c8243dbe706cd388763fe4c50b",
|
"1c240629bce6a4671a1b6f572cec708ec161a72a5ca04e50eabdfc25",
|
||||||
"00"
|
"00"
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
sig: concat!(
|
sig: concat!(
|
||||||
"f1c2605fc0b724696dff10d2df0ac28939f40dc3d9ba864605462355",
|
"c7ad7ad9fcfeef9d1492361ba641400bd3a3c8335a83cdffbdd8867d",
|
||||||
"c139229de643a6580e5807994cfcab0796644571c501cab00e85056a",
|
"2849bb4419dcc3e594baa731081a1a00cd3dea9219a81ecba4646e95",
|
||||||
"00",
|
"00",
|
||||||
"e7c423399b36a33ece81aaa75e419a9dc4387edc99682f9e4742c9b1",
|
"dd80dede747c7fa086b9796aa7e04ab655dab790d9d838ca08a4db6f",
|
||||||
"a9c2392cfe30510fd33f069a42dde987544dabd7ad307a62ae1c6b13",
|
"d30be9a641f83fdc12b124c3d34289c262126c5195517166f4c85e2e",
|
||||||
"00"
|
"00"
|
||||||
)
|
)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
|
|
|
@ -27,20 +27,20 @@ fn secp256k1_vectors() {
|
||||||
included: &[1, 3],
|
included: &[1, 3],
|
||||||
nonces: &[
|
nonces: &[
|
||||||
[
|
[
|
||||||
"95f352cf568508bce96ef3cb816bf9229eb521ca9c2aff6a4fe8b86bf49ae16f",
|
"36d5c4185c40b02b5e4673e2531a10e6ff9883840a68ec08dbeb896467e21355",
|
||||||
"c675aea50ff2510ae6b0fcb55432b97ad0b55a28b959bacb0e8b466dbf43dd26",
|
"7b3f573ca0a28f9f94522be4748df0ed04de8a83085aff4be7b01aa53fb6ac1b",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"b5089ebf363630d3477711005173c1419f4f40514f7287b4ca6ff110967a2d70",
|
"ba4f8b8e587b2c9fc61a6156885f0bc67654b5e068c9e7749f75c09a98f17c13",
|
||||||
"5e50ce9975cfc6164e85752f52094b11091fdbca846a9c245fdbfa4bab1ae28c",
|
"316de06639051ac7869e5ac4458eda1fef90ce93fa3c490556c4192e4fa550d0",
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
sig_shares: &[
|
sig_shares: &[
|
||||||
"280c44c6c37cd64c7f5a552ae8416a57d21c115cab524dbff5fbcebbf5c0019d",
|
"f9ee00d5ac0c746b751dde99f71d86f8f0300a81bd0336ca6649ef597239e13f",
|
||||||
"e372bca35133a80ca140dcac2125c966b763a934678f40e09fb8b0ae9d4aee1b",
|
"61048ca334ac6a6cb59d6b3ea2b25b7098e204adc09e2f88b024531b081d1d6f",
|
||||||
],
|
],
|
||||||
sig: "0364b02292a4b0e61f849f4d6fac0e67c2f698a21e1cba9e4a5b8fa535f2f9310d".to_owned() +
|
sig: "023cf76388f92d403aa937af2e3cb3e7a2350e40400c16a282e330af2c60eeb85a".to_owned() +
|
||||||
"0b7f016a14b07e59209b31d7096733bfced0ddaa6398ee64d5e220ddc2d4ae77",
|
"5af28d78e0b8ded82abb49d899cfe26ace633248ce58c617569be3e7aa20bd6d",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -64,20 +64,20 @@ fn p256_vectors() {
|
||||||
included: &[1, 3],
|
included: &[1, 3],
|
||||||
nonces: &[
|
nonces: &[
|
||||||
[
|
[
|
||||||
"e9165dad654fc20a9e31ca6f32ac032ec327b551a50e8ac5cf25f5c4c9e20757",
|
"9aa66350b0f72b27ce4668323b4280cd49709177ed8373977c22a75546c9995d",
|
||||||
"e9059a232598a0fba0e495a687580e624ab425337c3221246fb2c716905bc9e7",
|
"bd8b05d7fd0ff5a5ed65b1f105478f7718a981741fa8fa9b55ac6d3c8fc59a05",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"b9d136e29eb758bd77cb83c317ac4e336cf8cda830c089deddf6d5ec81da9884",
|
"4c1aec8e84c496b80af98415fada2e6a4b1f902d4bc6c9682699b8aeffd97419",
|
||||||
"5261e2d00ce227e67bb9b38990294e2c82970f335b2e6d9f1d07a72ba43d01f0",
|
"eeaf5ef7af01e55050fb8acafc9c9306ef1cc13214677ba33e7bc51e8677e892",
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
sig_shares: &[
|
sig_shares: &[
|
||||||
"bdaa275f10ca57e3a3a9a7a0d95aeabb517897d8482873a8f9713d458f94756f",
|
"ec5b8ab47d55903698492a07bb322ab6e7d3cf32581dcedf43c4fa18b46f3e10",
|
||||||
"0e8fd85386939e8974a8748e66641df0fe043323c52487a2b10b8a397897de21",
|
"c97da3580560e88725a8e393d46fee18ecd2e00148e5e303d4a510fae9c11da5",
|
||||||
],
|
],
|
||||||
sig: "03c41521412528dce484c35b6b9b7cc8150102ab3e4bdf858d702270c05098e6c6".to_owned() +
|
sig: "036b3eba585ff5d40df29893fb6f60572803aef97800cfaaaa5cf0f0f19d8237f7".to_owned() +
|
||||||
"cc39ffb2975df66d18521c2f3fbf08ac4f7ccafc0d4cfb4baa7cc77f082c5390",
|
"b5d92e0d82b678bcbdf20d9b8fa218d017bfb485f9ec135e24b04050a1cd3664",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,12 @@ pub mod vectors;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod literal;
|
mod literal;
|
||||||
|
|
||||||
|
/// Constant amount of participants to use when testing.
|
||||||
pub const PARTICIPANTS: u16 = 5;
|
pub const PARTICIPANTS: u16 = 5;
|
||||||
|
/// Constant threshold of participants to use when signing.
|
||||||
pub const THRESHOLD: u16 = ((PARTICIPANTS / 3) * 2) + 1;
|
pub const THRESHOLD: u16 = ((PARTICIPANTS / 3) * 2) + 1;
|
||||||
|
|
||||||
|
/// Clone a map without a specific value.
|
||||||
pub fn clone_without<K: Clone + std::cmp::Eq + std::hash::Hash, V: Clone>(
|
pub fn clone_without<K: Clone + std::cmp::Eq + std::hash::Hash, V: Clone>(
|
||||||
map: &HashMap<K, V>,
|
map: &HashMap<K, V>,
|
||||||
without: &K,
|
without: &K,
|
||||||
|
@ -36,6 +39,7 @@ pub fn clone_without<K: Clone + std::cmp::Eq + std::hash::Hash, V: Clone>(
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate FROST keys (as FrostCore objects) for tests.
|
||||||
pub fn core_gen<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) -> HashMap<u16, FrostCore<C>> {
|
pub fn core_gen<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) -> HashMap<u16, FrostCore<C>> {
|
||||||
let mut machines = HashMap::new();
|
let mut machines = HashMap::new();
|
||||||
let mut commitments = HashMap::new();
|
let mut commitments = HashMap::new();
|
||||||
|
@ -91,10 +95,12 @@ pub fn core_gen<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) -> HashMap<u16, F
|
||||||
.collect::<HashMap<_, _>>()
|
.collect::<HashMap<_, _>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate FROST keys for tests.
|
||||||
pub fn key_gen<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) -> HashMap<u16, FrostKeys<C>> {
|
pub fn key_gen<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) -> HashMap<u16, FrostKeys<C>> {
|
||||||
core_gen(rng).drain().map(|(i, core)| (i, FrostKeys::new(core))).collect()
|
core_gen(rng).drain().map(|(i, core)| (i, FrostKeys::new(core))).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Recover the secret from a collection of keys.
|
||||||
pub fn recover<C: Curve>(keys: &HashMap<u16, FrostKeys<C>>) -> C::F {
|
pub fn recover<C: Curve>(keys: &HashMap<u16, FrostKeys<C>>) -> C::F {
|
||||||
let first = keys.values().next().expect("no keys provided");
|
let first = keys.values().next().expect("no keys provided");
|
||||||
assert!(keys.len() >= first.params().t().into(), "not enough keys provided");
|
assert!(keys.len() >= first.params().t().into(), "not enough keys provided");
|
||||||
|
@ -107,6 +113,7 @@ pub fn recover<C: Curve>(keys: &HashMap<u16, FrostKeys<C>>) -> C::F {
|
||||||
group_private
|
group_private
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawn algorithm machines for a random selection of signers, each executing the given algorithm.
|
||||||
pub fn algorithm_machines<R: RngCore, C: Curve, A: Algorithm<C>>(
|
pub fn algorithm_machines<R: RngCore, C: Curve, A: Algorithm<C>>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
algorithm: A,
|
algorithm: A,
|
||||||
|
@ -136,6 +143,7 @@ pub fn algorithm_machines<R: RngCore, C: Curve, A: Algorithm<C>>(
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute the signing protocol.
|
||||||
pub fn sign<R: RngCore + CryptoRng, M: PreprocessMachine>(
|
pub fn sign<R: RngCore + CryptoRng, M: PreprocessMachine>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
mut machines: HashMap<u16, M>,
|
mut machines: HashMap<u16, M>,
|
||||||
|
|
Loading…
Reference in a new issue