Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some PartialEqs #202

Merged
merged 2 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 73 additions & 35 deletions schnorr_fun/src/binonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct Nonce<Z = NonZero>(pub [Point<Normal, Public, Z>; 2]);
impl<Z: ZeroChoice> Nonce<Z> {
/// Reads the pair of nonces from 66 bytes (two 33-byte serialized points).
///
/// If either pair of 33 bytes is `[0u8;32]` that point is interpreted as `Zero`.
/// If either pair of 33 bytes is `[0u8;33]` that point is interpreted as `Zero`.
pub fn from_bytes(bytes: [u8; 66]) -> Option<Self> {
let R1 = Point::from_slice(&bytes[..33])?;
let R2 = Point::from_slice(&bytes[33..])?;
Expand All @@ -35,7 +35,7 @@ impl<Z: ZeroChoice> Nonce<Z> {

/// Serializes a public nonce as as 66 bytes (two 33-byte serialized points).
///
/// If either point is `Zero` it will be serialized as `[0u8;32]`.
/// If either point is `Zero` it will be serialized as `[0u8;33]`.
pub fn to_bytes(&self) -> [u8; 66] {
let mut bytes = [0u8; 66];
bytes[..33].copy_from_slice(self.0[0].to_bytes().as_ref());
Expand Down Expand Up @@ -72,7 +72,7 @@ impl Nonce<Zero> {
}

secp256kfun::impl_fromstr_deserialize! {
name => "public nonce pair",
name => "public binonce",
fn from_bytes<Z: ZeroChoice>(bytes: [u8;66]) -> Option<Nonce<Z>> {
Nonce::from_bytes(bytes)
}
Expand All @@ -86,51 +86,64 @@ secp256kfun::impl_display_serialize! {

/// A pair of secret nonces along with the public portion.
///
/// A nonce key pair can be created manually with [`from_secrets`]
/// A nonce key pair can be created manually with [`from_secret`]
///
/// [`from_secrets`]: Self::from_secrets
/// [`from_secret`]: Self::from_secret
#[derive(Debug, Clone, PartialEq)]
pub struct NonceKeyPair {
/// The public nonce
pub public: Nonce<NonZero>,
/// The secret nonce
pub secret: [Scalar; 2],
pub secret: SecretNonce,
}

impl NonceKeyPair {
/// Load nonces from two secret scalars
pub fn from_secrets(secret: [Scalar; 2]) -> Self {
let [ref r1, ref r2] = secret;
let R1 = g!(r1 * G).normalize();
let R2 = g!(r2 * G).normalize();
NonceKeyPair {
public: Nonce([R1, R2]),
secret,
}
}
/// Deserializes a nonce key pair from 64-bytes (two 32-byte serialized scalars).
/// A pair of secret nonces.
///
/// ⚠ An attacker getting this allows them to extract your secret share from a signature share.
#[derive(Debug, Clone, PartialEq)]
pub struct SecretNonce(pub [Scalar; 2]);

impl SecretNonce {
/// Deserializes a secret binonce from 64-bytes (two 32-byte serialized scalars).
pub fn from_bytes(bytes: [u8; 64]) -> Option<Self> {
let r1 = Scalar::from_slice(&bytes[..32])?.non_zero()?;
let r2 = Scalar::from_slice(&bytes[32..])?.non_zero()?;
let R1 = g!(r1 * G).normalize();
let R2 = g!(r2 * G).normalize();
let pub_nonce = Nonce([R1, R2]);
Some(NonceKeyPair {
public: pub_nonce,
secret: [r1, r2],
})
Some(Self([r1, r2]))
}

/// Serializes a nonce key pair to 64-bytes (two 32-bytes serialized scalars).
/// Serializes a secret binonce to 64-bytes (two 32-bytes serialized scalars).
pub fn to_bytes(&self) -> [u8; 64] {
let mut bytes = [0u8; 64];
bytes[..32].copy_from_slice(self.secret[0].to_bytes().as_ref());
bytes[32..].copy_from_slice(self.secret[1].to_bytes().as_ref());
bytes[..32].copy_from_slice(self.0[0].to_bytes().as_ref());
bytes[32..].copy_from_slice(self.0[1].to_bytes().as_ref());
bytes
}

/// Generate a nonce secret binonce from an rng
pub fn random(rng: &mut impl RngCore) -> Self {
Self([Scalar::random(rng), Scalar::random(rng)])
}

/// Convert a secret nonce into a key pair by computing the public nonce
pub fn into_keypair(self) -> NonceKeyPair {
NonceKeyPair::from_secret(self)
}
}

impl NonceKeyPair {
/// Load nonces from two secret scalars
pub fn from_secret(secret: SecretNonce) -> Self {
let [ref r1, ref r2] = secret.0;
let R1 = g!(r1 * G).normalize();
let R2 = g!(r2 * G).normalize();
NonceKeyPair {
public: Nonce([R1, R2]),
secret,
}
}

/// Get the secret portion of the nonce key pair (don't share this!)
pub fn secret(&self) -> &[Scalar; 2] {
pub fn secret(&self) -> &SecretNonce {
&self.secret
}

Expand All @@ -139,21 +152,46 @@ impl NonceKeyPair {
self.public
}

/// Generate a nonce keypair from an rng
/// Generate a random secret nonce and conver to a keypair
pub fn random(rng: &mut impl RngCore) -> Self {
Self::from_secrets([Scalar::random(rng), Scalar::random(rng)])
Self::from_secret(SecretNonce::random(rng))
}
}

impl AsRef<SecretNonce> for NonceKeyPair {
fn as_ref(&self) -> &SecretNonce {
self.secret()
}
}

impl AsRef<SecretNonce> for SecretNonce {
fn as_ref(&self) -> &SecretNonce {
self
}
}

secp256kfun::impl_fromstr_deserialize! {
name => "secret binonce",
fn from_bytes(bytes: [u8;64]) -> Option<SecretNonce> {
SecretNonce::from_bytes(bytes)
}
}

secp256kfun::impl_display_serialize! {
fn to_bytes(value: &SecretNonce) -> [u8;64] {
value.to_bytes()
}
}

secp256kfun::impl_fromstr_deserialize! {
name => "secret nonce pair",
name => "secret binonce",
fn from_bytes(bytes: [u8;64]) -> Option<NonceKeyPair> {
NonceKeyPair::from_bytes(bytes)
Some(NonceKeyPair::from_secret(SecretNonce::from_bytes(bytes)?))
}
}

secp256kfun::impl_display_serialize! {
fn to_bytes(nkp: &NonceKeyPair) -> [u8;64] {
nkp.to_bytes()
fn to_bytes(value: &NonceKeyPair) -> [u8;64] {
value.secret.to_bytes()
}
}
2 changes: 1 addition & 1 deletion schnorr_fun/src/frost/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ pub type PartyIndex = Scalar<Public, NonZero>;
///
/// - `H`: hash type for challenges, and binding coefficient.
/// - `NG`: nonce generator for FROST nonces (only used if you explicitly call nonce generation functions).
#[derive(Clone)]
#[derive(Clone, Debug, PartialEq)]
pub struct Frost<H, NG> {
/// The instance of the Schnorr signature scheme.
pub schnorr: Schnorr<H, NG>,
Expand Down
12 changes: 8 additions & 4 deletions schnorr_fun/src/frost/session.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use crate::{binonce, frost::PartyIndex, Signature};
use crate::{
binonce::{self, SecretNonce},
frost::PartyIndex,
Signature,
};
use alloc::collections::{BTreeMap, BTreeSet};
use secp256kfun::{poly, prelude::*};

use super::{NonceKeyPair, PairedSecretShare, SharedKey, SignatureShare, VerificationShare};
use super::{PairedSecretShare, SharedKey, SignatureShare, VerificationShare};
/// A FROST signing session used to *verify* signatures.
///
/// Created using [`coordinator_sign_session`].
Expand Down Expand Up @@ -214,7 +218,7 @@ impl PartySignSession {
pub fn sign(
&self,
secret_share: &PairedSecretShare<EvenY>,
secret_nonce: NonceKeyPair,
secret_nonce: impl AsRef<SecretNonce>,
) -> SignatureShare {
if self.public_key != secret_share.public_key() {
panic!("the share's shared key is not the same as the shared key of the session");
Expand All @@ -224,7 +228,7 @@ impl PartySignSession {
}
let secret_share = secret_share.secret_share();
let lambda = poly::eval_basis_poly_at_0(secret_share.index, self.parties.iter().cloned());
let [mut r1, mut r2] = secret_nonce.secret;
let [mut r1, mut r2] = secret_nonce.as_ref().0;
r1.conditional_negate(self.binonce_needs_negation);
r2.conditional_negate(self.binonce_needs_negation);

Expand Down
10 changes: 7 additions & 3 deletions schnorr_fun/src/musig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@
//!
//! [the excellent paper]: https://eprint.iacr.org/2020/1261.pdf
//! [secp256k1-zkp]: https://github.com/ElementsProject/secp256k1-zkp/pull/131
use crate::{adaptor::EncryptedSignature, binonce, Message, Schnorr, Signature};
use crate::{
adaptor::EncryptedSignature,
binonce::{self, SecretNonce},
Message, Schnorr, Signature,
};
use alloc::vec::Vec;
use secp256kfun::{
hash::{Hash32, HashAdd, Tag},
Expand Down Expand Up @@ -556,7 +560,7 @@ impl<H: Hash32, NG> MuSig<H, NG> {
session: &SignSession<T>,
my_index: usize,
keypair: &KeyPair,
local_secret_nonce: binonce::NonceKeyPair,
local_secret_nonce: impl AsRef<SecretNonce>,
) -> Scalar<Public, Zero> {
assert_eq!(
keypair.public_key(),
Expand All @@ -569,7 +573,7 @@ impl<H: Hash32, NG> MuSig<H, NG> {
let mut a = agg_key.coefs[my_index];

a.conditional_negate(agg_key.needs_negation);
let [mut r1, mut r2] = local_secret_nonce.secret;
let [mut r1, mut r2] = local_secret_nonce.as_ref().0;
r1.conditional_negate(session.nonce_needs_negation);
r2.conditional_negate(session.nonce_needs_negation);
s!(c * a * x_i + r1 + b * r2).public()
Expand Down
2 changes: 1 addition & 1 deletion schnorr_fun/src/schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
/// [_Fiat-Shamir_]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic
/// [`NonceGen<H>`]: crate::fun::hash::NonceGen
/// [BIP-340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
#[derive(Clone)]
#[derive(Clone, Debug, PartialEq)]
pub struct Schnorr<CH, NG = NoNonces> {
/// The [`NonceGen`] used to generate nonces.
///
Expand Down
5 changes: 2 additions & 3 deletions schnorr_fun/tests/musig_sign_verify.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![cfg(feature = "serde")]
use schnorr_fun::{
binonce,
binonce::NonceKeyPair,
fun::{marker::*, serde, Point, Scalar},
musig, Message,
};
Expand All @@ -26,15 +25,15 @@ impl<T> Maybe<T> {

#[derive(Clone, Debug)]
struct SecNonce {
nonce: NonceKeyPair,
nonce: binonce::SecretNonce,
pk: Point,
}

impl SecNonce {
pub fn from_bytes(bytes: [u8; 97]) -> Option<Self> {
let mut nonce = [0u8; 64];
nonce.copy_from_slice(&bytes[..64]);
let nonce = binonce::NonceKeyPair::from_bytes(nonce)?;
let nonce = binonce::SecretNonce::from_bytes(nonce)?;
Some(SecNonce {
nonce,
pk: Point::from_slice(&bytes[64..])?,
Expand Down
7 changes: 3 additions & 4 deletions schnorr_fun/tests/musig_tweak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
use std::{rc::Rc, sync::Arc};

use schnorr_fun::{
binonce,
binonce::NonceKeyPair,
binonce::{self, NonceKeyPair},
fun::{marker::*, serde, Point, Scalar},
musig, Message,
};
Expand All @@ -28,15 +27,15 @@ impl<T> Maybe<T> {
}

struct SecNonce {
nonce: NonceKeyPair,
nonce: binonce::SecretNonce,
_pk: Point,
}

impl SecNonce {
pub fn from_bytes(bytes: [u8; 97]) -> Option<Self> {
let mut nonce = [0u8; 64];
nonce.copy_from_slice(&bytes[..64]);
let nonce = binonce::NonceKeyPair::from_bytes(nonce)?;
let nonce = binonce::SecretNonce::from_bytes(nonce)?;
Some(SecNonce {
nonce,
_pk: Point::from_slice(&bytes[64..])?,
Expand Down
6 changes: 3 additions & 3 deletions secp256kfun/src/nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<R: RngCore> NonceRng for std::sync::Mutex<R> {
/// [`ThreadRng`]: https://docs.rs/rand/latest/rand/rngs/struct.ThreadRng.html
/// [`OsRng`]: rand_core::OsRng
/// [`GlobalRng`]: crate::nonce::GlobalRng
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Synthetic<H, R> {
rng: R,
nonce_hash: H,
Expand Down Expand Up @@ -125,7 +125,7 @@ impl<H: Default, R: NonceRng> Synthetic<H, R> {
/// ```
///
/// [`ThreadRng`]: https://docs.rs/rand/latest/rand/rngs/struct.ThreadRng.html
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct GlobalRng<R> {
// Using fn(R) ensures that it is sync even if R is not sync
inner: PhantomData<fn(R)>,
Expand All @@ -145,7 +145,7 @@ pub struct GlobalRng<R> {
/// let nonce_gen = Deterministic::<Sha256>::default().tag(b"BIP0340");
/// ```
/// [`Synthetic`]: crate::nonce::Synthetic
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Deterministic<H> {
nonce_hash: H,
}
Expand Down
Loading