From a0a54eb0de0b37bfcaee73bec324624bb1f1b852 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Thu, 13 Oct 2022 00:38:36 -0400 Subject: [PATCH] Update to FROST v11 Ensures random functions never return zero. This, combined with a check commitments aren't 0, causes no serialized elements to be 0. Also directly reads their vectors. --- Cargo.lock | 2 + crypto/frost/Cargo.toml | 2 + crypto/frost/src/curve/dalek.rs | 4 +- crypto/frost/src/curve/ed448.rs | 6 +- crypto/frost/src/curve/kp256.rs | 4 +- crypto/frost/src/curve/mod.rs | 29 ++++-- crypto/frost/src/key_gen.rs | 4 +- crypto/frost/src/sign.rs | 13 ++- crypto/frost/src/tests/curve.rs | 4 +- crypto/frost/src/tests/literal/dalek.rs | 68 ++----------- crypto/frost/src/tests/literal/ed448.rs | 90 ++--------------- crypto/frost/src/tests/literal/kp256.rs | 68 ++----------- .../literal/vectors/frost-ed25519-sha512.json | 68 +++++++++++++ .../literal/vectors/frost-ed448-shake256.json | 68 +++++++++++++ .../literal/vectors/frost-p256-sha256.json | 68 +++++++++++++ .../vectors/frost-ristretto255-sha512.json | 68 +++++++++++++ .../vectors/frost-secp256k1-sha256.json | 68 +++++++++++++ crypto/frost/src/tests/schnorr.rs | 18 ++-- crypto/frost/src/tests/vectors.rs | 96 +++++++++++++------ 19 files changed, 491 insertions(+), 257 deletions(-) create mode 100644 crypto/frost/src/tests/literal/vectors/frost-ed25519-sha512.json create mode 100644 crypto/frost/src/tests/literal/vectors/frost-ed448-shake256.json create mode 100644 crypto/frost/src/tests/literal/vectors/frost-p256-sha256.json create mode 100644 crypto/frost/src/tests/literal/vectors/frost-ristretto255-sha512.json create mode 100644 crypto/frost/src/tests/literal/vectors/frost-secp256k1-sha256.json diff --git a/Cargo.lock b/Cargo.lock index fdb001ba..0b562451 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4578,8 +4578,10 @@ dependencies = [ "multiexp", "p256", "rand_core 0.6.4", + "serde_json", "sha2 0.10.6", "sha3 0.10.5", + "subtle", "thiserror", "zeroize", ] diff --git a/crypto/frost/Cargo.toml b/crypto/frost/Cargo.toml index 0d816030..4a284b66 100644 --- a/crypto/frost/Cargo.toml +++ b/crypto/frost/Cargo.toml @@ -18,6 +18,7 @@ thiserror = "1" rand_core = "0.6" zeroize = { version = "1.5", features = ["zeroize_derive"] } +subtle = "2" hex = "0.4" @@ -44,6 +45,7 @@ dleq = { path = "../dleq", version = "0.1", features = ["serialize"] } [dev-dependencies] sha2 = "0.10" dalek-ff-group = { path = "../dalek-ff-group", version = "^0.1.2" } +serde_json = "1" [features] dalek = ["sha2", "dalek-ff-group"] diff --git a/crypto/frost/src/curve/dalek.rs b/crypto/frost/src/curve/dalek.rs index f6b94b77..8db03bd0 100644 --- a/crypto/frost/src/curve/dalek.rs +++ b/crypto/frost/src/curve/dalek.rs @@ -74,7 +74,7 @@ dalek_curve!( IetfRistrettoHram, RistrettoPoint, b"ristretto", - b"FROST-RISTRETTO255-SHA512-v10", + b"FROST-RISTRETTO255-SHA512-v11", b"chal", ); @@ -85,6 +85,6 @@ dalek_curve!( IetfEd25519Hram, EdwardsPoint, b"edwards25519", - b"FROST-ED25519-SHA512-v10", + b"FROST-ED25519-SHA512-v11", b"", ); diff --git a/crypto/frost/src/curve/ed448.rs b/crypto/frost/src/curve/ed448.rs index 373c24a3..b3ae8550 100644 --- a/crypto/frost/src/curve/ed448.rs +++ b/crypto/frost/src/curve/ed448.rs @@ -7,7 +7,7 @@ use minimal_ed448::{scalar::Scalar, point::Point}; use crate::{curve::Curve, algorithm::Hram}; -const CONTEXT: &[u8] = b"FROST-ED448-SHAKE256-v10"; +const CONTEXT: &[u8] = b"FROST-ED448-SHAKE256-v11"; #[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)] pub struct Ed448; @@ -53,8 +53,8 @@ impl Ietf8032Ed448Hram { } #[derive(Copy, Clone)] -pub struct NonIetfEd448Hram; -impl Hram for NonIetfEd448Hram { +pub struct IetfEd448Hram; +impl Hram for IetfEd448Hram { #[allow(non_snake_case)] fn hram(R: &Point, A: &Point, m: &[u8]) -> Scalar { Ietf8032Ed448Hram::hram(&[], R, A, m) diff --git a/crypto/frost/src/curve/kp256.rs b/crypto/frost/src/curve/kp256.rs index b9d1a820..a7d65beb 100644 --- a/crypto/frost/src/curve/kp256.rs +++ b/crypto/frost/src/curve/kp256.rs @@ -92,7 +92,7 @@ macro_rules! kp_curve { } #[cfg(feature = "p256")] -kp_curve!("p256", p256, P256, IetfP256Hram, b"P-256", b"FROST-P256-SHA256-v10"); +kp_curve!("p256", p256, P256, IetfP256Hram, b"P-256", b"FROST-P256-SHA256-v11"); #[cfg(feature = "secp256k1")] kp_curve!( @@ -101,5 +101,5 @@ kp_curve!( Secp256k1, IetfSecp256k1Hram, b"secp256k1", - b"FROST-secp256k1-SHA256-v10" + b"FROST-secp256k1-SHA256-v11" ); diff --git a/crypto/frost/src/curve/mod.rs b/crypto/frost/src/curve/mod.rs index a12edea9..b8365d30 100644 --- a/crypto/frost/src/curve/mod.rs +++ b/crypto/frost/src/curve/mod.rs @@ -6,8 +6,9 @@ use thiserror::Error; use rand_core::{RngCore, CryptoRng}; use zeroize::Zeroize; +use subtle::ConstantTimeEq; -use ff::{PrimeField, PrimeFieldBits}; +use ff::{Field, PrimeField, PrimeFieldBits}; use group::{Group, GroupOps, GroupEncoding, prime::PrimeGroup}; #[cfg(any(test, feature = "dalek"))] @@ -27,7 +28,7 @@ pub use kp256::{P256, IetfP256Hram}; #[cfg(feature = "ed448")] mod ed448; #[cfg(feature = "ed448")] -pub use ed448::{Ed448, Ietf8032Ed448Hram, NonIetfEd448Hram}; +pub use ed448::{Ed448, Ietf8032Ed448Hram, IetfEd448Hram}; /// Set of errors for curve-related operations, namely encoding and decoding. #[derive(Clone, Error, Debug)] @@ -49,7 +50,7 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize { // This is available via G::Scalar yet `C::G::Scalar` is ambiguous, forcing horrific accesses type F: PrimeField + PrimeFieldBits + Zeroize; /// Group element type. - type G: Group + GroupOps + PrimeGroup + Zeroize; + type G: Group + GroupOps + PrimeGroup + Zeroize + ConstantTimeEq; /// ID for this curve. const ID: &'static [u8]; @@ -81,6 +82,16 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize { Self::hash_to_F(b"rho", binding) } + #[allow(non_snake_case)] + fn random_F(rng: &mut R) -> Self::F { + let mut res; + while { + res = Self::F::random(&mut *rng); + res.ct_eq(&Self::F::zero()).into() + } {} + res + } + /// Securely generate a random nonce. H3 from the IETF draft. fn random_nonce(mut secret: Self::F, rng: &mut R) -> Self::F { let mut seed = vec![0; 32]; @@ -89,12 +100,18 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize { let mut repr = secret.to_repr(); secret.zeroize(); - seed.extend(repr.as_ref()); + let mut res; + while { + seed.extend(repr.as_ref()); + res = Self::hash_to_F(b"nonce", &seed); + res.ct_eq(&Self::F::zero()).into() + } { + rng.fill_bytes(&mut seed); + } + for i in repr.as_mut() { i.zeroize(); } - - let res = Self::hash_to_F(b"nonce", &seed); seed.zeroize(); res } diff --git a/crypto/frost/src/key_gen.rs b/crypto/frost/src/key_gen.rs index 2cbb00f9..4a9571d7 100644 --- a/crypto/frost/src/key_gen.rs +++ b/crypto/frost/src/key_gen.rs @@ -48,7 +48,7 @@ fn generate_key_r1( for i in 0 .. t { // Step 1: Generate t random values to form a polynomial with - coefficients.push(C::F::random(&mut *rng)); + coefficients.push(C::random_F(&mut *rng)); // Step 3: Generate public commitments commitments.push(C::generator() * coefficients[i]); // Serialize them for publication @@ -56,7 +56,7 @@ fn generate_key_r1( } // Step 2: Provide a proof of knowledge - let mut r = C::F::random(rng); + let mut r = C::random_F(rng); serialized.extend( schnorr::sign::( coefficients[0], diff --git a/crypto/frost/src/sign.rs b/crypto/frost/src/sign.rs index e0efc822..4c19114e 100644 --- a/crypto/frost/src/sign.rs +++ b/crypto/frost/src/sign.rs @@ -7,6 +7,7 @@ use std::{ use rand_core::{RngCore, CryptoRng}; use zeroize::{Zeroize, ZeroizeOnDrop}; +use subtle::ConstantTimeEq; use transcript::Transcript; @@ -97,8 +98,6 @@ impl Drop for PreprocessPackage { } impl ZeroizeOnDrop for PreprocessPackage {} -// This library unifies the preprocessing step with signing due to security concerns and to provide -// a simpler UX fn preprocess>( rng: &mut R, params: &mut Params, @@ -202,14 +201,20 @@ fn sign_with_share>( // consistency. While this is suboptimal, it maintains IETF compliance, and Algorithm is // documented accordingly let transcript = |t: &mut A::Transcript, commitments: [C::G; 2]| { + if commitments[0].ct_eq(&C::G::identity()).into() || + commitments[1].ct_eq(&C::G::identity()).into() + { + Err(FrostError::InvalidCommitment(*l))?; + } t.append_message(b"commitment_D", commitments[0].to_bytes().as_ref()); t.append_message(b"commitment_E", commitments[1].to_bytes().as_ref()); + Ok(()) }; if *l == params.keys.params().i { for nonce_commitments in &our_preprocess.commitments { for commitments in nonce_commitments { - transcript(params.algorithm.transcript(), *commitments); + transcript(params.algorithm.transcript(), *commitments).unwrap(); } } @@ -227,7 +232,7 @@ fn sign_with_share>( commitments.push(Vec::with_capacity(nonce_generators.len())); for _ in 0 .. nonce_generators.len() { commitments[n].push(read_D_E::<_, C>(&mut cursor, *l)?); - transcript(params.algorithm.transcript(), commitments[n][commitments[n].len() - 1]); + transcript(params.algorithm.transcript(), commitments[n][commitments[n].len() - 1])?; } if nonce_generators.len() >= 2 { diff --git a/crypto/frost/src/tests/curve.rs b/crypto/frost/src/tests/curve.rs index 078df28e..56265f85 100644 --- a/crypto/frost/src/tests/curve.rs +++ b/crypto/frost/src/tests/curve.rs @@ -2,7 +2,7 @@ use std::io::Cursor; use rand_core::{RngCore, CryptoRng}; -use group::{ff::Field, Group}; +use group::Group; use crate::{Curve, FrostCore, tests::core_gen}; @@ -27,7 +27,7 @@ pub fn test_multiexp(rng: &mut R) { let mut sum = C::G::identity(); for _ in 0 .. 10 { for _ in 0 .. 100 { - pairs.push((C::F::random(&mut *rng), C::generator() * C::F::random(&mut *rng))); + pairs.push((C::random_F(&mut *rng), C::generator() * C::random_F(&mut *rng))); sum += pairs[pairs.len() - 1].1 * pairs[pairs.len() - 1].0; } assert_eq!(multiexp::multiexp(&pairs), sum); diff --git a/crypto/frost/src/tests/literal/dalek.rs b/crypto/frost/src/tests/literal/dalek.rs index b35e54e4..02cddec2 100644 --- a/crypto/frost/src/tests/literal/dalek.rs +++ b/crypto/frost/src/tests/literal/dalek.rs @@ -10,35 +10,12 @@ use crate::{ fn ristretto_vectors() { test_with_vectors::<_, curve::Ristretto, curve::IetfRistrettoHram>( &mut OsRng, - Vectors { - threshold: 2, - shares: &[ - "5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e", - "b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01", - "f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04", - ], - group_secret: "1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab265f2ebc4f970b", - group_key: "e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d05083c7254f57", - - msg: "74657374", - included: &[1, 3], - nonces: &[ - [ - "de3e8f526dcb51a1b9b48cc284aeca27c385aa3ba1a92a0c8440d51e1a1d2f00", - "fa8dca5ec7a05d5a7b782be847ba3dde1509de1dbcf0569fc980cff795db5404", - ], - [ - "e07061a9ab6735de9a75b0c64f086c5b999894611d0cdc03f85c4e87c8aae602", - "38b17578e8e6ad4077071ce6b0bf9cb85ac35fee7868dcb6d9bfa97f0e153e0e", - ], - ], - sig_shares: &[ - "a5f046916a6a111672111e47f9825586e1188da8a0f3b7c61f2b6b432c636e07", - "4c175c7e43bd197980c2021774036eb288f54179f079fbf21b7d2f9f52846401", - ], - sig: "94b11def3f919503c3544452ad2a59f198f64cc323bd758bb1c65b42032a7473".to_owned() + - "f107a30fae272b8ff2d3205e6d86c3386a0ecf21916db3b93ba89ae27ee7d208", - }, + Vectors::from( + serde_json::from_str::(include_str!( + "vectors/frost-ristretto255-sha512.json" + )) + .unwrap(), + ), ); } @@ -47,34 +24,9 @@ fn ristretto_vectors() { fn ed25519_vectors() { test_with_vectors::<_, curve::Ed25519, curve::IetfEd25519Hram>( &mut OsRng, - Vectors { - threshold: 2, - shares: &[ - "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509", - "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d", - "d3cb090a075eb154e82fdb4b3cb507f110040905468bb9c46da8bdea643a9a02", - ], - group_secret: "7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a790c6e13a98304", - group_key: "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673", - - msg: "74657374", - included: &[1, 3], - nonces: &[ - [ - "4e64f59e90a3b9cdce346fae68eb0e459532c8ca1ad59a566c3ee2c67bf0100b", - "470c660895c6db164ee6564120eec71023fa5297f09c663bb8171646c5632d00", - ], - [ - "6fc516495dbb364b807cdd0c2e5e3f58aa4914a53fed33cc340033979bb07304", - "0837e770a88147d41ff39138ca23b35d6cf303a4f148294755ede4b7e760d701", - ], - ], - sig_shares: &[ - "3f2eb12735e5b39da97e884a6caadf6bb83f1efcec709d6f66333d0d67ebe707", - "79e572b8632fbb928519dd2eff793de8784a56d582ae48c807d39b0dc5b93509", - ], - sig: "e31e69a4e10d5ca2307c4a0d12cd86e3fceee550e55cb5b3f47c7ad6dbb38884".to_owned() + - "cb3f2e837eb15cd858fb6dd68c2a3e3f318a74d16f1fe6376e06d91a2ca51d01", - }, + Vectors::from( + serde_json::from_str::(include_str!("vectors/frost-ed25519-sha512.json")) + .unwrap(), + ), ); } diff --git a/crypto/frost/src/tests/literal/ed448.rs b/crypto/frost/src/tests/literal/ed448.rs index 82e762b6..df0c9ee7 100644 --- a/crypto/frost/src/tests/literal/ed448.rs +++ b/crypto/frost/src/tests/literal/ed448.rs @@ -3,7 +3,7 @@ use std::io::Cursor; use rand_core::OsRng; use crate::{ - curve::{Curve, Ed448, Ietf8032Ed448Hram, NonIetfEd448Hram}, + curve::{Curve, Ed448, Ietf8032Ed448Hram, IetfEd448Hram}, schnorr::{SchnorrSignature, verify}, tests::vectors::{Vectors, test_with_vectors}, }; @@ -48,88 +48,12 @@ fn ed448_8032_vector() { } #[test] -fn ed448_non_ietf() { - test_with_vectors::<_, Ed448, NonIetfEd448Hram>( +fn ed448_vectors() { + test_with_vectors::<_, Ed448, IetfEd448Hram>( &mut OsRng, - Vectors { - threshold: 2, - shares: &[ - concat!( - "4a2b2f5858a932ad3d3b18bd16e76ced3070d72fd79ae4402df201f5", - "25e754716a1bc1b87a502297f2a99d89ea054e0018eb55d39562fd01", - "00" - ), - concat!( - "2503d56c4f516444a45b080182b8a2ebbe4d9b2ab509f25308c88c0e", - "a7ccdc44e2ef4fc4f63403a11b116372438a1e287265cadeff1fcb07", - "00" - ), - concat!( - "00db7a8146f995db0a7cf844ed89d8e94c2b5f259378ff66e39d1728", - "28b264185ac4decf7219e4aa4478285b9c0eef4fccdf3eea69dd980d", - "00" - ), - ], - group_secret: concat!( - "6298e1eef3c379392caaed061ed8a31033c9e9e3420726f23b404158", - "a401cd9df24632adfe6b418dc942d8a091817dd8bd70e1c72ba52f3c", - "00" - ), - group_key: concat!( - "3832f82fda00ff5365b0376df705675b63d2a93c24c6e81d40801ba2", - "65632be10f443f95968fadb70d10786827f30dc001c8d0f9b7c1d1b0", - "00" - ), - - msg: "74657374", - included: &[1, 3], - nonces: &[ - [ - concat!( - "06f2e15b05d29a50f0686a890259f4dcf66147a80809ed9e50926f5f", - "173fe23a0627561efa003724dc270effc47a30bc4d80aba30725401d", - "00" - ), - concat!( - "e0482e611c34f191d1c13a09bc8bbf4bda68db4de32aa7908849b02b", - "a912cfba46c805e2d8560ab9437e343e1dde6b481a2bae527e111b2c", - "00" - ), - ], - [ - concat!( - "295c56447c070157e6bc3c83ed2afca194569e07d0ad27d28a40dec2", - "c4107c07d507db20da1be62ea6976b8e53ab5d26e225c663f2e71511", - "00" - ), - concat!( - "b97303a6c5ab12b6ad310834361033a19d99dfdf93109da721da35c3", - "abbc5f29df33b3402692bef9f005bb8ea00af5ba20cc688360fd8831", - "00" - ), - ], - ], - sig_shares: &[ - concat!( - "5b65641e27007ec71509c6af5cf8527eb01fee5b2b07d8beecf6646e", - "b7e7e27d85119b74f895b56ba7561834a1b0c42639b122160a0b6208", - "00" - ), - concat!( - "821b7ac04d7c01d970b0b3ba4ae8f737a5bac934aed1600b1cad7601", - "1c240629bce6a4671a1b6f572cec708ec161a72a5ca04e50eabdfc25", - "00" - ), - ], - sig: concat!( - "c7ad7ad9fcfeef9d1492361ba641400bd3a3c8335a83cdffbdd8867d", - "2849bb4419dcc3e594baa731081a1a00cd3dea9219a81ecba4646e95", - "00", - "dd80dede747c7fa086b9796aa7e04ab655dab790d9d838ca08a4db6f", - "d30be9a641f83fdc12b124c3d34289c262126c5195517166f4c85e2e", - "00" - ) - .to_string(), - }, + Vectors::from( + serde_json::from_str::(include_str!("vectors/frost-ed448-shake256.json")) + .unwrap(), + ), ); } diff --git a/crypto/frost/src/tests/literal/kp256.rs b/crypto/frost/src/tests/literal/kp256.rs index b0b581d2..175039e4 100644 --- a/crypto/frost/src/tests/literal/kp256.rs +++ b/crypto/frost/src/tests/literal/kp256.rs @@ -13,35 +13,12 @@ use crate::curve::{P256, IetfP256Hram}; fn secp256k1_vectors() { test_with_vectors::<_, Secp256k1, IetfSecp256k1Hram>( &mut OsRng, - Vectors { - threshold: 2, - shares: &[ - "08f89ffe80ac94dcb920c26f3f46140bfc7f95b493f8310f5fc1ea2b01f4254c", - "04f0feac2edcedc6ce1253b7fab8c86b856a797f44d83d82a385554e6e401984", - "00e95d59dd0d46b0e303e500b62b7ccb0e555d49f5b849f5e748c071da8c0dbc", - ], - group_secret: "0d004150d27c3bf2a42f312683d35fac7394b1e9e318249c1bfe7f0795a83114", - group_key: "02f37c34b66ced1fb51c34a90bdae006901f10625cc06c4f64663b0eae87d87b4f", - - msg: "74657374", - included: &[1, 3], - nonces: &[ - [ - "36d5c4185c40b02b5e4673e2531a10e6ff9883840a68ec08dbeb896467e21355", - "7b3f573ca0a28f9f94522be4748df0ed04de8a83085aff4be7b01aa53fb6ac1b", - ], - [ - "ba4f8b8e587b2c9fc61a6156885f0bc67654b5e068c9e7749f75c09a98f17c13", - "316de06639051ac7869e5ac4458eda1fef90ce93fa3c490556c4192e4fa550d0", - ], - ], - sig_shares: &[ - "f9ee00d5ac0c746b751dde99f71d86f8f0300a81bd0336ca6649ef597239e13f", - "61048ca334ac6a6cb59d6b3ea2b25b7098e204adc09e2f88b024531b081d1d6f", - ], - sig: "023cf76388f92d403aa937af2e3cb3e7a2350e40400c16a282e330af2c60eeb85a".to_owned() + - "5af28d78e0b8ded82abb49d899cfe26ace633248ce58c617569be3e7aa20bd6d", - }, + Vectors::from( + serde_json::from_str::(include_str!( + "vectors/frost-secp256k1-sha256.json" + )) + .unwrap(), + ), ); } @@ -50,34 +27,9 @@ fn secp256k1_vectors() { fn p256_vectors() { test_with_vectors::<_, P256, IetfP256Hram>( &mut OsRng, - Vectors { - threshold: 2, - shares: &[ - "0c9c1a0fe806c184add50bbdcac913dda73e482daf95dcb9f35dbb0d8a9f7731", - "8d8e787bef0ff6c2f494ca45f4dad198c6bee01212d6c84067159c52e1863ad5", - "0e80d6e8f6192c003b5488ce1eec8f5429587d48cf001541e713b2d53c09d928", - ], - group_secret: "8ba9bba2e0fd8c4767154d35a0b7562244a4aaf6f36c8fb8735fa48b301bd8de", - group_key: "023a309ad94e9fe8a7ba45dfc58f38bf091959d3c99cfbd02b4dc00585ec45ab70", - - msg: "74657374", - included: &[1, 3], - nonces: &[ - [ - "9aa66350b0f72b27ce4668323b4280cd49709177ed8373977c22a75546c9995d", - "bd8b05d7fd0ff5a5ed65b1f105478f7718a981741fa8fa9b55ac6d3c8fc59a05", - ], - [ - "4c1aec8e84c496b80af98415fada2e6a4b1f902d4bc6c9682699b8aeffd97419", - "eeaf5ef7af01e55050fb8acafc9c9306ef1cc13214677ba33e7bc51e8677e892", - ], - ], - sig_shares: &[ - "ec5b8ab47d55903698492a07bb322ab6e7d3cf32581dcedf43c4fa18b46f3e10", - "c97da3580560e88725a8e393d46fee18ecd2e00148e5e303d4a510fae9c11da5", - ], - sig: "036b3eba585ff5d40df29893fb6f60572803aef97800cfaaaa5cf0f0f19d8237f7".to_owned() + - "b5d92e0d82b678bcbdf20d9b8fa218d017bfb485f9ec135e24b04050a1cd3664", - }, + Vectors::from( + serde_json::from_str::(include_str!("vectors/frost-p256-sha256.json")) + .unwrap(), + ), ); } diff --git a/crypto/frost/src/tests/literal/vectors/frost-ed25519-sha512.json b/crypto/frost/src/tests/literal/vectors/frost-ed25519-sha512.json new file mode 100644 index 00000000..b0ebb1dc --- /dev/null +++ b/crypto/frost/src/tests/literal/vectors/frost-ed25519-sha512.json @@ -0,0 +1,68 @@ +{ + "config": { + "MAX_PARTICIPANTS": "3", + "NUM_PARTICIPANTS": "2", + "MIN_PARTICIPANTS": "2", + "name": "FROST(Ed25519, SHA-512)", + "group": "ed25519", + "hash": "SHA-512" + }, + "inputs": { + "group_secret_key": "7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a790c6e13a98304", + "group_public_key": "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673", + "message": "74657374", + "share_polynomial_coefficients": [ + "178199860edd8c62f5212ee91eff1295d0d670ab4ed4506866bae57e7030b204" + ], + "participants": { + "1": { + "participant_share": "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509" + }, + "2": { + "participant_share": "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d" + }, + "3": { + "participant_share": "d3cb090a075eb154e82fdb4b3cb507f110040905468bb9c46da8bdea643a9a02" + } + } + }, + "round_one_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "hiding_nonce_randomness": "9d06a6381c7a4493929761a73692776772b274236fb5cfcc7d1b48ac3a9c249f", + "binding_nonce_randomness": "db184d7bc01a3417fe1f2eb3cf5479bb027145e6369a5f879f32d334ab256b23", + "hiding_nonce": "70652da3e8d7533a0e4b9e9104f01b48c396b5b553717784ed8d05c6a36b9609", + "binding_nonce": "4f9e1ad260b5c0e4fe0e0719c6324f89fecd053758f77c957f56967e634a710e", + "hiding_nonce_commitment": "44105304351ceddc58e15ddea35b2cb48e60ced54ceb22c3b0e5d42d098aa1d8", + "binding_nonce_commitment": "b8274b18a12f2cef74ae42f876cec1e31daab5cb162f95a56cd2487409c9d1dd", + "binding_factor_input": "c5b95020cba31a9035835f074f718d0c3af02a318d6b4723bbd1c088f4889dd7b9ff8e79f9a67a9d27605144259a7af18b7cca2539ffa5c4f1366a98645da8f4e077d604fff64f20e2377a37e5a10ce152194d62fe856ef4cd935d4f1cb0088c2083a2722ad3f5a84d778e257da0df2a7cadb004b1f5528352af778b94ee1c2a0100000000000000000000000000000000000000000000000000000000000000", + "binding_factor": "2d5630c36d33258b1208c4205fa759b762d09bfa06b29cf792cf98758c0b3305" + }, + "3": { + "hiding_nonce_randomness": "31ca9b07936d6b342a43d97f23b7bec5a5f5a09575a075393868dd8df5c05a54", + "binding_nonce_randomness": "c1db96a85d8b593e14fdb869c0955625478afa6a987ad217e7f2261dcab26819", + "hiding_nonce": "233adcb0ec0eddba5f1cc5268f3f4e6fc1dd97fb1e4a1754e6ddc92ed834ca0b", + "binding_nonce": "b59fc8a32fe02ec0a44c4671f3d1f82ea3924b7c7c0179398fc9137e82757803", + "hiding_nonce_commitment": "d31bd81ce216b1c83912803a574a0285796275cb8b14f6dc92c8b09a6951f0a2", + "binding_nonce_commitment": "e1c863cfd08df775b6747ef2456e9bf9a03cc281a479a95261dc39137fcf0967", + "binding_factor_input": "c5b95020cba31a9035835f074f718d0c3af02a318d6b4723bbd1c088f4889dd7b9ff8e79f9a67a9d27605144259a7af18b7cca2539ffa5c4f1366a98645da8f4e077d604fff64f20e2377a37e5a10ce152194d62fe856ef4cd935d4f1cb0088c2083a2722ad3f5a84d778e257da0df2a7cadb004b1f5528352af778b94ee1c2a0300000000000000000000000000000000000000000000000000000000000000", + "binding_factor": "1137be5cdf3d18e44367acee8485e9a66c3164077af80619b6291e3943bbef04" + } + } + }, + "round_two_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "sig_share": "c4b26af1e91fbc8440a0dad253e72620da624553c5b625fd51e6ea179fc09f05" + }, + "3": { + "sig_share": "9369640967d0cb98f4dedfde58a845e0e18e0a7164396358439060ed282b4e08" + } + } + }, + "final_output": { + "sig": "ae11c539fdc709b78fef5ee1f5a2250297e3e1b62a86a86c26d93c389934ba0e571ccffa50f0871d357fbab1ac8f6c00bcf14fc429f0885595764b05c8ebed0d" + } +} \ No newline at end of file diff --git a/crypto/frost/src/tests/literal/vectors/frost-ed448-shake256.json b/crypto/frost/src/tests/literal/vectors/frost-ed448-shake256.json new file mode 100644 index 00000000..b8b20418 --- /dev/null +++ b/crypto/frost/src/tests/literal/vectors/frost-ed448-shake256.json @@ -0,0 +1,68 @@ +{ + "config": { + "MAX_PARTICIPANTS": "3", + "NUM_PARTICIPANTS": "2", + "MIN_PARTICIPANTS": "2", + "name": "FROST(Ed448, SHAKE256)", + "group": "ed448", + "hash": "SHAKE256" + }, + "inputs": { + "group_secret_key": "6298e1eef3c379392caaed061ed8a31033c9e9e3420726f23b404158a401cd9df24632adfe6b418dc942d8a091817dd8bd70e1c72ba52f3c00", + "group_public_key": "3832f82fda00ff5365b0376df705675b63d2a93c24c6e81d40801ba265632be10f443f95968fadb70d10786827f30dc001c8d0f9b7c1d1b000", + "message": "74657374", + "share_polynomial_coefficients": [ + "dbd7a514f7a731976620f0436bd135fe8dddc3fadd6e0d13dbd58a1981e587d377d48e0b7ce4e0092967c5e85884d0275a7a740b6abdcd0500" + ], + "participants": { + "1": { + "participant_share": "4a2b2f5858a932ad3d3b18bd16e76ced3070d72fd79ae4402df201f525e754716a1bc1b87a502297f2a99d89ea054e0018eb55d39562fd0100" + }, + "2": { + "participant_share": "2503d56c4f516444a45b080182b8a2ebbe4d9b2ab509f25308c88c0ea7ccdc44e2ef4fc4f63403a11b116372438a1e287265cadeff1fcb0700" + }, + "3": { + "participant_share": "00db7a8146f995db0a7cf844ed89d8e94c2b5f259378ff66e39d172828b264185ac4decf7219e4aa4478285b9c0eef4fccdf3eea69dd980d00" + } + } + }, + "round_one_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "hiding_nonce_randomness": "89bf16040081ff2990336b200613787937ebe1f024b8cdff90eb6f1c741d91c1", + "binding_nonce_randomness": "cd646348bb98fd2a4b2f27fb7d6da18201c161847352576b4bf125190e965483", + "hiding_nonce": "67a6f023e77361707c6e894c625e809e80f33fdb310810053ae29e28e7011f3193b9020e73c183a98cc3a519160ed759376dd92c9483162200", + "binding_nonce": "4812e8d7c8b7a50ced80b507902d074ef8647bc1146979683da8d0fecd93fa3c8230cade2fb4344600aa04bd4b7a21d046c5b63ee865b12a00", + "hiding_nonce_commitment": "649c6a53b109897d962d033f23d01fd4e1053dddf3746d2ddce9bd66aea38ccfc3df061df03ca399eb806312ab3037c0c31523142956ada780", + "binding_nonce_commitment": "0064cc729a8e2fcf417e43788ecec37b10e9e1dcb3ae90854efbfaad00a0ef3cdd52e18d56f073c8ff0947cb71ff0bb17c3d45d096409ddb00", + "binding_factor_input": "106dadce87ca867018702d69a02effd165e1ac1a511c957cff1897ceff2e34ca212fe798d84f0bde6054bf0fa77fd4cd4bc4853d6dc8dbd19d340923f0ebbbb35172df4ab865a45d55af31fa0e6606ea97cf8513022b2b133d0f9f6b8d3be184221fc4592bf12bd7fb4127bb67e51a6dc9e5f1ed5243362fb46a6da552418ca967d43d9bc811a21917a3018de58f11c25f6b9ad8bec3699e06b87dd3ab67a7326c30878c7c55ec1a45802af65da193ce99634158539e38c232a627895c5f14e2e20d487382ccc9c99cd0a0df266a292f283bb9b6854e344ecc32d5e1852fdde5fde77798010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "binding_factor": "3412ac894a91a6bc0e3e7c790f3e8ef5d1288e54de780aba384cbb3081b602dd188010e5b0c9ac2b5dca0aae54cfd0f5c391cece8092131d00" + }, + "3": { + "hiding_nonce_randomness": "3718dabb4fd3d7dd9adad4878c6de8b33c8841cfe7cc95a85592952a2c9c554d", + "binding_nonce_randomness": "3becbc90798211a0f52543dd1f24869a143fdf743409581af4db30f045773d64", + "hiding_nonce": "4f2666770317d14ec9f7fd6690c075c34b4cde7f6d9bceda9e9433ec8c0f2dc983ff1622c3a54916ce7c161381d263fad62539cddab2101600", + "binding_nonce": "88f66df8bb66389932721a40de4aa5754f632cac114abc1052688104d19f3b1a010880ebcd0c4c0f8cf567d887e5b0c3c0dc78821166550f00", + "hiding_nonce_commitment": "8dcf049167e28d5f53fa7ebbbd136abcaf2be9f2c02448c8979002f92577b22027640def7ddd5b98f9540c2280f36a92d4747bbade0b0c4280", + "binding_nonce_commitment": "12e837b89a2c085481fcf0ca640a17a24b6fc96b032d40e4301c78e7232a9f49ffdcad2c21acbc992e79dfc3c6c07cb94e4680b3dcc9935580", + "binding_factor_input": "106dadce87ca867018702d69a02effd165e1ac1a511c957cff1897ceff2e34ca212fe798d84f0bde6054bf0fa77fd4cd4bc4853d6dc8dbd19d340923f0ebbbb35172df4ab865a45d55af31fa0e6606ea97cf8513022b2b133d0f9f6b8d3be184221fc4592bf12bd7fb4127bb67e51a6dc9e5f1ed5243362fb46a6da552418ca967d43d9bc811a21917a3018de58f11c25f6b9ad8bec3699e06b87dd3ab67a7326c30878c7c55ec1a45802af65da193ce99634158539e38c232a627895c5f14e2e20d487382ccc9c99cd0a0df266a292f283bb9b6854e344ecc32d5e1852fdde5fde77798030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "binding_factor": "6aa48a3635d7b962489283ee1ccda8ea66e5677b1e17f2f475eb565e3ae8ea73360f24c04e3775dadd1f2923adcda3d105536ad28c3c561100" + } + } + }, + "round_two_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "sig_share": "c5057c80d13e565545dac6f3aa333065c809a14a94fea3c8e4e87e386a9cb89602de7355c5d19ebb09d553b100ef1858104fc7c43992d83400" + }, + "3": { + "sig_share": "2b490ea08411f78c620c668fff8ba70b25b7c89436f20cc45419213de70f93fb6c9094c79293697d72e741b68d2e493446005145d0b7fc3500" + } + } + }, + "final_output": { + "sig": "83ac141d289a5171bc894b058aee2890316280719a870fc5c1608b77403023155d7a9dc15a2b7920bb5826dd540bf76336be99536cebe36280fd093275c38dd4be525767f537fd6a4f5d8a9330811562c84fded5f851ac4b926f6e081d586508397cbc95678e1d628c564f180a0a4ad52a00" + } +} \ No newline at end of file diff --git a/crypto/frost/src/tests/literal/vectors/frost-p256-sha256.json b/crypto/frost/src/tests/literal/vectors/frost-p256-sha256.json new file mode 100644 index 00000000..db6be1f8 --- /dev/null +++ b/crypto/frost/src/tests/literal/vectors/frost-p256-sha256.json @@ -0,0 +1,68 @@ +{ + "config": { + "MAX_PARTICIPANTS": "3", + "NUM_PARTICIPANTS": "2", + "MIN_PARTICIPANTS": "2", + "name": "FROST(P-256, SHA-256)", + "group": "P-256", + "hash": "SHA-256" + }, + "inputs": { + "group_secret_key": "8ba9bba2e0fd8c4767154d35a0b7562244a4aaf6f36c8fb8735fa48b301bd8de", + "group_public_key": "023a309ad94e9fe8a7ba45dfc58f38bf091959d3c99cfbd02b4dc00585ec45ab70", + "message": "74657374", + "share_polynomial_coefficients": [ + "80f25e6c0709353e46bfbe882a11bdbb1f8097e46340eb8673b7e14556e6c3a4" + ], + "participants": { + "1": { + "participant_share": "0c9c1a0fe806c184add50bbdcac913dda73e482daf95dcb9f35dbb0d8a9f7731" + }, + "2": { + "participant_share": "8d8e787bef0ff6c2f494ca45f4dad198c6bee01212d6c84067159c52e1863ad5" + }, + "3": { + "participant_share": "0e80d6e8f6192c003b5488ce1eec8f5429587d48cf001541e713b2d53c09d928" + } + } + }, + "round_one_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "hiding_nonce_randomness": "f4e8cf80aec3f888d997900ac7e3e349944b5a6b47649fc32186d2f1238103c6", + "binding_nonce_randomness": "a7f220770b6f10ff54ec6afa55f99bd08cc92fa1a488c86e9bf493e9cb894cdf", + "hiding_nonce": "f871dfcf6bcd199342651adc361b92c941cb6a0d8c8c1a3b91d79e2c1bf3722d", + "binding_nonce": "bd3ece3634a1b303dea0586ed67a91fe68510f11ebe66e8868309b1551ef2388", + "hiding_nonce_commitment": "03987febbc67a8ed735affdff4d3a5adf22c05c80f97f311ab7437a3027372deb3", + "binding_nonce_commitment": "02a1960477d139035b986d6adcb06491378beb92ccd097ad94e76291c52343849d", + "binding_factor_input": "350c8b523feea9bb35720e9fbe0405ed48d78caa4fb60869f34367e144c68bb0fc77bf512409ad8b91e2ace4909229891a446c45683f5eb2f843dbec224527dc0000000000000000000000000000000000000000000000000000000000000001", + "binding_factor": "cb415dd1d866493ee7d2db7cb33929d7e430e84d80c58070e2bbb1fdbf76a9c8" + }, + "3": { + "hiding_nonce_randomness": "1b6149d252a0a0a6618b8d22a1c49897f9b0d23a48f19598e191e05dc7b7ae33", + "binding_nonce_randomness": "e13994bb75aafe337c32afdbfd08ae60dd108fc768845edaa871992044cabf1b", + "hiding_nonce": "802e9321f9f63688c6c1a9681a4a4661f71770e0cef92b8a5997155d18fb82ef", + "binding_nonce": "8b6b692ae634a24536f45dda95b2398af71cd605fb7a0bbdd9408d211ab99eba", + "hiding_nonce_commitment": "0212cac45ebd4100c97506939391f9be4ffc3ca2960e2ef95aeaa38abdede204ca", + "binding_nonce_commitment": "03017ce754d310eabda0f5681e61ce3d713cdd337070faa6a68471af49694a4e7e", + "binding_factor_input": "350c8b523feea9bb35720e9fbe0405ed48d78caa4fb60869f34367e144c68bb0fc77bf512409ad8b91e2ace4909229891a446c45683f5eb2f843dbec224527dc0000000000000000000000000000000000000000000000000000000000000003", + "binding_factor": "dfd82467569334e952edecb10d92adf85b8e299db0b40be3131a12efdfa3e796" + } + } + }, + "round_two_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "sig_share": "c5acd980310aaf87cb7a9a90428698ef3e6b1e5860f7fb06329bc0efe3f14ca5" + }, + "3": { + "sig_share": "1e064fbd35467377eb3fe161ff975e9ec3ed8e2e0d4c73f3a6b0a023777e1264" + } + } + }, + "final_output": { + "sig": "029e07d4171dbf9a730ed95e9d95bda06fa4db76c88c519f7f3ca5483019f46cb0e3b3293d665122ffb6ba7bf2421df78e0258ac866e446ef9d94c61135b6f5f09" + } +} \ No newline at end of file diff --git a/crypto/frost/src/tests/literal/vectors/frost-ristretto255-sha512.json b/crypto/frost/src/tests/literal/vectors/frost-ristretto255-sha512.json new file mode 100644 index 00000000..72a518b6 --- /dev/null +++ b/crypto/frost/src/tests/literal/vectors/frost-ristretto255-sha512.json @@ -0,0 +1,68 @@ +{ + "config": { + "MAX_PARTICIPANTS": "3", + "NUM_PARTICIPANTS": "2", + "MIN_PARTICIPANTS": "2", + "name": "FROST(ristretto255, SHA-512)", + "group": "ristretto255", + "hash": "SHA-512" + }, + "inputs": { + "group_secret_key": "1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab265f2ebc4f970b", + "group_public_key": "e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d05083c7254f57", + "message": "74657374", + "share_polynomial_coefficients": [ + "410f8b744b19325891d73736923525a4f596c805d060dfb9c98009d34e3fec02" + ], + "participants": { + "1": { + "participant_share": "5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e" + }, + "2": { + "participant_share": "b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01" + }, + "3": { + "participant_share": "f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04" + } + } + }, + "round_one_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "hiding_nonce_randomness": "81800157bb554f299fe0b6bd658e4c4591d74168b5177bf55e8dceed59dc80c7", + "binding_nonce_randomness": "e9b37de02fde28f601f09051ed9a277b02ac81c803a5c72492d58635001fe355", + "hiding_nonce": "40f58e8df202b21c94f826e76e4647efdb0ea3ca7ae7e3689bc0cbe2e2f6660c", + "binding_nonce": "373dd42b5fe80e88edddf82e03744b6a12d59256f546de612d4bbd91a6b1df06", + "hiding_nonce_commitment": "b8c7319a56b296537436e5a6f509a871a3c74eff1534ec1e2f539ccd8b322411", + "binding_nonce_commitment": "7af5d4bece8763ce3630370adbd978699402f624fd3a7d2c71ea5839efc3cf54", + "binding_factor_input": "9c245d5fc2e451c5c5a617cc6f2a20629fb317d9b1c1915ab4bfa319d4ebf922c54dd1a5b3b754550c72734ac9255db8107a2b01f361754d9f13f428c2f6de9e4f609ae0dbe8bd1f95bee9f9ea219154d567ef174390bac737bb67ee1787c8a34279728d4aa99a6de2d5ce6deb86afe6bc68178f01223bb5eb934c8a23b6354e0100000000000000000000000000000000000000000000000000000000000000", + "binding_factor": "607df5e2e3a8b5e2704716693e18f548100a32b86a5685d3932a774c3f107e06" + }, + "3": { + "hiding_nonce_randomness": "daeb223c4a913943cff2fb0b0e638dfcc281e1e8936ee6c3fef4d49ad9cbfaa0", + "binding_nonce_randomness": "c425768d952ab8f18b9720c54b93e612ba2cca170bb7518cac080896efa7429b", + "hiding_nonce": "491477c9dbe8717c77c6c1e2c5f4cec636c7c154313a44c91fea63e309f3e100", + "binding_nonce": "3ae1bba7d6f2076f81596912dd916efae5b3c2ef896956321194fdd2e52ebc0f", + "hiding_nonce_commitment": "e4466b7670ac4f9d9b7b67655860dd1ab341be18a654bb1966df53c76c85d511", + "binding_nonce_commitment": "ce47cd595d25d7effc3c095efa2a687a1728a5ecab402b39e0c0ad9a525ea54f", + "binding_factor_input": "9c245d5fc2e451c5c5a617cc6f2a20629fb317d9b1c1915ab4bfa319d4ebf922c54dd1a5b3b754550c72734ac9255db8107a2b01f361754d9f13f428c2f6de9e4f609ae0dbe8bd1f95bee9f9ea219154d567ef174390bac737bb67ee1787c8a34279728d4aa99a6de2d5ce6deb86afe6bc68178f01223bb5eb934c8a23b6354e0300000000000000000000000000000000000000000000000000000000000000", + "binding_factor": "2bd27271c28746eb93e2114d6778c12b44c9287d84b85dc780eb08da6f689900" + } + } + }, + "round_two_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "sig_share": "c38f438c325ce6bfa4272b37e7707caaeb57fa8c7ddcc05e0725acb8a7d9cd0c" + }, + "3": { + "sig_share": "4cb9917be3bd53f1d60f1c3d1a3ff563565fa15a391133e7f980e55d3aeb7904" + } + } + }, + "final_output": { + "sig": "204d5d93aa486192ecf2f64ce7dbc1db76948fb1077d1a719ae1ecca6143501e2275dfaafbb62759a59a4fd122b692f941b79be7b6edf34501a69116e2c44701" + } +} \ No newline at end of file diff --git a/crypto/frost/src/tests/literal/vectors/frost-secp256k1-sha256.json b/crypto/frost/src/tests/literal/vectors/frost-secp256k1-sha256.json new file mode 100644 index 00000000..e7f8e317 --- /dev/null +++ b/crypto/frost/src/tests/literal/vectors/frost-secp256k1-sha256.json @@ -0,0 +1,68 @@ +{ + "config": { + "MAX_PARTICIPANTS": "3", + "NUM_PARTICIPANTS": "2", + "MIN_PARTICIPANTS": "2", + "name": "FROST(secp256k1, SHA-256)", + "group": "secp256k1", + "hash": "SHA-256" + }, + "inputs": { + "group_secret_key": "0d004150d27c3bf2a42f312683d35fac7394b1e9e318249c1bfe7f0795a83114", + "group_public_key": "02f37c34b66ced1fb51c34a90bdae006901f10625cc06c4f64663b0eae87d87b4f", + "message": "74657374", + "share_polynomial_coefficients": [ + "fbf85eadae3058ea14f19148bb72b45e4399c0b16028acaf0395c9b03c823579" + ], + "participants": { + "1": { + "participant_share": "08f89ffe80ac94dcb920c26f3f46140bfc7f95b493f8310f5fc1ea2b01f4254c" + }, + "2": { + "participant_share": "04f0feac2edcedc6ce1253b7fab8c86b856a797f44d83d82a385554e6e401984" + }, + "3": { + "participant_share": "00e95d59dd0d46b0e303e500b62b7ccb0e555d49f5b849f5e748c071da8c0dbc" + } + } + }, + "round_one_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "hiding_nonce_randomness": "80cbea5e405d169999d8c4b30b755fedb26ab07ec8198cda4873ed8ce5e16773", + "binding_nonce_randomness": "f6d5b38197843046b68903048c1feba433e3500145281fa8bb1e26fdfeef5e7f", + "hiding_nonce": "acc83278035223c1ba464e2d11bfacfc872b2b23e1041cf5f6130da21e4d8068", + "binding_nonce": "c3ef169995bc3d2c2d48f30b83d0c63751e67ceb057695bcb2a6aa40ed5d926b", + "hiding_nonce_commitment": "036673d68a928793c33ae07776908eae8ea15dd947ed81284e939aaba118573a5e", + "binding_nonce_commitment": "03d2a96dd4ec1ee29dc22067109d1290dabd8016cb41856ee8ff9281c3fa1baffd", + "binding_factor_input": "a645d8249457bbcac34fa7b740f66bcce08fc39506b8bbf1a1c81092f6272eda82ae39234d714f87a7b91dd67d124a06561a36817c1ecaa255c3527d694fc4f10000000000000000000000000000000000000000000000000000000000000001", + "binding_factor": "d7bcbd29408dedc9e138262d99b09d8b5705d76eb5de2369d9103e4423f8ac79" + }, + "3": { + "hiding_nonce_randomness": "b9794047604beda0c5c0529ac9dfd83c0a80399a7bdf4c3e23cef2faf69cdcc3", + "binding_nonce_randomness": "c28ce6252631620b84c2702b34774fab365e286ebc77030a112ebccccbffa78b", + "hiding_nonce": "cb3387defef07fc9010c0564ba6495ed41876626ed86b886ca26cbbd3566ffbc", + "binding_nonce": "4559459735eb68e8c16319a9fd9a14016053957cb8cea273a24b7c7bc1ee26f6", + "hiding_nonce_commitment": "030278e6e6055fb963b40e0c3c37099f803f3f38930fc89092517f8ce1b47e8d6b", + "binding_nonce_commitment": "028eb6d238c6c0fc6216906706ad0ff9943c6c1d6079cdf74f674481ebb2485db3", + "binding_factor_input": "a645d8249457bbcac34fa7b740f66bcce08fc39506b8bbf1a1c81092f6272eda82ae39234d714f87a7b91dd67d124a06561a36817c1ecaa255c3527d694fc4f10000000000000000000000000000000000000000000000000000000000000003", + "binding_factor": "ecc057259f3c8b195308c9b73aaaf840660a37eb264ebce342412c58102ee437" + } + } + }, + "round_two_outputs": { + "participant_list": "1,3", + "participants": { + "1": { + "sig_share": "1750b2a314a81b66fd81366583617aaafcffa68f14495204795aa0434b907aa3" + }, + "3": { + "sig_share": "e4dbbbbbcb035eb3512918b0368c4ab2c836a92dccff3251efa7a4aacc7d3790" + } + } + }, + "final_output": { + "sig": "0259696aac722558e8638485d252bb2556f6241a7adfdf284c8c87a3428d46448dfc2c6e5edfab7a1a4eaa4f15b9edc55dc5364fbce1488456690244ee180db233" + } +} \ No newline at end of file diff --git a/crypto/frost/src/tests/schnorr.rs b/crypto/frost/src/tests/schnorr.rs index 8c12b07d..d25d066d 100644 --- a/crypto/frost/src/tests/schnorr.rs +++ b/crypto/frost/src/tests/schnorr.rs @@ -12,9 +12,9 @@ use crate::{ }; pub(crate) fn core_sign(rng: &mut R) { - let private_key = C::F::random(&mut *rng); - let nonce = C::F::random(&mut *rng); - let challenge = C::F::random(rng); // Doesn't bother to craft an HRAM + let private_key = C::random_F(&mut *rng); + let nonce = C::random_F(&mut *rng); + let challenge = C::random_F(rng); // Doesn't bother to craft an HRAm assert!(schnorr::verify::( C::generator() * private_key, challenge, @@ -27,8 +27,8 @@ pub(crate) fn core_sign(rng: &mut R) { // random pub(crate) fn core_verify(rng: &mut R) { assert!(!schnorr::verify::( - C::generator() * C::F::random(&mut *rng), - C::F::random(rng), + C::generator() * C::random_F(&mut *rng), + C::random_F(rng), &SchnorrSignature { R: C::G::identity(), s: C::F::zero() } )); } @@ -39,9 +39,9 @@ pub(crate) fn core_batch_verify(rng: &mut R) { let mut challenges = vec![]; let mut sigs = vec![]; for i in 0 .. 5 { - keys.push(C::F::random(&mut *rng)); - challenges.push(C::F::random(&mut *rng)); - sigs.push(schnorr::sign::(keys[i], C::F::random(&mut *rng), challenges[i])); + keys.push(C::random_F(&mut *rng)); + challenges.push(C::random_F(&mut *rng)); + sigs.push(schnorr::sign::(keys[i], C::random_F(&mut *rng), challenges[i])); } // Batch verify @@ -66,7 +66,7 @@ pub(crate) fn core_batch_verify(rng: &mut R) { // Make sure a completely invalid signature fails when included for i in 0 .. 5 { let mut triplets = triplets.clone(); - triplets[i].3.s = C::F::random(&mut *rng); + triplets[i].3.s = C::random_F(&mut *rng); if let Err(blame) = schnorr::batch_verify(rng, &triplets) { assert_eq!(blame, u16::try_from(i + 1).unwrap()); } else { diff --git a/crypto/frost/src/tests/vectors.rs b/crypto/frost/src/tests/vectors.rs index ca2cf278..a1d4b3ee 100644 --- a/crypto/frost/src/tests/vectors.rs +++ b/crypto/frost/src/tests/vectors.rs @@ -1,4 +1,6 @@ use std::{io::Cursor, collections::HashMap}; +#[cfg(test)] +use std::str::FromStr; use rand_core::{RngCore, CryptoRng}; @@ -16,17 +18,61 @@ use crate::{ pub struct Vectors { pub threshold: u16, - pub shares: &'static [&'static str], - pub group_secret: &'static str, - pub group_key: &'static str, - pub msg: &'static str, - pub included: &'static [u16], - pub nonces: &'static [[&'static str; 2]], - pub sig_shares: &'static [&'static str], + pub group_secret: String, + pub group_key: String, + pub shares: Vec, + + pub msg: String, + pub included: Vec, + pub nonces: Vec<[String; 2]>, + + pub sig_shares: Vec, + pub sig: String, } +#[cfg(test)] +impl From for Vectors { + fn from(value: serde_json::Value) -> Vectors { + let to_str = |value: &serde_json::Value| dbg!(value).as_str().unwrap().to_string(); + Vectors { + threshold: u16::from_str(value["config"]["NUM_PARTICIPANTS"].as_str().unwrap()).unwrap(), + + group_secret: to_str(&value["inputs"]["group_secret_key"]), + group_key: to_str(&value["inputs"]["group_public_key"]), + shares: value["inputs"]["participants"] + .as_object() + .unwrap() + .values() + .map(|share| to_str(&share["participant_share"])) + .collect(), + + msg: to_str(&value["inputs"]["message"]), + included: to_str(&value["round_one_outputs"]["participant_list"]) + .split(",") + .map(u16::from_str) + .collect::>() + .unwrap(), + nonces: value["round_one_outputs"]["participants"] + .as_object() + .unwrap() + .values() + .map(|value| [to_str(&value["hiding_nonce"]), to_str(&value["binding_nonce"])]) + .collect(), + + sig_shares: value["round_two_outputs"]["participants"] + .as_object() + .unwrap() + .values() + .map(|value| to_str(&value["sig_share"])) + .collect(), + + sig: to_str(&value["final_output"]["sig"]), + } + } +} + // Load these vectors into FrostKeys using a custom serialization it'll deserialize fn vectors_to_multisig_keys(vectors: &Vectors) -> HashMap> { let shares = vectors @@ -54,7 +100,7 @@ fn vectors_to_multisig_keys(vectors: &Vectors) -> HashMap>( ) { // Do basic tests before trying the vectors test_curve::<_, C>(&mut *rng); - test_schnorr::<_, C>(rng); + test_schnorr::<_, C>(&mut *rng); test_promotion::<_, C>(rng); // Test against the vectors let keys = vectors_to_multisig_keys::(&vectors); - let group_key = C::read_G(&mut Cursor::new(hex::decode(vectors.group_key).unwrap())).unwrap(); - assert_eq!( - C::generator() * - C::read_F(&mut Cursor::new(hex::decode(vectors.group_secret).unwrap())).unwrap(), - group_key - ); - assert_eq!( - recover(&keys), - C::read_F(&mut Cursor::new(hex::decode(vectors.group_secret).unwrap())).unwrap() - ); + let group_key = C::read_G(&mut Cursor::new(hex::decode(&vectors.group_key).unwrap())).unwrap(); + let secret = C::read_F(&mut Cursor::new(hex::decode(&vectors.group_secret).unwrap())).unwrap(); + assert_eq!(C::generator() * secret, group_key); + assert_eq!(recover(&keys), secret); let mut machines = vec![]; - for i in vectors.included { + for i in &vectors.included { machines.push(( - *i, + i, AlgorithmMachine::new( Schnorr::::new(), keys[i].clone(), @@ -102,8 +142,8 @@ pub fn test_with_vectors>( .drain(..) .map(|(i, machine)| { let nonces = [ - C::read_F(&mut Cursor::new(hex::decode(vectors.nonces[c][0]).unwrap())).unwrap(), - C::read_F(&mut Cursor::new(hex::decode(vectors.nonces[c][1]).unwrap())).unwrap(), + C::read_F(&mut Cursor::new(hex::decode(&vectors.nonces[c][0]).unwrap())).unwrap(), + C::read_F(&mut Cursor::new(hex::decode(&vectors.nonces[c][1]).unwrap())).unwrap(), ]; c += 1; let these_commitments = vec![[C::generator() * nonces[0], C::generator() * nonces[1]]]; @@ -114,7 +154,7 @@ pub fn test_with_vectors>( }); commitments.insert( - i, + *i, Cursor::new( [ these_commitments[0][0].to_bytes().as_ref(), @@ -134,18 +174,18 @@ pub fn test_with_vectors>( .drain(..) .map(|(i, machine)| { let (machine, share) = - machine.sign(clone_without(&commitments, &i), &hex::decode(vectors.msg).unwrap()).unwrap(); + machine.sign(clone_without(&commitments, i), &hex::decode(&vectors.msg).unwrap()).unwrap(); - assert_eq!(share, hex::decode(vectors.sig_shares[c]).unwrap()); + assert_eq!(share, hex::decode(&vectors.sig_shares[c]).unwrap()); c += 1; - shares.insert(i, Cursor::new(share)); + shares.insert(*i, Cursor::new(share)); (i, machine) }) .collect::>(); for (i, machine) in machines.drain() { - let sig = machine.complete(clone_without(&shares, &i)).unwrap(); + let sig = machine.complete(clone_without(&shares, i)).unwrap(); let mut serialized = sig.R.to_bytes().as_ref().to_vec(); serialized.extend(sig.s.to_repr().as_ref()); assert_eq!(hex::encode(serialized), vectors.sig);