diff --git a/src/aggregate.rs b/src/aggregate.rs index 14e0fbb..77db915 100644 --- a/src/aggregate.rs +++ b/src/aggregate.rs @@ -20,9 +20,7 @@ pub struct AggPublicKeyAndMusigCoeff { #[derive(Debug, Clone, PartialEq, Eq)] /// Data required to sign for the derived public key, this is generated when [`AggPublicKeyAndMusigCoeff::derive_key`] is called, /// and this needs to be passed to [`KeyPair::partial_sign_derived`] when signing -pub struct DerivationData { - pub(crate) scalar: Scalar -} +pub struct DerivationData(pub(crate) Scalar); impl AggPublicKeyAndMusigCoeff { /// Aggregate public keys. This creates a combined public key that requires both parties in order to sign messages. @@ -82,7 +80,7 @@ impl AggPublicKeyAndMusigCoeff { musig_coefficient: self.musig_coefficient, location: self.location, }, - DerivationData { scalar: delta }, + DerivationData(delta), ) } @@ -112,18 +110,16 @@ impl AggPublicKeyAndMusigCoeff { /// The aggregated nonce of both parties, required for aggregating the signatures. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct AggregatedNonce { - pub(crate) point: EdwardsPoint -} +pub struct AggregatedNonce(pub(crate) EdwardsPoint); impl AggregatedNonce { /// Serialize the aggregated nonce pub fn serialize(&self) -> [u8; 32] { - self.point.compress().0 + self.0.compress().0 } /// Deserialize the aggregated nonce pub fn deserialize(bytes: [u8; 32]) -> Option { - edwards_from_bytes(&bytes).map(|x| Self { point: x }) + edwards_from_bytes(&bytes).map(Self) } } diff --git a/src/keypair.rs b/src/keypair.rs index e5029eb..cf2550f 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -74,8 +74,8 @@ impl KeyPair { // Only one party needs to adjust the signature, so we limit to just the "first" party in the ordered set. if agg_public_key.location == KeySortedLocation::First { - let challenge = Signature::k(&nonce.point, &agg_public_key.agg_public_key, message); - sig.scalar += derived_data.scalar * challenge; + let challenge = Signature::k(&nonce.0, &agg_public_key.agg_public_key, message); + sig.0 += derived_data.0 * challenge; } (sig, nonce) } @@ -93,8 +93,8 @@ impl KeyPair { // is the sum of partial_nonces[i] from both parties // NOTE: the number of nonces is v = 2 here! let sum_R = [ - public_partial_nonce[0].point1 + public_partial_nonce[1].point1, - public_partial_nonce[0].point2 + public_partial_nonce[1].point2, + public_partial_nonce[0].0.0 + public_partial_nonce[1].0.0, + public_partial_nonce[0].0.1 + public_partial_nonce[1].0.1, ]; // Compute b as hash of nonces @@ -111,7 +111,7 @@ impl KeyPair { // Compute effective nonce // The idea is to compute R and r s.t. R = R_0 + b•R_1 and r = r_0 + b•r_1 let effective_R = sum_R[0] + b * sum_R[1]; - let effective_r = private_partial_nonce.scalar1 + b * private_partial_nonce.scalar2; + let effective_r = private_partial_nonce.0.0 + b * private_partial_nonce.0.1; // Compute Fiat-Shamir challenge of signature let sig_challenge = Signature::k(&effective_R, &agg_public_key.agg_public_key, message); @@ -119,8 +119,8 @@ impl KeyPair { let partial_signature = effective_r + (agg_public_key.musig_coefficient * self.private_key * sig_challenge); ( - PartialSignature { scalar: partial_signature }, - AggregatedNonce{ point: effective_R }, + PartialSignature(partial_signature), + AggregatedNonce(effective_R), ) } @@ -147,14 +147,8 @@ impl KeyPair { }); let R: [EdwardsPoint; 2] = r.map(|scalar| &scalar * constants::ED25519_BASEPOINT_TABLE); ( - PrivatePartialNonces { - scalar1: r[0], - scalar2: r[1] - }, - PublicPartialNonces { - point1:R[0], - point2: R[1] - } + PrivatePartialNonces((r[0],r[1])), + PublicPartialNonces((R[0], R[1])) ) } } diff --git a/src/partial_sig.rs b/src/partial_sig.rs index 16ffb5c..edce89a 100644 --- a/src/partial_sig.rs +++ b/src/partial_sig.rs @@ -5,18 +5,17 @@ use curve25519_dalek::scalar::Scalar; /// A partial signature, should be aggregated with another partial signature under the same aggregated public key and message. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct PartialSignature{ - pub(crate) scalar: Scalar -} +pub struct PartialSignature(pub(crate) Scalar); + impl PartialSignature { /// Serialize the partial signature pub fn serialize(&self) -> [u8; 32] { - self.scalar.to_bytes() + self.0.to_bytes() } /// Deserialize the partial signature, returns None if the bytes cannot represent a signature. pub fn deserialize(bytes: [u8; 32]) -> Option { - scalar_from_bytes(&bytes).map(|x| Self { scalar: x }) + scalar_from_bytes(&bytes).map(Self) } } diff --git a/src/private_partial_nonces.rs b/src/private_partial_nonces.rs index 5052bcf..4700c0d 100644 --- a/src/private_partial_nonces.rs +++ b/src/private_partial_nonces.rs @@ -10,10 +10,8 @@ use zeroize::Zeroize; /// Private Partial Nonces, they should be kept until partially signing a message and then they should be discarded. /// /// SECURITY: Reusing them across signatures will cause the private key to leak -pub struct PrivatePartialNonces { - pub(crate) scalar1: Scalar, - pub(crate) scalar2: Scalar -} +pub struct PrivatePartialNonces(pub(crate)(Scalar, Scalar)); + impl PrivatePartialNonces { /// Serialize the private partial nonces for storage. @@ -21,18 +19,17 @@ impl PrivatePartialNonces { /// SECURITY: Do not reuse the nonces across signing instances. reusing the nonces will leak the private key. pub fn serialize(&self) -> [u8; 64] { let mut output = [0u8; 64]; - output[..32].copy_from_slice(&self.scalar1.to_bytes()); - output[32..64].copy_from_slice(&self.scalar2.to_bytes()); + output[..32].copy_from_slice(&self.0.0.to_bytes()); + output[32..64].copy_from_slice(&self.0.1.to_bytes()); output } /// Deserialize the private nonces, /// Will return `None` if they're invalid. pub fn deserialize(bytes: [u8; 64]) -> Option { - Some(Self{ - scalar1: scalar_from_bytes(&bytes[..32])?, - scalar2: scalar_from_bytes(&bytes[32..64])?, - }) + let scalar1 = scalar_from_bytes(&bytes[..32])?; + let scalar2 = scalar_from_bytes(&bytes[32..64])?; + Some(Self((scalar1, scalar2))) } } @@ -40,14 +37,14 @@ impl zeroize::ZeroizeOnDrop for PrivatePartialNonces {} impl zeroize::Zeroize for PrivatePartialNonces { fn zeroize(&mut self) { - self.scalar1.zeroize(); - self.scalar2.zeroize(); + self.0.0.zeroize(); + self.0.1.zeroize(); } } impl Drop for PrivatePartialNonces { fn drop(&mut self) { - self.scalar1.zeroize(); - self.scalar2.zeroize(); + self.0.0.zeroize(); + self.0.1.zeroize(); } } diff --git a/src/public_partial_nonces.rs b/src/public_partial_nonces.rs index 9c224da..038f0ea 100644 --- a/src/public_partial_nonces.rs +++ b/src/public_partial_nonces.rs @@ -10,26 +10,22 @@ use crate::common::edwards_from_bytes; /// Public partial nonces, they should be transmitted to the other party in order to generate the aggregated nonce. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct PublicPartialNonces{ - pub(crate) point1: EdwardsPoint, - pub(crate) point2: EdwardsPoint -} +pub struct PublicPartialNonces(pub(crate) (EdwardsPoint, EdwardsPoint)); impl PublicPartialNonces { /// Serialize the public partial nonces in order to transmit the other party. pub fn serialize(&self) -> [u8; 64] { let mut output = [0u8; 64]; - output[..32].copy_from_slice(&self.point1.compress().0[..]); - output[32..64].copy_from_slice(&self.point2.compress().0[..]); + output[..32].copy_from_slice(&self.0.0.compress().0[..]); + output[32..64].copy_from_slice(&self.0.1.compress().0[..]); output } /// Deserialize the public partial nonces. pub fn deserialize(bytes: [u8; 64]) -> Option { - Some(Self { - point1: edwards_from_bytes(&bytes[..32])?, - point2: edwards_from_bytes(&bytes[32..64])?, - }) + let point1 = edwards_from_bytes(&bytes[..32])?; + let point2 = edwards_from_bytes(&bytes[32..64])?; + Some(Self((point1, point2))) } } diff --git a/src/signature.rs b/src/signature.rs index 81d0051..734cc5e 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -35,8 +35,8 @@ impl Signature { partial_sigs: [PartialSignature; 2], ) -> Self { Self { - R: aggregated_nonce.point, - s: partial_sigs[0].scalar + partial_sigs[1].scalar, + R: aggregated_nonce.0, + s: partial_sigs[0].0 + partial_sigs[1].0, } } /// Verify an ed25519 signature, this is a strict verification and requires both the public key