diff --git a/Cargo.lock b/Cargo.lock index 25bd616..e0b4d7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] name = "autocfg" @@ -115,18 +115,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.4" +version = "4.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80672091db20273a15cf9fdd4e47ed43b5091ec9841bf4c6145c9dfbbcae09ed" +checksum = "d9394150f5b4273a1763355bd1c2ec54cc5a2593f790587bcd6b2c947cfa9211" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.3.4" +version = "4.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636" +checksum = "9a78fbdd3cc2914ddf37ba444114bc7765bbdcb55ec9cbe6fa054f0137400717" dependencies = [ "anstyle", "bitflags", @@ -141,9 +141,9 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -265,7 +265,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2c35ab6e03642397cdda1dd58abbc05d418aef8e36297f336d5aba060fe8df" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", "syn 1.0.109", ] @@ -286,7 +286,7 @@ version = "0.1.0" dependencies = [ "exitcode", "eyre", - "frost-ed25519 0.5.0", + "frost-ed25519", "hex", "itertools", "rand", @@ -358,27 +358,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "frost-core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fe2b22eee8914aaf54ab74c7bc6cf71e539c40d92a746cf5c65b619acb02dc" -dependencies = [ - "byteorder", - "criterion", - "debugless-unwrap", - "digest", - "hex", - "itertools", - "proptest", - "proptest-derive", - "rand_core", - "serde_json", - "thiserror", - "visibility", - "zeroize", -] - [[package]] name = "frost-core" version = "0.5.0" @@ -403,18 +382,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "frost-ed25519" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f56348765eef8f99de247aba00c1599ba980ca372aa2e4c26c4e9d11e6e4b2" -dependencies = [ - "curve25519-dalek", - "frost-core 0.4.0", - "rand_core", - "sha2", -] - [[package]] name = "frost-ed25519" version = "0.5.0" @@ -422,7 +389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53e6ab361daf95ca692647e63377ced9b97017e4f4d475485d008dbc15519eab" dependencies = [ "curve25519-dalek", - "frost-core 0.5.0", + "frost-core", "rand_core", "sha2", ] @@ -548,9 +515,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libm" @@ -631,7 +598,7 @@ dependencies = [ name = "participant" version = "0.1.0" dependencies = [ - "frost-ed25519 0.4.0", + "frost-ed25519", "hex", ] @@ -643,9 +610,9 @@ checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" [[package]] name = "plotters" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -656,15 +623,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] @@ -686,9 +653,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] @@ -745,7 +712,7 @@ version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", ] [[package]] @@ -901,16 +868,16 @@ version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", - "syn 2.0.18", + "syn 2.0.22", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -929,9 +896,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -961,18 +928,18 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.18" +version = "2.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", "unicode-ident", ] @@ -1006,9 +973,9 @@ version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", - "syn 2.0.18", + "syn 2.0.22", ] [[package]] @@ -1026,7 +993,7 @@ name = "trusted-dealer" version = "0.1.0" dependencies = [ "exitcode", - "frost-ed25519 0.4.0", + "frost-ed25519", "hex", "itertools", "rand", @@ -1069,7 +1036,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8881d5cc0ae34e3db2f1de5af81e5117a420d2f937506c2dc20d6f4cfb069051" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", "syn 1.0.109", ] @@ -1118,9 +1085,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", - "syn 2.0.18", + "syn 2.0.22", "wasm-bindgen-shared", ] @@ -1140,9 +1107,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", - "syn 2.0.18", + "syn 2.0.22", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1275,7 +1242,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.60", + "proc-macro2 1.0.63", "quote 1.0.28", - "syn 2.0.18", + "syn 2.0.22", ] diff --git a/participant/Cargo.toml b/participant/Cargo.toml index 25b66e7..5619ccd 100644 --- a/participant/Cargo.toml +++ b/participant/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -frost-ed25519 = "0.4.0" +frost-ed25519 = "0.5.0" hex = "0.4" diff --git a/participant/src/cli.rs b/participant/src/cli.rs index 7a9c035..963dc5e 100644 --- a/participant/src/cli.rs +++ b/participant/src/cli.rs @@ -1,6 +1,8 @@ -use participant::{request_inputs, Logger}; +use participant::{generate_key_package, request_inputs, Logger}; use std::io::BufRead; pub fn cli(input: &mut impl BufRead, logger: &mut dyn Logger) { - let _config = request_inputs(input, logger); + let config = request_inputs(input, logger).unwrap(); // TODO: handle error + let _key_package = generate_key_package(config); + logger.log("Key Package succesfully created.".to_string()); } diff --git a/participant/src/lib.rs b/participant/src/lib.rs index 1b1db87..38f39cb 100644 --- a/participant/src/lib.rs +++ b/participant/src/lib.rs @@ -1,20 +1,28 @@ -use frost::{Error, Identifier, VerifyingKey}; +use frost::{ + keys::{ + KeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare, + }, + Error, Identifier, VerifyingKey, +}; use frost_ed25519 as frost; use hex::FromHex; use std::io::BufRead; +// TODO: Rethink the types here. They're inconsistent with each other #[derive(Debug, PartialEq)] pub struct Config { pub identifier: Identifier, - pub public_key: [u8; 32], + pub public_key: VerifyingShare, pub group_public_key: VerifyingKey, - pub signing_share: [u8; 32], + pub signing_share: SigningShare, + pub vss_commitment: Vec, } pub trait Logger { fn log(&mut self, value: String); } +// TODO: refactor to generate config pub fn request_inputs(input: &mut impl BufRead, logger: &mut dyn Logger) -> Result { logger.log("Your identifier (this should be an integer between 1 and 65535):".to_string()); @@ -33,17 +41,22 @@ pub fn request_inputs(input: &mut impl BufRead, logger: &mut dyn Logger) -> Resu input.read_line(&mut public_key_input).unwrap(); - let public_key = - <[u8; 32]>::from_hex(public_key_input.trim()).map_err(|_| Error::MalformedVerifyingKey)?; + // A specific VerifyingShare error does not currently exist in Frost so `MalformedVerifyingKey` + // has been used. This should either be added to Frost or the error handling here can be reconsidered + let public_key = VerifyingShare::from_bytes( + <[u8; 32]>::from_hex(public_key_input.trim()).map_err(|_| Error::MalformedVerifyingKey)?, + )?; //TODO: test error logger.log("The group public key:".to_string()); - let mut group_public_key_input = String::new(); input.read_line(&mut group_public_key_input).unwrap(); - let group_public_key = VerifyingKey::from_hex(group_public_key_input.trim()) - .map_err(|_| Error::MalformedVerifyingKey)?; // TODO: Frost library needs to be updated with correct Error type + let group_public_key = VerifyingKey::from_bytes( + <[u8; 32]>::from_hex(group_public_key_input.trim()) + .map_err(|_| Error::MalformedVerifyingKey)?, + ) + .map_err(|_| Error::MalformedVerifyingKey)?; // TODO: Add test for correct error to be returned on failing deserialisation logger.log("Your secret share:".to_string()); @@ -51,13 +64,91 @@ pub fn request_inputs(input: &mut impl BufRead, logger: &mut dyn Logger) -> Resu input.read_line(&mut signing_share_input).unwrap(); - let signing_share = - <[u8; 32]>::from_hex(signing_share_input.trim()).map_err(|_| Error::MalformedSigningKey)?; + // A specific SigningShare error does not currently exist in Frost so `MalformedSigningKey` + // has been used. This should either be added to Frost or the error handling here can be reconsidered + let signing_share = SigningShare::from_bytes( + <[u8; 32]>::from_hex(signing_share_input.trim()).map_err(|_| Error::MalformedSigningKey)?, + )?; //TODO: test error + + logger.log("Your verifiable secret sharing commitment:".to_string()); + + let mut vss_commitment_input = String::new(); + + input.read_line(&mut vss_commitment_input).unwrap(); + + let vss_commitment = hex::decode(vss_commitment_input.trim()).unwrap(); Ok(Config { identifier: Identifier::try_from(identifier)?, public_key, group_public_key, signing_share, + vss_commitment, }) } + +pub fn generate_key_package(config: Config) -> Result { + let secret_share = SecretShare::new( + config.identifier, + config.signing_share, + decode_vss_commitment(config.vss_commitment).unwrap(), + ); + let key_package = KeyPackage::try_from(secret_share)?; + + Ok(key_package) +} + +fn decode_vss_commitment( + vss_commitment: Vec, +) -> Result { + let coeff_commitments_data = vss_commitment[1..vss_commitment.len()].to_vec(); + + let n = vss_commitment[0] as usize; + let l = coeff_commitments_data.len() / n; + + let mut coeff_commitments = Vec::with_capacity(n); + + for i in 0..n { + let commitment_value = hex::encode(&coeff_commitments_data[(i * l)..((i * l) + l)]); + let serialized = + <[u8; 32]>::from_hex(commitment_value).map_err(|_| Error::InvalidCoefficients)?; // TODO: Is this the right error? Need to add test + coeff_commitments.push(serialized) + } + + let out = VerifiableSecretSharingCommitment::deserialize(coeff_commitments)?; //TODO: test for this error + Ok(out) +} + +#[cfg(test)] +mod tests { + use frost::keys::VerifiableSecretSharingCommitment; + use frost_ed25519 as frost; + use hex::FromHex; + + use crate::decode_vss_commitment; + + // TODO: Add details of encoding + #[test] + fn check_decode_vss_commitment() { + let vss_commitment_input = hex::decode("0353e4f0ed77543d021eb12cac53c35d4d99f5fc0fa5c3dfd82a3e1e296fba01bdcad2a298d93b5f0079f5f3874599ca2295482e9a4fa75be6c6deb273b61ee441e30ae9f78c1b56a4648130417247826afe3499c0d80b449740f8c968c64df0a4").unwrap(); + let expected = VerifiableSecretSharingCommitment::deserialize(vec![ + <[u8; 32]>::from_hex( + "53e4f0ed77543d021eb12cac53c35d4d99f5fc0fa5c3dfd82a3e1e296fba01bd", + ) + .unwrap(), + <[u8; 32]>::from_hex( + "cad2a298d93b5f0079f5f3874599ca2295482e9a4fa75be6c6deb273b61ee441", + ) + .unwrap(), + <[u8; 32]>::from_hex( + "e30ae9f78c1b56a4648130417247826afe3499c0d80b449740f8c968c64df0a4", + ) + .unwrap(), + ]) + .unwrap(); + + let actual = decode_vss_commitment(vss_commitment_input).unwrap(); + + assert!(expected == actual); + } +} diff --git a/participant/src/tests/cli.rs b/participant/src/tests/cli.rs index 39e95b7..d37765a 100644 --- a/participant/src/tests/cli.rs +++ b/participant/src/tests/cli.rs @@ -12,12 +12,14 @@ impl Logger for TestLogger { #[test] fn check_cli() { let identifier = "1"; - let pub_key = "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509"; - let group_pub_key = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673"; - let signing_share = "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d"; // SigningShare + let pub_key = "470f53fb724502bf5b851471e9f8317616fcc7be9405ccff3347c232a3052ce7"; + let group_pub_key = "42ae1baa1bce5a38c130e60aade154ec8775076e729881aba66dabd0c0ac6332"; + let signing_share = "1edfa2ebd280cba9a72f0bc027d21c30078c11f92e0c908addb958062c1ac900"; + let vss_commitment = "0342ae1baa1bce5a38c130e60aade154ec8775076e729881aba66dabd0c0ac6332393a813a6b47782f0fbe653593cbb7b0e0e13f01b54b801144545cb774c0fe5683d8bee3cd63b10523ccace10044869c56bce8a6061950f9aebd7f2e36249571"; + let input = format!( - "{}\n{}\n{}\n{}\n", - identifier, pub_key, group_pub_key, signing_share + "{}\n{}\n{}\n{}\n{}\n", + identifier, pub_key, group_pub_key, signing_share, vss_commitment ); let mut reader = input.as_bytes(); let mut test_logger = TestLogger(Vec::new()); @@ -29,5 +31,13 @@ fn check_cli() { ); assert_eq!(test_logger.0[1], format!("Your public key:")); assert_eq!(test_logger.0[2], format!("The group public key:")); - assert_eq!(test_logger.0[3], format!("Your secret share:")) + assert_eq!(test_logger.0[3], format!("Your secret share:")); + assert_eq!( + test_logger.0[4], + format!("Your verifiable secret sharing commitment:") + ); + assert_eq!( + test_logger.0[5], + format!("Key Package succesfully created.") + ) } diff --git a/participant/src/tests/lib.rs b/participant/src/tests/lib.rs index bf69d1f..ec95856 100644 --- a/participant/src/tests/lib.rs +++ b/participant/src/tests/lib.rs @@ -1,9 +1,12 @@ -use frost::VerifyingKey; +use frost::{ + keys::{KeyPackage, SigningShare, VerifyingShare}, + VerifyingKey, +}; #[cfg(test)] use frost::{Error, Identifier}; use frost_ed25519 as frost; use hex::FromHex; -use participant::{request_inputs, Config}; +use participant::{generate_key_package, request_inputs, Config}; use crate::Logger; @@ -15,25 +18,28 @@ impl Logger for TestLogger { } } +const IDENTIFIER: &str = "1"; +const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d"; +const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e"; +const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104"; +const VSS_COMMITMENT : &str = "03087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"; + #[test] fn check_valid_inputs() { - let public_key = "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509"; - let identifier = 1; - let group_public_key = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673"; - let signing_share = "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d"; - let config = Config { - identifier: Identifier::try_from(identifier).unwrap(), - public_key: <[u8; 32]>::from_hex(public_key).unwrap(), - group_public_key: VerifyingKey::from_hex(group_public_key).unwrap(), - signing_share: <[u8; 32]>::from_hex(signing_share).unwrap(), + identifier: Identifier::try_from(1).unwrap(), + public_key: VerifyingShare::from_bytes(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(), + group_public_key: VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(), + signing_share: SigningShare::from_bytes(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()) + .unwrap(), + vss_commitment: hex::decode(VSS_COMMITMENT).unwrap(), }; let mut test_logger = TestLogger(Vec::new()); let input = format!( - "{}\n{}\n{}\n{}\n", - identifier, public_key, group_public_key, signing_share + "{}\n{}\n{}\n{}\n{}\n", + IDENTIFIER, PUBLIC_KEY, GROUP_PUBLIC_KEY, SIGNING_SHARE, VSS_COMMITMENT ); let mut valid_input = input.as_bytes(); @@ -46,13 +52,10 @@ fn check_valid_inputs() { fn check_0_input_for_identifier() { let mut test_logger = TestLogger(Vec::new()); - let identifier = "0"; - let pub_key = "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509"; - let group_pub_key = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673"; - let signing_share = "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d"; + let invalid_identifier = "0"; let input = format!( - "{}\n{}\n{}\n{}\n", - identifier, pub_key, group_pub_key, signing_share + "{}\n{}\n{}\n{}\n{}\n", + invalid_identifier, PUBLIC_KEY, GROUP_PUBLIC_KEY, SIGNING_SHARE, VSS_COMMITMENT ); let mut invalid_input = input.as_bytes(); @@ -65,7 +68,10 @@ fn check_0_input_for_identifier() { fn check_non_u16_input_for_identifier() { let mut test_logger = TestLogger(Vec::new()); - let mut invalid_input = "-1\n".as_bytes(); + let invalid_identifier = "-1"; + let input = format!("{}\n", invalid_identifier); + let mut invalid_input = input.as_bytes(); + let expected = request_inputs(&mut invalid_input, &mut test_logger); assert!(expected.is_err()); @@ -75,13 +81,10 @@ fn check_non_u16_input_for_identifier() { fn check_invalid_length_public_key() { let mut test_logger = TestLogger(Vec::new()); - let identifier = "1"; - let pub_key = "123456"; - let group_pub_key = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673"; - let signing_share = "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d"; + let invalid_public_key = "123456"; let input = format!( - "{}\n{}\n{}\n{}\n", - identifier, pub_key, group_pub_key, signing_share + "{}\n{}\n{}\n{}\n{}\n", + IDENTIFIER, invalid_public_key, GROUP_PUBLIC_KEY, SIGNING_SHARE, VSS_COMMITMENT ); let mut invalid_input = input.as_bytes(); @@ -95,13 +98,10 @@ fn check_invalid_length_public_key() { fn check_invalid_length_group_public_key() { let mut test_logger = TestLogger(Vec::new()); - let identifier = "1"; - let pub_key = "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509"; - let group_pub_key = "123456"; - let signing_share = "a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d"; + let invalid_group_pub_key = "123456"; let input = format!( - "{}\n{}\n{}\n{}\n", - identifier, pub_key, group_pub_key, signing_share + "{}\n{}\n{}\n{}\n{}\n", + IDENTIFIER, PUBLIC_KEY, invalid_group_pub_key, SIGNING_SHARE, VSS_COMMITMENT ); let mut invalid_input = input.as_bytes(); @@ -115,13 +115,10 @@ fn check_invalid_length_group_public_key() { fn check_invalid_length_signing_share() { let mut test_logger = TestLogger(Vec::new()); - let identifier = "1"; - let pub_key = "929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509"; - let group_pub_key = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673"; - let signing_share = "123456"; + let invalid_signing_share = "123456"; let input = format!( - "{}\n{}\n{}\n{}\n", - identifier, pub_key, group_pub_key, signing_share + "{}\n{}\n{}\n{}\n{}\n", + IDENTIFIER, PUBLIC_KEY, GROUP_PUBLIC_KEY, invalid_signing_share, VSS_COMMITMENT ); let mut invalid_input = input.as_bytes(); @@ -130,3 +127,61 @@ fn check_invalid_length_signing_share() { assert!(expected.is_err()); assert!(expected == Err(Error::MalformedSigningKey)) } + +// TODO: Handle this error differently +#[test] +#[should_panic] +fn check_invalid_length_vss_commitment() { + let mut test_logger = TestLogger(Vec::new()); + + let invalid_vss_commitment = "1234567"; + let input = format!( + "{}\n{}\n{}\n{}\n{}\n", + IDENTIFIER, PUBLIC_KEY, GROUP_PUBLIC_KEY, SIGNING_SHARE, invalid_vss_commitment + ); + let mut invalid_input = input.as_bytes(); + + let _expected = request_inputs(&mut invalid_input, &mut test_logger); +} + +#[test] +fn check_key_package_generation() { + let config = Config { + identifier: Identifier::try_from(1).unwrap(), + public_key: VerifyingShare::from_bytes(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(), + group_public_key: VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(), + signing_share: SigningShare::from_bytes(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()) + .unwrap(), + vss_commitment: hex::decode(VSS_COMMITMENT).unwrap(), + }; + + let expected = KeyPackage::new( + config.identifier, + config.signing_share, + config.public_key, + config.group_public_key, + ); + let key_package = generate_key_package(config).unwrap(); + + assert!(expected == key_package) +} + +#[test] +fn check_key_package_generation_fails_with_invalid_secret_share() { + let incorrect_signing_share = + "afc0ba51fd450297725f9efe714400d51a1180a273177b5dd8ad3b8cba41560d"; + let config = Config { + identifier: Identifier::try_from(1).unwrap(), + public_key: VerifyingShare::from_bytes(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(), + group_public_key: VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(), + signing_share: SigningShare::from_bytes( + <[u8; 32]>::from_hex(incorrect_signing_share).unwrap(), + ) + .unwrap(), + vss_commitment: hex::decode(VSS_COMMITMENT).unwrap(), + }; + + let key_package = generate_key_package(config); + + assert!(key_package.is_err()); +} diff --git a/trusted-dealer/Cargo.toml b/trusted-dealer/Cargo.toml index 0a23e6e..d960c33 100644 --- a/trusted-dealer/Cargo.toml +++ b/trusted-dealer/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -frost-ed25519 = "0.4.0" +frost-ed25519 = "0.5.0" thiserror = "1.0" rand = "0.8" hex = "0.4" diff --git a/trusted-dealer/src/output.rs b/trusted-dealer/src/output.rs index 25a91ca..a1d9d1d 100644 --- a/trusted-dealer/src/output.rs +++ b/trusted-dealer/src/output.rs @@ -19,37 +19,46 @@ fn encode_commitment(vss_commitment: &VerifiableSecretSharingCommitment) -> Stri out } +fn get_identifier_value(i: Identifier) -> String { + let s = i.serialize(); + let le_bytes: [u8; 2] = [s[0], s[1]]; + u16::from_le_bytes(le_bytes).to_string() +} + pub fn print_values( keys: &HashMap, pubkeys: &PublicKeyPackage, logger: &mut dyn Logger, ) { logger.log(format!( - "Group public key: {:x?}", - hex::encode(pubkeys.group_public.to_bytes()) + "Group public key: {}", + hex::encode(pubkeys.group_public().to_bytes()) )); println!("---"); for (k, v) in keys.iter().sorted_by_key(|x| x.0) { - logger.log(format!("Participant {:?}", k)); + logger.log(format!("Participant: {}", get_identifier_value(*k))); logger.log(format!( - "Secret share: {:?}", - hex::encode(v.value.to_bytes()) + "Secret share: {}", + hex::encode(v.value().to_bytes()) )); logger.log(format!( - "Public key: {:?}", - hex::encode(pubkeys.signer_pubkeys[k].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[k].to_bytes()) + )); + logger.log(format!( + "Your verifiable secret sharing commitment: {}", + encode_commitment(v.commitment()) )); - logger.log(format!("Commitment: {}", encode_commitment(&v.commitment))); println!("---") } } #[cfg(test)] mod tests { - use crate::output::encode_commitment; - use frost::keys::VerifiableSecretSharingCommitment; + use crate::output::{encode_commitment, get_identifier_value}; + use frost::{keys::VerifiableSecretSharingCommitment, Identifier}; use frost_ed25519 as frost; use hex::FromHex; @@ -71,4 +80,17 @@ mod tests { let commitment = encode_commitment(&vss_commitment); assert!(commitment == expected) } + + #[test] + fn check_get_identifier_value() { + let min = "1"; + let identifier_min = Identifier::try_from(1).unwrap(); + + assert!(get_identifier_value(identifier_min) == min); + + let max = "65535"; + let identifier_max = Identifier::try_from(65535).unwrap(); + + assert!(get_identifier_value(identifier_max) == max); + } } diff --git a/trusted-dealer/src/tests/integration_test.rs b/trusted-dealer/src/tests/integration_test.rs index 11eaf70..b2b02bb 100644 --- a/trusted-dealer/src/tests/integration_test.rs +++ b/trusted-dealer/src/tests/integration_test.rs @@ -21,12 +21,12 @@ fn check_keygen_with_dealer() { signature_gen::generate_nonces_and_commitments(config.min_signers, &key_packages, &mut rng); let message = "message to sign".as_bytes(); let comms = commitments.into_values().collect(); - let signing_package = frost::SigningPackage::new(comms, message.to_vec()); + let signing_package = frost::SigningPackage::new(comms, message); let signature_shares = signature_gen::generate_signature_shares(nonces, &key_packages, &signing_package); let group_signature = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys).unwrap(); - let verify_signature = pubkeys.group_public.verify(message, &group_signature); + let verify_signature = pubkeys.group_public().verify(message, &group_signature); assert!(verify_signature.is_ok()); } @@ -45,12 +45,12 @@ fn check_keygen_with_dealer_with_large_num_of_signers() { signature_gen::generate_nonces_and_commitments(config.min_signers, &key_packages, &mut rng); let message = "message to sign".as_bytes(); let comms = commitments.into_values().collect(); - let signing_package = frost::SigningPackage::new(comms, message.to_vec()); + let signing_package = frost::SigningPackage::new(comms, message); let signature_shares = signature_gen::generate_signature_shares(nonces, &key_packages, &signing_package); let group_signature = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys).unwrap(); - let verify_signature = pubkeys.group_public.verify(message, &group_signature); + let verify_signature = pubkeys.group_public().verify(message, &group_signature); assert!(verify_signature.is_ok()); } @@ -76,12 +76,12 @@ fn check_keygen_with_dealer_with_secret() { ); let message = "message to sign".as_bytes(); let comms = commitments.into_values().collect(); - let signing_package = frost::SigningPackage::new(comms, message.to_vec()); + let signing_package = frost::SigningPackage::new(comms, message); let signature_shares = signature_gen::generate_signature_shares(nonces, &key_packages, &signing_package); let group_signature = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys).unwrap(); - let verify_signature = pubkeys.group_public.verify(message, &group_signature); + let verify_signature = pubkeys.group_public().verify(message, &group_signature); assert!(verify_signature.is_ok()); } @@ -107,12 +107,12 @@ fn check_keygen_with_dealer_with_secret_with_large_num_of_signers() { ); let message = "message to sign".as_bytes(); let comms = commitments.into_values().collect(); - let signing_package = frost::SigningPackage::new(comms, message.to_vec()); + let signing_package = frost::SigningPackage::new(comms, message); let signature_shares = signature_gen::generate_signature_shares(nonces, &key_packages, &signing_package); let group_signature = frost::aggregate(&signing_package, &signature_shares[..], &pubkeys).unwrap(); - let verify_signature = pubkeys.group_public.verify(message, &group_signature); + let verify_signature = pubkeys.group_public().verify(message, &group_signature); assert!(verify_signature.is_ok()); } diff --git a/trusted-dealer/src/tests/output_tests.rs b/trusted-dealer/src/tests/output_tests.rs index c74e707..6d750cd 100644 --- a/trusted-dealer/src/tests/output_tests.rs +++ b/trusted-dealer/src/tests/output_tests.rs @@ -40,80 +40,84 @@ fn check_output_without_secret() { let signer_2 = Identifier::try_from(2).unwrap(); let signer_3 = Identifier::try_from(3).unwrap(); + let signer_1_id = "1"; + let signer_2_id = "2"; + let signer_3_id = "3"; + assert_eq!( test_logger.0[0], format!( - "Group public key: \"{}\"", - hex::encode(pubkeys.group_public.to_bytes()) + "Group public key: {}", + hex::encode(pubkeys.group_public().to_bytes()) ) ); - assert_eq!(test_logger.0[1], format!("Participant {:?}", signer_1)); + assert_eq!(test_logger.0[1], format!("Participant: {}", signer_1_id)); assert_eq!( test_logger.0[2], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_1].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_1].value().to_bytes()) ) ); assert_eq!( test_logger.0[3], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_1].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_1].to_bytes()) ) ); assert_eq!( test_logger.0[4], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_1].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_1].commitment().serialize()) ) ); - assert_eq!(test_logger.0[5], format!("Participant {:?}", signer_2)); + assert_eq!(test_logger.0[5], format!("Participant: {}", signer_2_id)); assert_eq!( test_logger.0[6], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_2].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_2].value().to_bytes()) ) ); assert_eq!( test_logger.0[7], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_2].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_2].to_bytes()) ) ); assert_eq!( test_logger.0[8], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_2].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_2].commitment().serialize()) ) ); - assert_eq!(test_logger.0[9], format!("Participant {:?}", signer_3)); + assert_eq!(test_logger.0[9], format!("Participant: {}", signer_3_id)); assert_eq!( test_logger.0[10], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_3].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_3].value().to_bytes()) ) ); assert_eq!( test_logger.0[11], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_3].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_3].to_bytes()) ) ); assert_eq!( test_logger.0[12], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_3].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_3].commitment().serialize()) ) ); } @@ -139,80 +143,84 @@ fn check_output_with_secret() { let signer_2 = Identifier::try_from(2).unwrap(); let signer_3 = Identifier::try_from(3).unwrap(); + let signer_1_id = "1"; + let signer_2_id = "2"; + let signer_3_id = "3"; + assert_eq!( test_logger.0[0], format!( - "Group public key: \"{}\"", - hex::encode(pubkeys.group_public.to_bytes()) + "Group public key: {}", + hex::encode(pubkeys.group_public().to_bytes()) ) ); - assert_eq!(test_logger.0[1], format!("Participant {:?}", signer_1)); + assert_eq!(test_logger.0[1], format!("Participant: {}", signer_1_id)); assert_eq!( test_logger.0[2], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_1].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_1].value().to_bytes()) ) ); assert_eq!( test_logger.0[3], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_1].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_1].to_bytes()) ) ); assert_eq!( test_logger.0[4], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_1].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_1].commitment().serialize()) ) ); - assert_eq!(test_logger.0[5], format!("Participant {:?}", signer_2)); + assert_eq!(test_logger.0[5], format!("Participant: {}", signer_2_id)); assert_eq!( test_logger.0[6], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_2].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_2].value().to_bytes()) ) ); assert_eq!( test_logger.0[7], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_2].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_2].to_bytes()) ) ); assert_eq!( test_logger.0[8], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_2].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_2].commitment().serialize()) ) ); - assert_eq!(test_logger.0[9], format!("Participant {:?}", signer_3)); + assert_eq!(test_logger.0[9], format!("Participant: {}", signer_3_id)); assert_eq!( test_logger.0[10], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_3].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_3].value().to_bytes()) ) ); assert_eq!( test_logger.0[11], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_3].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_3].to_bytes()) ) ); assert_eq!( test_logger.0[12], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_3].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_3].commitment().serialize()) ) ); } @@ -231,35 +239,36 @@ fn check_output_with_large_num_of_signers() { print_values(&shares, &pubkeys, &mut test_logger); let signer_10 = Identifier::try_from(10).unwrap(); + let signer_10_id = "10"; assert_eq!( test_logger.0[0], format!( - "Group public key: \"{}\"", - hex::encode(pubkeys.group_public.to_bytes()) + "Group public key: {}", + hex::encode(pubkeys.group_public().to_bytes()) ) ); - assert_eq!(test_logger.0[37], format!("Participant {:?}", signer_10)); + assert_eq!(test_logger.0[37], format!("Participant: {}", signer_10_id)); assert_eq!( test_logger.0[38], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_10].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_10].value().to_bytes()) ) ); assert_eq!( test_logger.0[39], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_10].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_10].to_bytes()) ) ); assert_eq!( test_logger.0[40], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_10].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_10].commitment().serialize()) ) ); } @@ -282,35 +291,36 @@ fn check_output_with_secret_with_large_num_of_signers() { print_values(&shares, &pubkeys, &mut test_logger); let signer_10 = Identifier::try_from(10).unwrap(); + let signer_10_id = "10"; assert_eq!( test_logger.0[0], format!( - "Group public key: \"{}\"", - hex::encode(pubkeys.group_public.to_bytes()) + "Group public key: {}", + hex::encode(pubkeys.group_public().to_bytes()) ) ); - assert_eq!(test_logger.0[37], format!("Participant {:?}", signer_10)); + assert_eq!(test_logger.0[37], format!("Participant: {}", signer_10_id)); assert_eq!( test_logger.0[38], format!( - "Secret share: \"{}\"", - hex::encode(shares[&signer_10].value.to_bytes()) + "Secret share: {}", + hex::encode(shares[&signer_10].value().to_bytes()) ) ); assert_eq!( test_logger.0[39], format!( - "Public key: \"{}\"", - hex::encode(pubkeys.signer_pubkeys[&signer_10].to_bytes()) + "Public key: {}", + hex::encode(pubkeys.signer_pubkeys()[&signer_10].to_bytes()) ) ); assert_eq!( test_logger.0[40], format!( - "Commitment: {}", - encode_commitment_helper(shares[&signer_10].commitment.serialize()) + "Your verifiable secret sharing commitment: {}", + encode_commitment_helper(shares[&signer_10].commitment().serialize()) ) ); }