From 9965591a83009fd32c5b57a3f28482a6879582b5 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Thu, 27 Feb 2025 10:41:00 -0300 Subject: [PATCH] frost-client: add message confirmation step to Comms trait (#491) * frost-client: add message confirmation step to Comms trait * actually call the new comms method --- participant/src/cli.rs | 15 +++-------- participant/src/comms.rs | 36 +++++++++++++++++++++----- participant/src/comms/cli.rs | 23 +++++++++------- participant/src/comms/http.rs | 29 +++------------------ participant/src/comms/socket.rs | 15 +++++------ participant/src/round2.rs | 27 +++++++++---------- participant/src/tests/round2.rs | 10 ++++--- participant/tests/integration_tests.rs | 11 +++++--- 8 files changed, 85 insertions(+), 81 deletions(-) diff --git a/participant/src/cli.rs b/participant/src/cli.rs index 8e11dcee..55ff98d1 100644 --- a/participant/src/cli.rs +++ b/participant/src/cli.rs @@ -8,7 +8,7 @@ use crate::comms::Comms; use crate::round1::{generate_nonces_and_commitments, print_values}; use crate::round2::{generate_signature, print_values_round_2, round_2_request_inputs}; -use eyre::eyre; + use frost_core::Ciphersuite; use frost_ed25519::Ed25519Sha512; use frost_rerandomized::RandomizedCiphersuite; @@ -69,16 +69,9 @@ pub async fn cli_for_processed_args( ) .await?; - writeln!( - logger, - "Message to be signed (hex-encoded):\n{}\nDo you want to sign it? (y/n)", - hex::encode(round_2_config.signing_package.message()) - )?; - let mut sign_it = String::new(); - input.read_line(&mut sign_it)?; - if sign_it.trim() != "y" { - return Err(eyre!("signing cancelled").into()); - } + comms + .confirm_message(input, logger, &round_2_config) + .await?; let signature = generate_signature(round_2_config, &key_package, &nonces)?; diff --git a/participant/src/comms.rs b/participant/src/comms.rs index 51f23ee9..0a7b952b 100644 --- a/participant/src/comms.rs +++ b/participant/src/comms.rs @@ -3,8 +3,10 @@ pub mod http; pub mod socket; use async_trait::async_trait; +use eyre::eyre; use frost_core::{self as frost, Ciphersuite}; +use frostd::SendSigningPackageArgs; use std::{ error::Error, @@ -43,13 +45,33 @@ pub trait Comms { commitments: SigningCommitments, identifier: Identifier, rerandomized: bool, - ) -> Result< - ( - frost::SigningPackage, - Option>, - ), - Box, - >; + ) -> Result, Box>; + + /// Ask the user if they want to sign the message. + /// + /// Implementations should show the message to the user (or auxiliary data + /// that maps to the message) and ask for confirmation. + /// + /// The default implementation prints the message to output and reads + /// confirmation from input. + async fn confirm_message( + &mut self, + input: &mut dyn BufRead, + output: &mut dyn Write, + signing_package: &SendSigningPackageArgs, + ) -> Result<(), Box> { + writeln!( + output, + "Message to be signed (hex-encoded):\n{}\nDo you want to sign it? (y/n)", + hex::encode(signing_package.signing_package[0].message()) + )?; + let mut sign_it = String::new(); + input.read_line(&mut sign_it)?; + if sign_it.trim() != "y" { + return Err(eyre!("signing cancelled").into()); + } + Ok(()) + } async fn send_signature_share( &mut self, diff --git a/participant/src/comms/cli.rs b/participant/src/comms/cli.rs index 976e8b91..00dc7088 100644 --- a/participant/src/comms/cli.rs +++ b/participant/src/comms/cli.rs @@ -10,6 +10,7 @@ use frost::{ keys::PublicKeyPackage, round1::SigningCommitments, round2::SignatureShare, Identifier, SigningPackage, }; +use frostd::SendSigningPackageArgs; use std::{ error::Error, @@ -47,13 +48,7 @@ where _commitments: SigningCommitments, _identifier: Identifier, rerandomized: bool, - ) -> Result< - ( - frost::SigningPackage, - Option>, - ), - Box, - > { + ) -> Result, Box> { writeln!(output, "Enter the JSON-encoded SigningPackage:")?; let mut signing_package_json = String::new(); @@ -71,9 +66,19 @@ where let randomizer = frost_rerandomized::Randomizer::::deserialize(&hex::decode(json.trim())?)?; - Ok((signing_package, Some(randomizer))) + let r = frostd::SendSigningPackageArgs:: { + signing_package: vec![signing_package], + randomizer: vec![randomizer], + aux_msg: vec![], + }; + Ok(r) } else { - Ok((signing_package, None)) + let r = frostd::SendSigningPackageArgs:: { + signing_package: vec![signing_package], + randomizer: vec![], + aux_msg: vec![], + }; + Ok(r) } } diff --git a/participant/src/comms/http.rs b/participant/src/comms/http.rs index e866f0f1..b64b2b3e 100644 --- a/participant/src/comms/http.rs +++ b/participant/src/comms/http.rs @@ -9,9 +9,7 @@ use std::{ use async_trait::async_trait; use eyre::{eyre, OptionExt}; -use frost_core::{ - self as frost, round1::SigningCommitments, round2::SignatureShare, Ciphersuite, Identifier, -}; +use frost_core::{round1::SigningCommitments, round2::SignatureShare, Ciphersuite, Identifier}; use rand::thread_rng; use snow::{HandshakeState, TransportState}; use xeddsa::{xed25519, Sign as _}; @@ -169,14 +167,8 @@ where _output: &mut dyn Write, commitments: SigningCommitments, _identifier: Identifier, - rerandomized: bool, - ) -> Result< - ( - frost::SigningPackage, - Option>, - ), - Box, - > { + _rerandomized: bool, + ) -> Result, Box> { let mut rng = thread_rng(); eprintln!("Logging in..."); @@ -334,20 +326,7 @@ where } }; - if rerandomized { - let signing_package = r - .signing_package - .first() - .ok_or(eyre!("missing signing package"))?; - let randomizer = r.randomizer.first().ok_or(eyre!("missing randomizer"))?; - Ok((signing_package.clone(), Some(*randomizer))) - } else { - let signing_package = r - .signing_package - .first() - .ok_or(eyre!("missing signing package"))?; - Ok((signing_package.clone(), None)) - } + Ok(r) } async fn send_signature_share( diff --git a/participant/src/comms/socket.rs b/participant/src/comms/socket.rs index 6d01531e..fe7aa314 100644 --- a/participant/src/comms/socket.rs +++ b/participant/src/comms/socket.rs @@ -5,6 +5,7 @@ use async_trait::async_trait; use frost_core::{self as frost, Ciphersuite}; use eyre::eyre; +use frostd::SendSigningPackageArgs; use message_io::{ network::{Endpoint, NetEvent, Transport}, node::{self, NodeHandler, NodeListener}, @@ -89,13 +90,7 @@ where commitments: SigningCommitments, identifier: Identifier, _rerandomized: bool, - ) -> Result< - ( - frost::SigningPackage, - Option>, - ), - Box, - > { + ) -> Result, Box> { // Send Commitments to Coordinator let data = serde_json::to_vec(&Message::::IdentifiedCommitments { identifier, @@ -116,7 +111,11 @@ where randomizer, } = message { - Ok((signing_package, randomizer)) + Ok(SendSigningPackageArgs:: { + signing_package: vec![signing_package], + randomizer: randomizer.map(|r| vec![r]).unwrap_or_default(), + aux_msg: vec![], + }) } else { Err(eyre!("Expected SigningPackage message"))? } diff --git a/participant/src/round2.rs b/participant/src/round2.rs index 869b3515..51b2e58e 100644 --- a/participant/src/round2.rs +++ b/participant/src/round2.rs @@ -1,4 +1,5 @@ use frost_core::{self as frost, Ciphersuite}; +use frostd::SendSigningPackageArgs; use crate::comms::Comms; use frost::{ @@ -24,28 +25,28 @@ pub async fn round_2_request_inputs( commitments: SigningCommitments, identifier: Identifier, rerandomized: bool, -) -> Result, Box> { - let r = comms +) -> Result, Box> { + comms .get_signing_package(input, logger, commitments, identifier, rerandomized) - .await?; - - Ok(Round2Config { - signing_package: r.0, - randomizer: r.1, - }) + .await } pub fn generate_signature( - config: Round2Config, + config: SendSigningPackageArgs, key_package: &KeyPackage, signing_nonces: &SigningNonces, ) -> Result, Error> { - let signing_package = config.signing_package; + let signing_package = config.signing_package.first().unwrap(); - let signature = if let Some(randomizer) = config.randomizer { - frost_rerandomized::sign::(&signing_package, signing_nonces, key_package, randomizer)? + let signature = if !config.randomizer.is_empty() { + frost_rerandomized::sign::( + signing_package, + signing_nonces, + key_package, + config.randomizer[0], + )? } else { - round2::sign(&signing_package, signing_nonces, key_package)? + round2::sign(signing_package, signing_nonces, key_package)? }; Ok(signature) } diff --git a/participant/src/tests/round2.rs b/participant/src/tests/round2.rs index fd3f0a10..53bcb22d 100644 --- a/participant/src/tests/round2.rs +++ b/participant/src/tests/round2.rs @@ -11,6 +11,7 @@ use frost::{ round2::SignatureShare, SigningPackage, VerifyingKey, }; +use frostd::SendSigningPackageArgs; use hex::FromHex; use participant::comms::cli::CLIComms; use participant::round2::print_values_round_2; @@ -82,7 +83,7 @@ async fn check_valid_round_2_inputs() { assert!(round_2_config.is_ok()); assert_eq!( expected.signing_package, - round_2_config.unwrap().signing_package + round_2_config.unwrap().signing_package[0] ) } @@ -120,9 +121,10 @@ async fn check_sign() { let signing_package = SigningPackage::new(signer_commitments, message); - let config = Round2Config { - signing_package, - randomizer: None, + let config = SendSigningPackageArgs { + signing_package: vec![signing_package], + randomizer: vec![], + aux_msg: vec![], }; let signature = generate_signature(config, &key_package, &nonces); diff --git a/participant/tests/integration_tests.rs b/participant/tests/integration_tests.rs index 3fa2ed45..1a4286aa 100644 --- a/participant/tests/integration_tests.rs +++ b/participant/tests/integration_tests.rs @@ -1,10 +1,12 @@ use std::collections::{BTreeMap, HashMap}; +use std::vec; use frost_ed25519 as frost; use frost::keys::IdentifierList; use frost::{aggregate, SigningPackage}; -use participant::round2::{generate_signature, Round2Config}; +use frostd::SendSigningPackageArgs; +use participant::round2::generate_signature; use rand::thread_rng; #[test] @@ -40,9 +42,10 @@ fn check_participant() { let mut signature_shares = BTreeMap::new(); for participant_identifier in nonces.keys() { - let config = Round2Config { - signing_package: SigningPackage::new(commitments.clone(), &message), - randomizer: None, + let config = SendSigningPackageArgs { + signing_package: vec![SigningPackage::new(commitments.clone(), &message)], + randomizer: vec![], + aux_msg: vec![], }; let signature = generate_signature( config,