Skip to content

Commit

Permalink
Create DKG vector tests (#587)
Browse files Browse the repository at this point in the history
* Add DKG vector test for ed25519 (#567)

* Add DKG test vectors for all ciphersuites (#567)

* Add description for DKG vector test (#567)

* Update imports for DKG vector tests (#567)
  • Loading branch information
natalieesk authored Dec 4, 2023
1 parent 6d82adf commit 1e29230
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 0 deletions.
2 changes: 2 additions & 0 deletions frost-core/src/keys/dkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
// > Every participant P_i computes a public commitment
// > C⃗_i = 〈φ_{i0}, ..., φ_{i(t−1)}〉, where φ_{ij} = g^{a_{ij}}, 0 ≤ j ≤ t − 1
let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, &mut rng);

let (coefficients, commitment) =
generate_secret_polynomial(&secret, max_signers, min_signers, coefficients)?;
let proof_of_knowledge =
Expand Down Expand Up @@ -517,6 +518,7 @@ pub fn part3<C: Ciphersuite>(

signing_share = signing_share + round2_secret_package.secret_share;
let signing_share = SigningShare(signing_share);

// Round 2, Step 4
//
// > Each P_i calculates their public verification share Y_i = g^{s_i}.
Expand Down
1 change: 1 addition & 0 deletions frost-core/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ pub mod helpers;
pub mod proptests;
pub mod repairable;
pub mod vectors;
pub mod vectors_dkg;
pub mod vss_commitment;
222 changes: 222 additions & 0 deletions frost-core/src/tests/vectors_dkg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
//! Helper function for testing with test vectors.
use std::collections::BTreeMap;

use debugless_unwrap::DebuglessUnwrap;
use hex::{self};
use serde_json::Value;

use crate::{
keys::{
dkg::{
part2, part3, round1::Package as Round1Package, round1::SecretPackage,
round2::Package as Round2Package,
},
generate_secret_polynomial, KeyPackage, PublicKeyPackage, SigningShare,
VerifiableSecretSharingCommitment, VerifyingShare,
},
Ciphersuite, Field, Group, Header, Identifier, Scalar, Signature, SigningKey, VerifyingKey,
};

/// Test vectors for a ciphersuite.
pub struct DKGTestVectors<C: Ciphersuite> {
secret: SigningKey<C>,
coefficient: Scalar<C>,
round1_packages: BTreeMap<Identifier<C>, Round1Package<C>>,
round2_packages: BTreeMap<Identifier<C>, Round2Package<C>>,
public_key_package: PublicKeyPackage<C>,
key_package: KeyPackage<C>,
participant_id: Identifier<C>,
}

fn json_to_scalar<C: Ciphersuite>(
vector: &Value,
) -> <<C::Group as Group>::Field as Field>::Serialization {
(hex::decode(vector.as_str().unwrap()).unwrap())
.try_into()
.debugless_unwrap()
}

fn json_to_element<C: Ciphersuite>(vector: &Value) -> <C::Group as Group>::Serialization {
(hex::decode(vector.as_str().unwrap()).unwrap())
.try_into()
.debugless_unwrap()
}

/// Parse test vectors for a given ciphersuite.
#[allow(clippy::type_complexity)]
pub fn parse_test_vectors_dkg<C: Ciphersuite>(json_vectors: &Value) -> DKGTestVectors<C> {
let inputs = &json_vectors["inputs"];
let participant = &inputs["1"];

let participant_1_id: Identifier<C> = (participant["identifier"].as_u64().unwrap() as u16)
.try_into()
.unwrap();
let participant_2_id: Identifier<C> = (inputs["2"]["identifier"].as_u64().unwrap() as u16)
.try_into()
.unwrap();
let participant_3_id: Identifier<C> = (inputs["3"]["identifier"].as_u64().unwrap() as u16)
.try_into()
.unwrap();

let mut round1_packages = BTreeMap::new();
round1_packages.insert(participant_2_id, build_round_1_package(json_vectors, 2));
round1_packages.insert(participant_3_id, build_round_1_package(json_vectors, 3));

let mut round2_packages = BTreeMap::new();
round2_packages.insert(participant_2_id, build_round_2_package(json_vectors, 2));
round2_packages.insert(participant_3_id, build_round_2_package(json_vectors, 3));

let secret = SigningKey::deserialize(json_to_scalar::<C>(&participant["signing_key"])).unwrap();

let coefficient = <<C::Group as Group>::Field as Field>::deserialize(&json_to_scalar::<C>(
&participant["coefficient"],
))
.unwrap();

let public_key_package = build_public_key_package(json_vectors);

let verifying_share =
VerifyingShare::deserialize(json_to_element::<C>(&participant["verifying_share"])).unwrap();

let verifying_key =
VerifyingKey::deserialize(json_to_element::<C>(&inputs["verifying_key"])).unwrap();

let signing_share =
SigningShare::deserialize(json_to_scalar::<C>(&participant["signing_share"])).unwrap();

let key_package = KeyPackage {
header: Header::default(),
identifier: participant_1_id,
signing_share,
verifying_share,
verifying_key,
min_signers: 2,
};

DKGTestVectors {
secret,
coefficient,
round1_packages,
round2_packages,
public_key_package,
key_package,
participant_id: participant_1_id,
}
}

fn build_round_1_package<C: Ciphersuite>(
json_vectors: &Value,
participant_num: usize,
) -> Round1Package<C> {
let inputs = &json_vectors["inputs"];
let participant = &inputs[participant_num.to_string()];
let vss_commitment = participant["vss_commitments"]
.as_array()
.unwrap()
.iter()
.map(|v| json_to_element::<C>(v))
.collect();

let commitment = VerifiableSecretSharingCommitment::deserialize(vss_commitment).unwrap();

let proof_of_knowledge = Signature::deserialize(
C::SignatureSerialization::try_from(
hex::decode(participant["proof_of_knowledge"].as_str().unwrap()).unwrap(),
)
.debugless_unwrap(),
)
.unwrap();

Round1Package {
header: Header::default(),
commitment,
proof_of_knowledge,
}
}

fn build_round_2_package<C: Ciphersuite>(
json_vectors: &Value,
sender_num: usize,
) -> Round2Package<C> {
let inputs = &json_vectors["inputs"];

let signing_share = SigningShare::deserialize(json_to_scalar::<C>(
&inputs["1"]["signing_shares"][sender_num.to_string()],
))
.unwrap();

Round2Package {
header: Header::default(),
signing_share,
}
}

fn build_public_key_package<C: Ciphersuite>(json_vectors: &Value) -> PublicKeyPackage<C> {
let inputs = &json_vectors["inputs"];

let mut verifying_shares = BTreeMap::new();

let max_participants = json_vectors["config"]["MAX_PARTICIPANTS"].as_u64().unwrap() as u8;

for i in 1..=max_participants {
let participant_id: Identifier<C> = (inputs[i.to_string()]["identifier"].as_u64().unwrap()
as u16)
.try_into()
.unwrap();
let verifying_share = VerifyingShare::deserialize(json_to_element::<C>(
&inputs[i.to_string()]["verifying_share"],
))
.unwrap();
verifying_shares.insert(participant_id, verifying_share);
}

let verifying_key =
VerifyingKey::deserialize(json_to_element::<C>(&inputs["verifying_key"])).unwrap();

PublicKeyPackage {
header: Header::default(),
verifying_shares,
verifying_key,
}
}

/// Test DKG with the given test vectors for a ciphersuite
pub fn check_dkg_keygen<C: Ciphersuite>(json_vectors: &Value) {
let DKGTestVectors {
secret,
coefficient,
round1_packages,
round2_packages,
public_key_package,
key_package,
participant_id,
} = parse_test_vectors_dkg(json_vectors);

let min_signers = 2;
let max_signers = 3;

let (coefficients, commitment) = generate_secret_polynomial(
&secret as &SigningKey<C>,
max_signers,
min_signers,
vec![coefficient],
)
.unwrap();

let round1_secret_package = SecretPackage {
identifier: participant_id,
coefficients,
commitment: commitment.clone(),
min_signers,
max_signers,
};

let (round2_secret_package, _round2_packages_1) =
part2(round1_secret_package, &round1_packages).unwrap();

let (expected_key_package, expected_public_key_package) =
part3(&round2_secret_package, &round1_packages, &round2_packages).unwrap();

assert_eq!(public_key_package, expected_public_key_package);
assert_eq!(key_package, expected_key_package);
}
55 changes: 55 additions & 0 deletions frost-ed25519/tests/helpers/vectors_dkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"config": {
"MAX_PARTICIPANTS": 3,
"MIN_PARTICIPANTS": 2,
"name": "FROST(Ed25519, SHA-512)",
"group": "ed25519",
"hash": "SHA-512"
},
"inputs": {
"secret": "8a1b0a95ea88ab6d615060fe392709e857edb4fc35b60f24bf7c085653c4b00e",
"verifying_key": "3d9a67b93cec3acad2d32349cf7bdffaa23ae031a81174ddadae1c96bb455f4d",
"1": {
"identifier": 1,
"signing_key": "fc36bff380c95d607cd78080f493dd382df50f7007ec1b150b9bfbd8041fd208",
"coefficient": "2d2c3e2b558e555b1608838e0ded66cd36d8aaa9ed1e39ce8474855d0825b20e",
"vss_commitments": ["db67948a73033b0c886ed757d97352428df05ad5803aff256bc388c9a0772bfe", "6a25b55a80a287826fbc3ef4d978d15f98f4f573f4d96e798a970780c644f14c"],
"proof_of_knowledge": "64c41c1d0417aef33576c23a5150de2921d6249d7086b10012f942405fc08ed51a872dd021db2ac01e9f4182e950324c5f563421bd835f3f514a60c975cab70c",
"secret": "6cf4cfbbad5e277a46bb621bfdf1b0a39e2ea1d4f927ddea58db7368e36b9108",
"signing_shares": {
"2": "ebb85acf4d46173f519a8680eac89f567d3f4a568843b741b251cc2f3d112b05",
"3": "f088e2c4b3a7f81836968c642721031ed8828d2e3d532fecaa85c481e445000c"
},
"verifying_share": "f6b5e87c902796d8dab6369cbd6d342a32e46c136e9f1f5af2fc385aed804de3",
"signing_share": "2afd4ef9a27f9e636dd627ae56772951b98f929ebaa13b11ede611e82e9baf08"
},
"2": {
"identifier": 2,
"vss_commitments": ["17194e192408980956a9cfc388d38456b2e9619c42a57196facd7feaf980a3bd", "0b560ce2f1130dc7066fc47f6e3f1858ef553faf6bbc19d3cd2a502052f95ae5"],
"proof_of_knowledge": "4062dc7fc11144e636f4eddd7f2d8d3e02761671ae913674314a12b91f50bf98e9c410d651c45c3a1766c88524fccb7670de191e12686324c59333e74fc93402",
"coefficient": "ad167472cc332ee98237a1018ea89a7e002420f9e5e518995a10298405a5870d",
"signing_key": "2b76dcb99b75fbada4ffdc213b1ae4ec7c1b2a5da25d9ea85741a3ab376ca307",
"secret": "b4570377a521cfe31fe2d6d7d6f70c8e1d9bca6222a4863953a2888bcccc860a",
"signing_shares": {
"1": "7ce74f90f61fe466fcad9757527aeda99aa565c3e2298eb11484069415693606",
"3": "7fde55b354d5d8dddc940fe932de5d1a6110b9bc4edeba2db7b32c34074d3a0a"
},
"verifying_share": "f326b756ed38b43a94bdac698e044d9e3f3a08a40e7c9d2e5346dd5bfaadf2f5",
"signing_share": "80a16ad6cf78be27995d5e312722ff2d42a5b08380b49dbc2e7e65c124220e0a"
},
"3": {
"identifier": 3,
"vss_commitments": ["0e9c22b9edbcd06757eee5ba3cfeb74e4fa6470932aa1ab689c86f1fe3dde70c", "0ae6e3e6ff1d612adb5cabb425ee51f2be9952467ce9b6d83095322909a42dd7"],
"proof_of_knowledge": "37df5a836ceaaf9f5e3b9ae6a485bad5c15788f3883386fe43f2921bbe2cb987d23683ca18973065a00d69bbf74f7961889b820e64f98878df7844a4e4785907",
"coefficient": "7c29694bbb90f21c7d9b7a27eab63911898d2b8e118b8b410c2e68b222073a0e",
"signing_key": "61336fd6127a18548f9709e01b64a8214ff561a02bc8a3aa9e575ccfc13ec60d",
"secret": "8d6468a928bc9b0610f2bf879a0f1738f86615460ac72314d49caf9a56452e05",
"signing_shares": {
"1": "bc3f985e314b276a3c192343816d7562d17d106dd048c77f99f88bf11d8ee804",
"2": "6b3e57fab1e74e61aacfd93d4926172a7e878a48540fe97367721e38485b3a00"
},
"verifying_share": "6bc91a2755902d955ce220ad0df6fbf57162260949d40bcf5a69cfffec9c085a",
"signing_share": "8bd411475cdc423c1ba94cf11b80e776592d5f675419398800d17173d673f40a"
}
}
}
8 changes: 8 additions & 0 deletions frost-ed25519/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,21 @@ lazy_static! {
pub static ref VECTORS_BIG_IDENTIFIER: Value =
serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim())
.expect("Test vector is valid JSON");
pub static ref VECTORS_DKG: Value =
serde_json::from_str(include_str!("../tests/helpers/vectors_dkg.json").trim())
.expect("Test vector is valid JSON");
}

#[test]
fn check_sign_with_test_vectors() {
frost_core::tests::vectors::check_sign_with_test_vectors::<Ed25519Sha512>(&VECTORS);
}

#[test]
fn check_sign_with_test_vectors_dkg() {
frost_core::tests::vectors_dkg::check_dkg_keygen::<Ed25519Sha512>(&VECTORS_DKG);
}

#[test]
fn check_sign_with_test_vectors_with_big_identifiers() {
frost_core::tests::vectors::check_sign_with_test_vectors::<Ed25519Sha512>(
Expand Down
51 changes: 51 additions & 0 deletions frost-ed448/tests/helpers/vectors_dkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"config": {
"MAX_PARTICIPANTS": 3,
"MIN_PARTICIPANTS": 2,
"name": "FROST(Ed448, SHAKE256)",
"group": "ed448",
"hash": "SHAKE256"
},
"inputs": {
"verifying_key": "2c73a3b674e283032effc2494341a608145179b229d664a870336a09b433363079a5ad68044eed31c3cc187267fe8216e559e4e4a8b9f49a80",
"1": {
"identifier": 1,
"signing_key": "01cbf4ac6b8ee0d03b799a62b7d7f32f05e2e117e9362f11004071fdb17ee2740206f45c910b4754eb0729e36e657136acfe16ff5abaf13800",
"coefficient": "74d5bf96312d4aaebf4c6a7e4760a50233f3fb0ce76f34df95781cd8a07b1607073cf70d8272f76956c67f6a9d643ba257e280f19754692300",
"vss_commitments": ["2747193abad63b685e15421f8c15c7c98107bf00d447561906a23e595dcba7367b7cf5ec4b7c751ec4f1721be4a1162d906af4c88a74c09b80", "abd8994d10bfb50fbd360b8f0ade24bd5362c12e06aa72ea9b92ab2d497399c78789a0874d3b0bf99a624549cbc7ec5ccaa503f1d80d189880"],
"proof_of_knowledge": "345f573924403f60672d42d2f428959935f2dca278cec91c955d166ab06ca0e7919e311d376f0c5e4e28a5df96dda71d36576fc7d7748b128063d520bd4b3a6ddcdf05bb84c87a83766218067a3ebb85664084a5a8c58d99b073526234be5ec518333f5e8bcc80ed11d563569123f2fd1200",
"signing_shares": {
"2": "e29c8b642abfa741710945aedadf34ac73ef6863c3e56d599cc3c58039d45b7382674cbd2c8e064c8bae33851c9166536181b83fe34ce02200",
"3": "ae2817fbc11b1595e432362f7d40f28953a545f193851d182e5914f4800ccfcc0194d75f170693e2c0b7be169b45e5d890aaac1d55db9f0d00"
},
"verifying_share": "4f4c185df443f1d836d213469cf7a52d4e0d0b9dd34046af1c29d0f6b5c7e9a8881c1a138b1c5cdce1a33c42b8f8068aac788f91e7de69a080",
"signing_share": "1fdca64c6411f60ea7e3f4a271d3e625dffcdf1b945b51d98c8dd3500edb23bc8d3d0f885712d8ec8d349be9c3a0f804f60cfd4d2b37db0c00"
},
"2": {
"identifier": 2,
"signing_key": "9e17dfce20dfd4f0d0bd893a75cba3ff3ab6574d716cd68b4b393d9cd3ff747dcbb6d629ee48d8cc06b29397f3706e18a497f641ee633b2d00",
"coefficient": "37ca04419ca24b74f5da8001d8d6fdcdc86fe7c49b54e6913aae526165d4e6f5b6b075933e452e7f84fc9fed2820f83abde9c1fdf4e8a43500",
"vss_commitments": ["01f375709143c4ad10db96da820082e5c2d802bd0ba78712bdbbe915f1b1d30d20732067395f157c124e4c9e32e37c47a59452950751d7d180", "f410470bc15065f35168c120b784d57db922c047f290ba7c1322b2c713d6d6cc44272b17c6ddc25abe54f4d2acd6c17fccbd9c25595d4ccf00"],
"proof_of_knowledge": "7bd1f9052217b2a02f4798906480ac288927c54dbd846e5bcbf4d08389a205269bf620a6ad1a04a3a0bcfd238c57f5f3960dd4795cebe66a80ed3c4617d163ec19648bd55d2f7acb4c4080c0062b878086ddb73f83aee1ad73426cab8a7d08f4540ccf6e31e08606861dd5daca506fc10d00",
"signing_shares": {
"1": "f6301c2f3c26fc096683a9d1d3d5d113db9103836d3b490b420de030f4750f83107ee27895f03528989428b8a92ee87a5bc318e28a63c43f00",
"3": "cdc0200642d408d6a2147eebba853b2ee42730d85ca72287b5e0ec8182ccbeddcf3e7845cd35588bd9b7c63d9657f704fc706d7becb3d62200"
},
"verifying_share": "053898556feae3f11a5977bcc0e14eb55086ff935aa22ec2c97b166e97c7a58fc165210d442069e66c4785fd6e7b3e7fcb7dd434055a1e5c80",
"signing_share": "f6ce1c841fd7064fc55d62515c8d6679dbabd725966622f5fa17519b16eb10ca19d51c0fcef9c27e81f7c26885373e0e769f009b4f4d203b00"
},
"3": {
"identifier": 3,
"signing_key": "82d5659bd4259a777be0b300b2bd1507535931b9143f676d90f505e37e4cdfbb33e9367a61d6cd39a8b7b6ef9f33d3ac25e4ebbfbd02693800",
"coefficient": "1f98090b80b8f340bee147bc3d4549a49082eae6c821056f8787d88d01c0ef10ceaaa0e5b52fc5a818000827fb11122c6bc6c05d97d8361500",
"vss_commitments": ["792df7d8f5569fb6ded2e5db245f2c1f07469d9cb0a7685a027b5d12142d245d1a417cca43ddaeab39f4cf4299aed16c638fc639eae1881000", "f13a1e5fb94aef454a6062735cfde4b37e173b695f3c86b77e5bda60b0a75a0f13446dfeb1fabb515cfb6cfef0973421fbf76bcec44fda9080"],
"proof_of_knowledge": "eb47491f2461792114d357d02102c1a806451cfa88f1297f7a671a87a04de0ffde478ec1c2b91e743379254fe84eb2e0d170c69aec88bc1980bf8009ffc93d6ee0c3713681aa303cf85595bd975953318ab07be9e56dc6ba22465793ee337e383562fafc7525c05b36732b93f5f4fee22300",
"signing_shares": {
"1": "77c1831adb90cd94d0404ec2a8730af57d4e29e10ad02e26ee61328c95f1258a17bad98617632d92ee5aa8224793231db3a599d322b82d2300",
"2": "e29c8b642abfa741710945aedadf34ac73ef6863c3e56d599cc3c58039d45b7382674cbd2c8e064c8bae33851c9166536181b83fe34ce02200"
},
"verifying_share": "3a1b5a9945fc64b088174c34e16dbced81f824fe8f9f12d1ec98afd4ea593a6ec75a74f70b77522c66681bd468080b525963dbcc2785d53a00",
"signing_share": "da7c3a1048da9e6b8e480a72d48479ab4724f9804e96a44c7f7e04691ffbfdd7a56c2a9644e1ad1075baeae746ce8317f63104e87363652900"
}
}
}
8 changes: 8 additions & 0 deletions frost-ed448/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,21 @@ lazy_static! {
pub static ref VECTORS_BIG_IDENTIFIER: Value =
serde_json::from_str(include_str!("../tests/helpers/vectors-big-identifier.json").trim())
.expect("Test vector is valid JSON");
pub static ref VECTORS_DKG: Value =
serde_json::from_str(include_str!("../tests/helpers/vectors_dkg.json").trim())
.expect("Test vector is valid JSON");
}

#[test]
fn check_sign_with_test_vectors() {
frost_core::tests::vectors::check_sign_with_test_vectors::<Ed448Shake256>(&VECTORS);
}

#[test]
fn check_sign_with_test_vectors_dkg() {
frost_core::tests::vectors_dkg::check_dkg_keygen::<Ed448Shake256>(&VECTORS_DKG);
}

#[test]
fn check_sign_with_test_vectors_with_big_identifiers() {
frost_core::tests::vectors::check_sign_with_test_vectors::<Ed448Shake256>(
Expand Down
Loading

0 comments on commit 1e29230

Please sign in to comment.