diff --git a/src/simplpedpop.rs b/src/simplpedpop.rs index 354e96e..5bea66d 100644 --- a/src/simplpedpop.rs +++ b/src/simplpedpop.rs @@ -98,14 +98,14 @@ impl Parameters { fn derive_secret_key_from_secret(secret: Secret, mut rng: R) -> SecretKey { let mut bytes = [0u8; 64]; let mut nonce: [u8; 32] = [0u8; 32]; - rng.fill_bytes(&mut nonce); + rng.fill_bytes(&mut nonce); let secret_bytes = secret.to_bytes(); bytes[..32].copy_from_slice(&secret_bytes[..]); bytes[32..].copy_from_slice(&nonce[..]); - SecretKey::from_bytes(&bytes[..]).unwrap() // this never fails + SecretKey::from_bytes(&bytes[..]).unwrap() // This never fails because bytes has length 64 and the key is a scalar } /// SimplPedPoP round 1. @@ -176,7 +176,7 @@ pub mod round1 { } } - /// Private message to sent by a participant to another participant or to the coordinator in encrypted form in round.1 + /// Private message to sent by a participant to another participant or to the coordinator in encrypted form in round 1. #[derive(Debug, Clone, ZeroizeOnDrop, Getters)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct PrivateMessage { @@ -197,17 +197,17 @@ pub mod round1 { ) -> DKGResult<(PrivateData, Messages, PublicData)> { parameters.validate()?; - let (private_data, pop, secret_polynomial, public_data) = + let (private_data, proof_of_possession, secret_polynomial, public_data) = generate_data(parameters, &mut rng); - let round_messages = generate_messages( + let messages = generate_messages( parameters, - &pop, + &proof_of_possession, &secret_polynomial, &public_data.secret_polynomial_commitment, ); - Ok((private_data, round_messages, public_data)) + Ok((private_data, messages, public_data)) } fn generate_data( @@ -216,6 +216,7 @@ pub mod round1 { ) -> (PrivateData, ProofOfPossession, SecretPolynomial, PublicData) { let secret_polynomial = loop { let temp_polynomial = Polynomial::generate(&mut rng, *parameters.threshold()); + // There must be a secret, which is the constant coefficient of the secret polynomial if temp_polynomial.constant_coefficient != Scalar::ZERO { break temp_polynomial; } @@ -225,6 +226,7 @@ pub mod round1 { let secret_share = secret_polynomial.evaluate(¶meters.own_identifier().0); + // This secret key will be used to sign the proof of possession and the certificate let secret_key = derive_secret_key_from_secret(secret_polynomial.constant_coefficient, rng); let public_key = @@ -254,9 +256,9 @@ pub mod round1 { secret_polynomial_commitment: &SecretPolynomialCommitment, ) -> Messages { let mut private_messages = BTreeMap::new(); + for identifier in ¶meters.others_identifiers { let secret_share = secret_polynomial.evaluate(&identifier.0); - private_messages.insert(*identifier, PrivateMessage::new(SecretShare(secret_share))); } @@ -341,16 +343,11 @@ pub mod round2 { verify_round1_messages(parameters, round1_public_messages, &round1_private_messages)?; - let mut round1_private_messages = round1_private_messages; - - round1_private_messages.insert( - *parameters.own_identifier(), - round1::PrivateMessage { - secret_share: round1_private_data.secret_share, - }, - ); - - let private_data = generate_private_data(parameters, &round1_private_messages)?; + let private_data = generate_private_data( + parameters, + &round1_private_messages, + &round1_private_data.secret_share, + )?; let public_data = generate_public_data(round1_public_messages, round1_public_data, transcript)?; @@ -371,6 +368,7 @@ pub mod round2 { fn generate_private_data( parameters: &Parameters, private_messages: &BTreeMap, + own_secret_share: &SecretShare, ) -> DKGResult { let mut total_secret_share = Scalar::ZERO; @@ -382,11 +380,7 @@ pub mod round2 { .0; } - total_secret_share += private_messages - .get(parameters.own_identifier()) - .ok_or(DKGError::UnknownIdentifier)? - .secret_share() - .0; + total_secret_share += own_secret_share.0; let private_data = PrivateData { total_secret_share: SecretShare(total_secret_share), @@ -400,12 +394,13 @@ pub mod round2 { round1_public_data: &round1::PublicData, mut transcript: T, ) -> DKGResult> { + // Writes the data of all the participants in the transcript ordered by their identifiers for identifier in 1..=round1_public_messages.len() + 1 { if let Some(round1_public_message) = round1_public_messages.get(&(identifier as u16).try_into().unwrap()) - // this never fails + // This never fails because we previously checked for invalid identifiers { - // Committing points for each identifier present in round1_public_messages + // Writes the data of the other participants in the transcript transcript.commit_point( b"SecretCommitment", &round1_public_message @@ -427,8 +422,7 @@ pub mod round2 { &round1_public_message.proof_of_possession().R, ); } else { - // This else branch handles the case where an identifier is missing. - // Inserting code for processing round1_public_data here. + // Writes the data of the participant in the transcript transcript.commit_point( b"SecretCommitment", &round1_public_data @@ -460,20 +454,20 @@ pub mod round2 { round1_public_messages: &BTreeMap, round1_private_messages: &BTreeMap, ) -> DKGResult<()> { - for id in parameters.others_identifiers() { - let received_public_msg = round1_public_messages - .get(id) + for identifier in parameters.others_identifiers() { + let public_message = round1_public_messages + .get(identifier) .ok_or(DKGError::UnknownIdentifier)?; - let received_private_msg = round1_private_messages - .get(id) + let private_message = round1_private_messages + .get(identifier) .ok_or(DKGError::UnknownIdentifier)?; verify_round1_private_message( parameters, - received_public_msg, - received_private_msg, - *id, + public_message, + private_message, + *identifier, )?; } @@ -487,8 +481,9 @@ pub mod round2 { let mut public_keys = Vec::new(); let mut proofs_of_possession = Vec::new(); - for (id, public_message) in round1_public_messages { - if id != parameters.own_identifier() { + // The public keys are the secret commitments of the participants + for (identifier, public_message) in round1_public_messages { + if identifier != parameters.own_identifier() { let public_key = PublicKey::from_point( public_message .secret_polynomial_commitment() @@ -514,12 +509,13 @@ pub mod round2 { round1_private_message: &PrivateMessage, identifier: Identifier, ) -> DKGResult<()> { - let result = GENERATOR * round1_private_message.secret_share().0; - let f_result = round1_public_message + let expected_evaluation = GENERATOR * round1_private_message.secret_share().0; + + let evaluation = round1_public_message .secret_polynomial_commitment() .evaluate(params.own_identifier().0); - if !(f_result == result) { + if !(evaluation == expected_evaluation) { Err(DKGError::InvalidSecretShare(identifier)) } else { Ok(()) @@ -602,6 +598,7 @@ pub mod round3 { ) -> DKGResult<()> { let mut public_keys = Vec::new(); + // The public keys are the secret commitments of the participants for (id, round1_public_message) in round1_public_messages { if id != parameters.own_identifier() { let public_key = PublicKey::from_point( @@ -633,19 +630,22 @@ pub mod round3 { SharedPublicKey, BTreeMap, )> { - let partial_secret_polynomial_commitment = PolynomialCommitment::sum_polynomial_commitments( + // Sum of the secret polynomial commitments of the other participants + let others_secret_polynomial_commitment = PolynomialCommitment::sum_polynomial_commitments( &round1_public_messages .iter() .map(|x| x.1.secret_polynomial_commitment()) .collect::>(), ); + // The total secret polynomial commitment, which includes the secret polynomial commitment of the participant let total_secret_polynomial_commitment = PolynomialCommitment::sum_polynomial_commitments(&[ - &partial_secret_polynomial_commitment, + &others_secret_polynomial_commitment, &round1_public_data.secret_polynomial_commitment, ]); + // The total secret shares commitments of all the participants let mut total_secret_shares_commitments = BTreeMap::new(); for identifier in parameters.others_identifiers() { @@ -665,6 +665,7 @@ pub mod round3 { total_secret_polynomial_commitment.constant_coefficient_commitment, ); + // The shared public key corresponds to the secret commitment of the total secret polynomial commitment if shared_public_key.as_point() != &total_secret_polynomial_commitment.evaluate(Scalar::ZERO) { @@ -676,12 +677,10 @@ pub mod round3 { } #[cfg(test)] -pub mod tests { - use crate::SignatureError; - +mod tests { use self::round1::{PrivateData, PublicData}; - use super::*; + use crate::SignatureError; use alloc::borrow::ToOwned; #[cfg(feature = "alloc")] use alloc::{ @@ -713,152 +712,6 @@ pub mod tests { .collect() } - #[test] - pub fn test_successful_simplpedpop() { - let participants: u16 = 5; - let threshold: u16 = 3; - - let ( - parameters_list, - participants_round1_private_data, - participants_round1_public_data, - mut participants_round1_public_messages, - participants_round1_private_messages, - identifiers, - ) = round1(participants, threshold); - - for i in 0..participants { - participants_round1_public_messages[i as usize] - .remove(¶meters_list[i as usize].own_identifier()); - } - - let ( - participants_public_data_round2, - participants_private_data_round2, - participants_public_msgs_round2, - ) = round2( - participants, - parameters_list.clone(), - participants_round1_private_data.clone(), - participants_round1_public_data.clone(), - participants_round1_public_messages.clone(), - participants_round1_private_messages.clone(), - ); - - let participant_data_round3 = round3( - participants, - identifiers, - ¶meters_list, - participants_public_msgs_round2, - participants_public_data_round2, - participants_round1_public_messages, - participants_round1_public_data, - ); - - let shared_public_keys: Vec = participant_data_round3 - .iter() - .map(|state| state.0) - .collect(); - - assert!( - shared_public_keys.windows(2).all(|w| w[0] == w[1]), - "All participants should have the same shared public key!" - ); - - for i in 0..participants { - assert_eq!( - participant_data_round3[i as usize] - .1 - .get(parameters_list[i as usize].own_identifier()) - .unwrap(), - &(participants_private_data_round2[i as usize] - .total_secret_share - .0 - * GENERATOR), - "Verification of total secret shares failed!" - ); - } - } - - fn round3( - participants: u16, - identifiers: BTreeSet, - parameters_list: &Vec, - participants_round2_public_messages: Vec, - participants_round2_public_data: Vec>, - participants_round1_public_messages: Vec>, - participants_round1_public_data: Vec, - ) -> Vec<( - SharedPublicKey, - BTreeMap, - )> { - let mut participant_data_round3 = Vec::new(); - let identifiers_vec: Vec = identifiers.clone().iter().copied().collect(); - - for i in 0..participants { - let received_round2_public_messages = participants_round2_public_messages - .iter() - .enumerate() - .filter(|(index, _msg)| { - identifiers_vec[*index] != *parameters_list[i as usize].own_identifier() - }) - .map(|(index, msg)| (identifiers_vec[index], msg.clone())) - .collect::>(); - - let result = round3::run( - ¶meters_list[i as usize], - &received_round2_public_messages, - &participants_round2_public_data[i as usize], - &participants_round1_public_data[i as usize], - &participants_round1_public_messages[i as usize], - ) - .expect("Round 3 should complete without errors!"); - - participant_data_round3.push(result); - } - - participant_data_round3 - } - - fn round2( - participants: u16, - parameters_list: Vec, - participants_round1_private_data: Vec, - participants_round1_public_data: Vec, - participants_round1_public_messages: Vec>, - participants_round1_private_messages: Vec>, - ) -> ( - Vec>, - Vec, - Vec, - ) { - let mut participants_public_data_round2 = Vec::new(); - let mut participants_private_data_round2 = Vec::new(); - let mut participants_public_msgs_round2 = Vec::new(); - - for i in 0..participants { - let result = round2::run( - ¶meters_list[i as usize], - participants_round1_private_data[i as usize].clone(), - &participants_round1_public_data[i as usize].clone(), - &participants_round1_public_messages[i as usize].clone(), - participants_round1_private_messages[i as usize].clone(), - Transcript::new(b"transcript"), - ) - .expect("Round 2 should complete without errors!"); - - participants_public_data_round2.push(result.0); - participants_private_data_round2.push(result.1); - participants_public_msgs_round2.push(result.2); - } - - ( - participants_public_data_round2, - participants_private_data_round2, - participants_public_msgs_round2, - ) - } - fn round1( participants: u16, threshold: u16, @@ -947,6 +800,152 @@ pub mod tests { ) } + fn round2( + participants: u16, + parameters_list: Vec, + participants_round1_private_data: Vec, + participants_round1_public_data: Vec, + participants_round1_public_messages: Vec>, + participants_round1_private_messages: Vec>, + ) -> ( + Vec>, + Vec, + Vec, + ) { + let mut participants_public_data_round2 = Vec::new(); + let mut participants_private_data_round2 = Vec::new(); + let mut participants_public_msgs_round2 = Vec::new(); + + for i in 0..participants { + let result = round2::run( + ¶meters_list[i as usize], + participants_round1_private_data[i as usize].clone(), + &participants_round1_public_data[i as usize].clone(), + &participants_round1_public_messages[i as usize].clone(), + participants_round1_private_messages[i as usize].clone(), + Transcript::new(b"transcript"), + ) + .expect("Round 2 should complete without errors!"); + + participants_public_data_round2.push(result.0); + participants_private_data_round2.push(result.1); + participants_public_msgs_round2.push(result.2); + } + + ( + participants_public_data_round2, + participants_private_data_round2, + participants_public_msgs_round2, + ) + } + + fn round3( + participants: u16, + identifiers: BTreeSet, + parameters_list: &Vec, + participants_round2_public_messages: Vec, + participants_round2_public_data: Vec>, + participants_round1_public_messages: Vec>, + participants_round1_public_data: Vec, + ) -> Vec<( + SharedPublicKey, + BTreeMap, + )> { + let mut participant_data_round3 = Vec::new(); + let identifiers_vec: Vec = identifiers.clone().iter().copied().collect(); + + for i in 0..participants { + let received_round2_public_messages = participants_round2_public_messages + .iter() + .enumerate() + .filter(|(index, _msg)| { + identifiers_vec[*index] != *parameters_list[i as usize].own_identifier() + }) + .map(|(index, msg)| (identifiers_vec[index], msg.clone())) + .collect::>(); + + let result = round3::run( + ¶meters_list[i as usize], + &received_round2_public_messages, + &participants_round2_public_data[i as usize], + &participants_round1_public_data[i as usize], + &participants_round1_public_messages[i as usize], + ) + .expect("Round 3 should complete without errors!"); + + participant_data_round3.push(result); + } + + participant_data_round3 + } + + #[test] + pub fn test_successful_simplpedpop() { + let participants: u16 = 5; + let threshold: u16 = 3; + + let ( + parameters_list, + participants_round1_private_data, + participants_round1_public_data, + mut participants_round1_public_messages, + participants_round1_private_messages, + identifiers, + ) = round1(participants, threshold); + + for i in 0..participants { + participants_round1_public_messages[i as usize] + .remove(¶meters_list[i as usize].own_identifier()); + } + + let ( + participants_public_data_round2, + participants_private_data_round2, + participants_public_msgs_round2, + ) = round2( + participants, + parameters_list.clone(), + participants_round1_private_data.clone(), + participants_round1_public_data.clone(), + participants_round1_public_messages.clone(), + participants_round1_private_messages.clone(), + ); + + let participant_data_round3 = round3( + participants, + identifiers, + ¶meters_list, + participants_public_msgs_round2, + participants_public_data_round2, + participants_round1_public_messages, + participants_round1_public_data, + ); + + let shared_public_keys: Vec = participant_data_round3 + .iter() + .map(|state| state.0) + .collect(); + + assert!( + shared_public_keys.windows(2).all(|w| w[0] == w[1]), + "All participants should have the same shared public key!" + ); + + for i in 0..participants { + assert_eq!( + participant_data_round3[i as usize] + .1 + .get(parameters_list[i as usize].own_identifier()) + .unwrap(), + &(participants_private_data_round2[i as usize] + .total_secret_share + .0 + * GENERATOR), + "Verification of total secret shares failed!" + ); + } + } + #[test] fn test_incorrect_number_of_round1_public_messages_in_round2() { let participants: u16 = 5;