diff --git a/frost-core/src/round1.rs b/frost-core/src/round1.rs index eb4abb3..fd9faa9 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, } } +} - /// Gets the hiding [`Nonce`] - pub fn hiding(&self) -> &Nonce { - &self.hiding +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() + } +} + +#[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 35ad8fb..3080df0 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 8e20c1b..7fa11b7 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 424406b..fbe26a4 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 0000000..bf9dfcf --- /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 8763575..2f41596 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 9e609b8..435196f 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 9db4a5a..1caabab 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 21cc36c..761e56b 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 0000000..7f2419b --- /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 8763575..2f41596 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 c55d0a0..0158a8b 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 bfd4699..41ea280 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 49a9549..a920b6c 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 0000000..0b85706 --- /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 4553949..ee1bfbc 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 41888a6..c12cad7 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 f59d521..0578a64 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 0000000..a78f301 --- /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 8763575..2f41596 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 21e8b82..e8446fe 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 6fdf8ea..0806e55 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 aeb64ed..0a304a4 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 0000000..397cddf --- /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