From 9921b1218e3286c183b269deb306f6e8fc16bd79 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Tue, 16 Jan 2024 17:48:17 -0300 Subject: [PATCH] support serializing SigningNonces (#595) --- frost-core/src/round1.rs | 82 +++++++++++++++---- frost-ed25519/tests/helpers/samples.rs | 14 +++- frost-ed25519/tests/recreation_tests.rs | 12 ++- frost-ed25519/tests/serialization_tests.rs | 10 ++- ...signing_nonces_postcard_serialization.snap | 5 ++ frost-ed448/tests/helpers/mod.rs | 4 + frost-ed448/tests/helpers/samples.rs | 14 +++- frost-ed448/tests/recreation_tests.rs | 12 ++- frost-ed448/tests/serialization_tests.rs | 10 ++- ...signing_nonces_postcard_serialization.snap | 5 ++ frost-p256/tests/helpers/mod.rs | 4 + frost-p256/tests/helpers/samples.rs | 14 +++- frost-p256/tests/recreation_tests.rs | 12 ++- frost-p256/tests/serialization_tests.rs | 10 ++- ...signing_nonces_postcard_serialization.snap | 5 ++ frost-ristretto255/tests/helpers/samples.rs | 14 +++- frost-ristretto255/tests/recreation_tests.rs | 12 ++- .../tests/serialization_tests.rs | 10 ++- ...signing_nonces_postcard_serialization.snap | 5 ++ frost-secp256k1/tests/helpers/mod.rs | 4 + frost-secp256k1/tests/helpers/samples.rs | 14 +++- frost-secp256k1/tests/recreation_tests.rs | 12 ++- frost-secp256k1/tests/serialization_tests.rs | 10 ++- ...signing_nonces_postcard_serialization.snap | 5 ++ 24 files changed, 265 insertions(+), 34 deletions(-) create mode 100644 frost-ed25519/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap create mode 100644 frost-ed448/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap create mode 100644 frost-p256/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap create mode 100644 frost-ristretto255/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap create mode 100644 frost-secp256k1/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap diff --git a/frost-core/src/round1.rs b/frost-core/src/round1.rs index eb4abb3a..fd9faa96 100644 --- a/frost-core/src/round1.rs +++ b/frost-core/src/round1.rs @@ -19,12 +19,16 @@ use crate::{ }; #[cfg(feature = "serde")] -use crate::serialization::ElementSerialization; +use crate::serialization::{ElementSerialization, ScalarSerialization}; use super::{keys::SigningShare, Identifier}; /// A scalar that is a signing nonce. -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))] +#[cfg_attr(feature = "serde", serde(try_from = "ScalarSerialization"))] +#[cfg_attr(feature = "serde", serde(into = "ScalarSerialization"))] pub struct Nonce(pub(super) Scalar); impl Nonce @@ -107,6 +111,28 @@ where } } +#[cfg(feature = "serde")] +impl TryFrom> for Nonce +where + C: Ciphersuite, +{ + type Error = Error; + + fn try_from(value: ScalarSerialization) -> Result { + Self::deserialize(value.0) + } +} + +#[cfg(feature = "serde")] +impl From> for ScalarSerialization +where + C: Ciphersuite, +{ + fn from(value: Nonce) -> Self { + Self(value.serialize()) + } +} + /// A group element that is a commitment to a signing nonce share. #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -206,8 +232,14 @@ where /// Note that [`SigningNonces`] must be used *only once* for a signing /// operation; re-using nonces will result in leakage of a signer's long-lived /// signing key. -#[derive(Clone, Zeroize)] +#[derive(Clone, Zeroize, PartialEq, Eq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))] +#[cfg_attr(feature = "serde", serde(deny_unknown_fields))] pub struct SigningNonces { + /// Serialization header + #[getter(skip)] + pub(crate) header: Header, /// The hiding [`Nonce`]. pub(crate) hiding: Nonce, /// The binding [`Nonce`]. @@ -238,30 +270,52 @@ where Self::from_nonces(hiding, binding) } - /// Generates a new [`SigningNonces`] from a pair of [`Nonce`]. This is - /// useful internally since [`SigningNonces`] precompute the respective - /// commitments. - #[cfg_attr(test, visibility::make(pub))] - pub(crate) fn from_nonces(hiding: Nonce, binding: Nonce) -> Self { + /// Generates a new [`SigningNonces`] from a pair of [`Nonce`]. + /// + /// # Security + /// + /// SigningNonces MUST NOT be repeated in different FROST signings. + /// Thus, if you're using this method (because e.g. you're writing it + /// to disk between rounds), be careful so that does not happen. + pub fn from_nonces(hiding: Nonce, binding: Nonce) -> Self { let hiding_commitment = (&hiding).into(); let binding_commitment = (&binding).into(); let commitments = SigningCommitments::new(hiding_commitment, binding_commitment); Self { + header: Header::default(), hiding, binding, commitments, } } +} + +impl Debug for SigningNonces +where + C: Ciphersuite, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SigningNonces") + .field("hiding", &"") + .field("binding", &"") + .finish() + } +} - /// Gets the hiding [`Nonce`] - pub fn hiding(&self) -> &Nonce { - &self.hiding +#[cfg(feature = "serialization")] +impl SigningNonces +where + C: Ciphersuite, +{ + /// Serialize the struct into a Vec. + pub fn serialize(&self) -> Result, Error> { + Serialize::serialize(&self) } - /// Gets the binding [`Nonce`] - pub fn binding(&self) -> &Nonce { - &self.binding + /// Deserialize the struct from a slice of bytes. + pub fn deserialize(bytes: &[u8]) -> Result> { + Deserialize::deserialize(bytes) } } diff --git a/frost-ed25519/tests/helpers/samples.rs b/frost-ed25519/tests/helpers/samples.rs index 35ad8fbf..3080df01 100644 --- a/frost-ed25519/tests/helpers/samples.rs +++ b/frost-ed25519/tests/helpers/samples.rs @@ -2,14 +2,14 @@ use std::collections::BTreeMap; -use frost_core::{Ciphersuite, Element, Group, Scalar}; +use frost_core::{round1::Nonce, Ciphersuite, Element, Group, Scalar}; use frost_ed25519::{ keys::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare, }, - round1::{NonceCommitment, SigningCommitments}, + round1::{NonceCommitment, SigningCommitments, SigningNonces}, round2::SignatureShare, Field, Signature, SigningPackage, VerifyingKey, }; @@ -32,6 +32,16 @@ fn scalar1() -> Scalar { .expect("nonzero elements have inverses") } +/// Generate a sample SigningCommitments. +pub fn signing_nonces() -> SigningNonces { + let serialized_scalar1 = <::Group as Group>::Field::serialize(&scalar1()); + let serialized_scalar2 = <::Group as Group>::Field::serialize(&scalar1()); + let hiding_nonce = Nonce::deserialize(serialized_scalar1).unwrap(); + let binding_nonce = Nonce::deserialize(serialized_scalar2).unwrap(); + + SigningNonces::from_nonces(hiding_nonce, binding_nonce) +} + /// Generate a sample SigningCommitments. pub fn signing_commitments() -> SigningCommitments { let serialized_element1 = ::Group::serialize(&element1()); diff --git a/frost-ed25519/tests/recreation_tests.rs b/frost-ed25519/tests/recreation_tests.rs index 8e20c1bb..7fa11b79 100644 --- a/frost-ed25519/tests/recreation_tests.rs +++ b/frost-ed25519/tests/recreation_tests.rs @@ -6,7 +6,7 @@ use frost_ed25519::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,16 @@ mod helpers; use helpers::samples; +/// Check if SigningNonces can be recreated. +#[test] +fn check_signing_nonces_recreation() { + let nonces = samples::signing_nonces(); + let hiding = nonces.hiding(); + let binding = nonces.binding(); + let new_nonces = SigningNonces::from_nonces(*hiding, *binding); + assert!(nonces == new_nonces); +} + /// Check if SigningCommitments can be recreated. #[test] fn check_signing_commitments_recreation() { diff --git a/frost-ed25519/tests/serialization_tests.rs b/frost-ed25519/tests/serialization_tests.rs index 424406b5..fbe26a41 100644 --- a/frost-ed25519/tests/serialization_tests.rs +++ b/frost-ed25519/tests/serialization_tests.rs @@ -7,7 +7,7 @@ use frost_ed25519::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,14 @@ use frost_ed25519::{ use helpers::samples; use insta::assert_snapshot; +#[test] +fn check_signing_nonces_postcard_serialization() { + let nonces = samples::signing_nonces(); + let bytes: Vec<_> = nonces.serialize().unwrap(); + assert_snapshot!(hex::encode(&bytes)); + assert_eq!(nonces, SigningNonces::deserialize(&bytes).unwrap()); +} + #[test] fn check_signing_commitments_postcard_serialization() { let commitments = samples::signing_commitments(); diff --git a/frost-ed25519/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap b/frost-ed25519/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap new file mode 100644 index 00000000..bf9dfcf9 --- /dev/null +++ b/frost-ed25519/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap @@ -0,0 +1,5 @@ +--- +source: frost-ed25519/tests/serialization_tests.rs +expression: "hex::encode(&bytes)" +--- +00b169f0da498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a00b169f0daa57766449a934461866051263c8785663857640e5a32d702f21e085bc31a0283a57766449a934461866051263c8785663857640e5a32d702f21e085bc31a0283 diff --git a/frost-ed448/tests/helpers/mod.rs b/frost-ed448/tests/helpers/mod.rs index 87635756..2f415966 100644 --- a/frost-ed448/tests/helpers/mod.rs +++ b/frost-ed448/tests/helpers/mod.rs @@ -1 +1,5 @@ +// Required since each integration test is compiled as a separated crate, +// and each one uses only part of the module. +#![allow(dead_code)] + pub mod samples; diff --git a/frost-ed448/tests/helpers/samples.rs b/frost-ed448/tests/helpers/samples.rs index 9e609b87..435196f4 100644 --- a/frost-ed448/tests/helpers/samples.rs +++ b/frost-ed448/tests/helpers/samples.rs @@ -2,14 +2,14 @@ use std::collections::BTreeMap; -use frost_core::{Ciphersuite, Element, Group, Scalar}; +use frost_core::{round1::Nonce, Ciphersuite, Element, Group, Scalar}; use frost_ed448::{ keys::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare, }, - round1::{NonceCommitment, SigningCommitments}, + round1::{NonceCommitment, SigningCommitments, SigningNonces}, round2::SignatureShare, Field, Signature, SigningPackage, VerifyingKey, }; @@ -32,6 +32,16 @@ fn scalar1() -> Scalar { .expect("nonzero elements have inverses") } +/// Generate a sample SigningCommitments. +pub fn signing_nonces() -> SigningNonces { + let serialized_scalar1 = <::Group as Group>::Field::serialize(&scalar1()); + let serialized_scalar2 = <::Group as Group>::Field::serialize(&scalar1()); + let hiding_nonce = Nonce::deserialize(serialized_scalar1).unwrap(); + let binding_nonce = Nonce::deserialize(serialized_scalar2).unwrap(); + + SigningNonces::from_nonces(hiding_nonce, binding_nonce) +} + /// Generate a sample SigningCommitments. pub fn signing_commitments() -> SigningCommitments { let serialized_element1 = ::Group::serialize(&element1()); diff --git a/frost-ed448/tests/recreation_tests.rs b/frost-ed448/tests/recreation_tests.rs index 9db4a5a4..1caababa 100644 --- a/frost-ed448/tests/recreation_tests.rs +++ b/frost-ed448/tests/recreation_tests.rs @@ -6,7 +6,7 @@ use frost_ed448::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,16 @@ mod helpers; use helpers::samples; +/// Check if SigningNonces can be recreated. +#[test] +fn check_signing_nonces_recreation() { + let nonces = samples::signing_nonces(); + let hiding = nonces.hiding(); + let binding = nonces.binding(); + let new_nonces = SigningNonces::from_nonces(*hiding, *binding); + assert!(nonces == new_nonces); +} + /// Check if SigningCommitments can be recreated. #[test] fn check_signing_commitments_recreation() { diff --git a/frost-ed448/tests/serialization_tests.rs b/frost-ed448/tests/serialization_tests.rs index 21cc36ce..761e56b7 100644 --- a/frost-ed448/tests/serialization_tests.rs +++ b/frost-ed448/tests/serialization_tests.rs @@ -7,7 +7,7 @@ use frost_ed448::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,14 @@ use frost_ed448::{ use helpers::samples; use insta::assert_snapshot; +#[test] +fn check_signing_nonces_postcard_serialization() { + let nonces = samples::signing_nonces(); + let bytes: Vec<_> = nonces.serialize().unwrap(); + assert_snapshot!(hex::encode(&bytes)); + assert_eq!(nonces, SigningNonces::deserialize(&bytes).unwrap()); +} + #[test] fn check_signing_commitments_postcard_serialization() { let commitments = samples::signing_commitments(); diff --git a/frost-ed448/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap b/frost-ed448/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap new file mode 100644 index 00000000..7f2419b1 --- /dev/null +++ b/frost-ed448/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap @@ -0,0 +1,5 @@ +--- +source: frost-ed448/tests/serialization_tests.rs +expression: "hex::encode(&bytes)" +--- +005a064cfd4d83e51cb78150c2380ad9b3a18148166024e4c9db3cdf82466d3153aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2a004d83e51cb78150c2380ad9b3a18148166024e4c9db3cdf82466d3153aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2a00005a064cfd0e04abea2bff79d5b6223b84b0a9323e0ef8572c7d0afd1fd5e4535ae6823e352ee239ad5f5981eb0c23292fb88bc55fe969957103c0c002800e04abea2bff79d5b6223b84b0a9323e0ef8572c7d0afd1fd5e4535ae6823e352ee239ad5f5981eb0c23292fb88bc55fe969957103c0c00280 diff --git a/frost-p256/tests/helpers/mod.rs b/frost-p256/tests/helpers/mod.rs index 87635756..2f415966 100644 --- a/frost-p256/tests/helpers/mod.rs +++ b/frost-p256/tests/helpers/mod.rs @@ -1 +1,5 @@ +// Required since each integration test is compiled as a separated crate, +// and each one uses only part of the module. +#![allow(dead_code)] + pub mod samples; diff --git a/frost-p256/tests/helpers/samples.rs b/frost-p256/tests/helpers/samples.rs index c55d0a0e..0158a8bc 100644 --- a/frost-p256/tests/helpers/samples.rs +++ b/frost-p256/tests/helpers/samples.rs @@ -2,14 +2,14 @@ use std::collections::BTreeMap; -use frost_core::{Ciphersuite, Element, Group, Scalar}; +use frost_core::{round1::Nonce, Ciphersuite, Element, Group, Scalar}; use frost_p256::{ keys::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare, }, - round1::{NonceCommitment, SigningCommitments}, + round1::{NonceCommitment, SigningCommitments, SigningNonces}, round2::SignatureShare, Field, Signature, SigningPackage, VerifyingKey, }; @@ -32,6 +32,16 @@ fn scalar1() -> Scalar { .expect("nonzero elements have inverses") } +/// Generate a sample SigningCommitments. +pub fn signing_nonces() -> SigningNonces { + let serialized_scalar1 = <::Group as Group>::Field::serialize(&scalar1()); + let serialized_scalar2 = <::Group as Group>::Field::serialize(&scalar1()); + let hiding_nonce = Nonce::deserialize(serialized_scalar1).unwrap(); + let binding_nonce = Nonce::deserialize(serialized_scalar2).unwrap(); + + SigningNonces::from_nonces(hiding_nonce, binding_nonce) +} + /// Generate a sample SigningCommitments. pub fn signing_commitments() -> SigningCommitments { let serialized_element1 = ::Group::serialize(&element1()); diff --git a/frost-p256/tests/recreation_tests.rs b/frost-p256/tests/recreation_tests.rs index bfd46994..41ea2802 100644 --- a/frost-p256/tests/recreation_tests.rs +++ b/frost-p256/tests/recreation_tests.rs @@ -6,7 +6,7 @@ use frost_p256::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,16 @@ mod helpers; use helpers::samples; +/// Check if SigningNonces can be recreated. +#[test] +fn check_signing_nonces_recreation() { + let nonces = samples::signing_nonces(); + let hiding = nonces.hiding(); + let binding = nonces.binding(); + let new_nonces = SigningNonces::from_nonces(*hiding, *binding); + assert!(nonces == new_nonces); +} + /// Check if SigningCommitments can be recreated. #[test] fn check_signing_commitments_recreation() { diff --git a/frost-p256/tests/serialization_tests.rs b/frost-p256/tests/serialization_tests.rs index 49a95491..a920b6c2 100644 --- a/frost-p256/tests/serialization_tests.rs +++ b/frost-p256/tests/serialization_tests.rs @@ -7,7 +7,7 @@ use frost_p256::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,14 @@ use frost_p256::{ use helpers::samples; use insta::assert_snapshot; +#[test] +fn check_signing_nonces_postcard_serialization() { + let nonces = samples::signing_nonces(); + let bytes: Vec<_> = nonces.serialize().unwrap(); + assert_snapshot!(hex::encode(&bytes)); + assert_eq!(nonces, SigningNonces::deserialize(&bytes).unwrap()); +} + #[test] fn check_signing_commitments_postcard_serialization() { let commitments = samples::signing_commitments(); diff --git a/frost-p256/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap b/frost-p256/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap new file mode 100644 index 00000000..0b857067 --- /dev/null +++ b/frost-p256/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap @@ -0,0 +1,5 @@ +--- +source: frost-p256/tests/serialization_tests.rs +expression: "hex::encode(&bytes)" +--- +00a132f0c9aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100a132f0c902517d3f033d9b7d1994d200de245f8952bf5ac043d4014ca9af9ec20fee5119c802517d3f033d9b7d1994d200de245f8952bf5ac043d4014ca9af9ec20fee5119c8 diff --git a/frost-ristretto255/tests/helpers/samples.rs b/frost-ristretto255/tests/helpers/samples.rs index 4553949c..ee1bfbc4 100644 --- a/frost-ristretto255/tests/helpers/samples.rs +++ b/frost-ristretto255/tests/helpers/samples.rs @@ -2,14 +2,14 @@ use std::collections::BTreeMap; -use frost_core::{Ciphersuite, Element, Group, Scalar}; +use frost_core::{round1::Nonce, Ciphersuite, Element, Group, Scalar}; use frost_ristretto255::{ keys::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare, }, - round1::{NonceCommitment, SigningCommitments}, + round1::{NonceCommitment, SigningCommitments, SigningNonces}, round2::SignatureShare, Field, Signature, SigningPackage, VerifyingKey, }; @@ -32,6 +32,16 @@ fn scalar1() -> Scalar { .expect("nonzero elements have inverses") } +/// Generate a sample SigningCommitments. +pub fn signing_nonces() -> SigningNonces { + let serialized_scalar1 = <::Group as Group>::Field::serialize(&scalar1()); + let serialized_scalar2 = <::Group as Group>::Field::serialize(&scalar1()); + let hiding_nonce = Nonce::deserialize(serialized_scalar1).unwrap(); + let binding_nonce = Nonce::deserialize(serialized_scalar2).unwrap(); + + SigningNonces::from_nonces(hiding_nonce, binding_nonce) +} + /// Generate a sample SigningCommitments. pub fn signing_commitments() -> SigningCommitments { let serialized_element1 = ::Group::serialize(&element1()); diff --git a/frost-ristretto255/tests/recreation_tests.rs b/frost-ristretto255/tests/recreation_tests.rs index 41888a65..c12cad7e 100644 --- a/frost-ristretto255/tests/recreation_tests.rs +++ b/frost-ristretto255/tests/recreation_tests.rs @@ -6,7 +6,7 @@ use frost_ristretto255::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,16 @@ mod helpers; use helpers::samples; +/// Check if SigningNonces can be recreated. +#[test] +fn check_signing_nonces_recreation() { + let nonces = samples::signing_nonces(); + let hiding = nonces.hiding(); + let binding = nonces.binding(); + let new_nonces = SigningNonces::from_nonces(*hiding, *binding); + assert!(nonces == new_nonces); +} + /// Check if SigningCommitments can be recreated. #[test] fn check_signing_commitments_recreation() { diff --git a/frost-ristretto255/tests/serialization_tests.rs b/frost-ristretto255/tests/serialization_tests.rs index f59d5213..0578a64a 100644 --- a/frost-ristretto255/tests/serialization_tests.rs +++ b/frost-ristretto255/tests/serialization_tests.rs @@ -7,7 +7,7 @@ use frost_ristretto255::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,14 @@ use frost_ristretto255::{ use helpers::samples; use insta::assert_snapshot; +#[test] +fn check_signing_nonces_postcard_serialization() { + let nonces = samples::signing_nonces(); + let bytes: Vec<_> = nonces.serialize().unwrap(); + assert_snapshot!(hex::encode(&bytes)); + assert_eq!(nonces, SigningNonces::deserialize(&bytes).unwrap()); +} + #[test] fn check_signing_commitments_postcard_serialization() { let commitments = samples::signing_commitments(); diff --git a/frost-ristretto255/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap b/frost-ristretto255/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap new file mode 100644 index 00000000..a78f3015 --- /dev/null +++ b/frost-ristretto255/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap @@ -0,0 +1,5 @@ +--- +source: frost-ristretto255/tests/serialization_tests.rs +expression: "hex::encode(&bytes)" +--- +00d76ecff5498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a00d76ecff5e8f69f2ee87ef7c1e54ecf0c08883e39406c0d3fc01eda94116452870e0e6e3be8f69f2ee87ef7c1e54ecf0c08883e39406c0d3fc01eda94116452870e0e6e3b diff --git a/frost-secp256k1/tests/helpers/mod.rs b/frost-secp256k1/tests/helpers/mod.rs index 87635756..2f415966 100644 --- a/frost-secp256k1/tests/helpers/mod.rs +++ b/frost-secp256k1/tests/helpers/mod.rs @@ -1 +1,5 @@ +// Required since each integration test is compiled as a separated crate, +// and each one uses only part of the module. +#![allow(dead_code)] + pub mod samples; diff --git a/frost-secp256k1/tests/helpers/samples.rs b/frost-secp256k1/tests/helpers/samples.rs index 21e8b825..e8446fe7 100644 --- a/frost-secp256k1/tests/helpers/samples.rs +++ b/frost-secp256k1/tests/helpers/samples.rs @@ -2,14 +2,14 @@ use std::collections::BTreeMap; -use frost_core::{Ciphersuite, Element, Group, Scalar}; +use frost_core::{round1::Nonce, Ciphersuite, Element, Group, Scalar}; use frost_secp256k1::{ keys::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare, }, - round1::{NonceCommitment, SigningCommitments}, + round1::{NonceCommitment, SigningCommitments, SigningNonces}, round2::SignatureShare, Field, Signature, SigningPackage, VerifyingKey, }; @@ -32,6 +32,16 @@ fn scalar1() -> Scalar { .expect("nonzero elements have inverses") } +/// Generate a sample SigningCommitments. +pub fn signing_nonces() -> SigningNonces { + let serialized_scalar1 = <::Group as Group>::Field::serialize(&scalar1()); + let serialized_scalar2 = <::Group as Group>::Field::serialize(&scalar1()); + let hiding_nonce = Nonce::deserialize(serialized_scalar1).unwrap(); + let binding_nonce = Nonce::deserialize(serialized_scalar2).unwrap(); + + SigningNonces::from_nonces(hiding_nonce, binding_nonce) +} + /// Generate a sample SigningCommitments. pub fn signing_commitments() -> SigningCommitments { let serialized_element1 = ::Group::serialize(&element1()); diff --git a/frost-secp256k1/tests/recreation_tests.rs b/frost-secp256k1/tests/recreation_tests.rs index 6fdf8ea9..0806e55f 100644 --- a/frost-secp256k1/tests/recreation_tests.rs +++ b/frost-secp256k1/tests/recreation_tests.rs @@ -6,7 +6,7 @@ use frost_secp256k1::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,16 @@ mod helpers; use helpers::samples; +/// Check if SigningNonces can be recreated. +#[test] +fn check_signing_nonces_recreation() { + let nonces = samples::signing_nonces(); + let hiding = nonces.hiding(); + let binding = nonces.binding(); + let new_nonces = SigningNonces::from_nonces(*hiding, *binding); + assert!(nonces == new_nonces); +} + /// Check if SigningCommitments can be recreated. #[test] fn check_signing_commitments_recreation() { diff --git a/frost-secp256k1/tests/serialization_tests.rs b/frost-secp256k1/tests/serialization_tests.rs index aeb64edf..0a304a49 100644 --- a/frost-secp256k1/tests/serialization_tests.rs +++ b/frost-secp256k1/tests/serialization_tests.rs @@ -7,7 +7,7 @@ use frost_secp256k1::{ dkg::{round1, round2}, KeyPackage, PublicKeyPackage, SecretShare, }, - round1::SigningCommitments, + round1::{SigningCommitments, SigningNonces}, round2::SignatureShare, SigningPackage, }; @@ -15,6 +15,14 @@ use frost_secp256k1::{ use helpers::samples; use insta::assert_snapshot; +#[test] +fn check_signing_nonces_postcard_serialization() { + let nonces = samples::signing_nonces(); + let bytes: Vec<_> = nonces.serialize().unwrap(); + assert_snapshot!(hex::encode(&bytes)); + assert_eq!(nonces, SigningNonces::deserialize(&bytes).unwrap()); +} + #[test] fn check_signing_commitments_postcard_serialization() { let commitments = samples::signing_commitments(); diff --git a/frost-secp256k1/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap b/frost-secp256k1/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap new file mode 100644 index 00000000..397cddfc --- /dev/null +++ b/frost-secp256k1/tests/snapshots/serialization_tests__check_signing_nonces_postcard_serialization.snap @@ -0,0 +1,5 @@ +--- +source: frost-secp256k1/tests/serialization_tests.rs +expression: "hex::encode(&bytes)" +--- +00eed6b1b1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b8100eed6b1b1034c7ff4f2ba8603998339c8e42675ceac23ef2e9623fdb260b24b1c944a2ea1a9034c7ff4f2ba8603998339c8e42675ceac23ef2e9623fdb260b24b1c944a2ea1a9