use secp256kfun::{G, Point, Scalar, g, hash::HashInto, marker::*, rand_core::RngCore};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Nonce<Z = NonZero>(pub [Point<Normal, Public, Z>; 2]);
impl<Z: ZeroChoice> Nonce<Z> {
pub fn from_bytes(bytes: [u8; 66]) -> Option<Self> {
let R1 = Point::from_slice(&bytes[..33])?;
let R2 = Point::from_slice(&bytes[33..])?;
Some(Nonce([R1, R2]))
}
}
impl<Z: ZeroChoice> Nonce<Z> {
pub fn conditional_negate(&mut self, needs_negation: bool) {
self.0[0] = self.0[0].conditional_negate(needs_negation);
self.0[1] = self.0[1].conditional_negate(needs_negation);
}
pub fn to_bytes(&self) -> [u8; 66] {
let mut bytes = [0u8; 66];
bytes[..33].copy_from_slice(self.0[0].to_bytes().as_ref());
bytes[33..].copy_from_slice(self.0[1].to_bytes().as_ref());
bytes
}
pub fn bind(&self, binding_coeff: Scalar<Public>) -> (Point<EvenY>, bool) {
g!(self.0[0] + binding_coeff * self.0[1])
.normalize()
.non_zero()
.unwrap_or(Point::generator())
.into_point_with_even_y()
}
}
impl<Z> HashInto for Nonce<Z> {
fn hash_into(self, hash: &mut impl secp256kfun::digest::Update) {
self.0.hash_into(hash)
}
}
impl Nonce<Zero> {
pub fn aggregate(nonces: impl IntoIterator<Item = Nonce>) -> Self {
Self::aggregate_and_add(nonces, Point::<Normal, Public, _>::zero())
}
pub fn aggregate_and_add(
nonces: impl IntoIterator<Item = Nonce>,
addition: Point<impl PointType, impl Secrecy, impl ZeroChoice>,
) -> Self {
let mut agg = nonces.into_iter().fold([Point::zero(); 2], |acc, nonce| {
[g!(acc[0] + nonce.0[0]), g!(acc[1] + nonce.0[1])]
});
agg[0] += addition;
Self([agg[0].normalize(), agg[1].normalize()])
}
}
secp256kfun::impl_fromstr_deserialize! {
name => "public binonce",
fn from_bytes<Z: ZeroChoice>(bytes: [u8;66]) -> Option<Nonce<Z>> {
Nonce::from_bytes(bytes)
}
}
secp256kfun::impl_display_serialize! {
fn to_bytes<Z: ZeroChoice>(nonce: &Nonce<Z>) -> [u8;66] {
nonce.to_bytes()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct NonceKeyPair {
pub public: Nonce<NonZero>,
pub secret: SecretNonce,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SecretNonce(pub [Scalar; 2]);
impl SecretNonce {
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()?;
Some(Self([r1, r2]))
}
pub fn to_bytes(&self) -> [u8; 64] {
let mut bytes = [0u8; 64];
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
}
pub fn random(rng: &mut impl RngCore) -> Self {
Self([Scalar::random(rng), Scalar::random(rng)])
}
pub fn into_keypair(self) -> NonceKeyPair {
NonceKeyPair::from_secret(self)
}
}
impl NonceKeyPair {
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,
}
}
pub fn secret(&self) -> &SecretNonce {
&self.secret
}
pub fn public(&self) -> Nonce<NonZero> {
self.public
}
pub fn random(rng: &mut impl RngCore) -> Self {
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 binonce",
fn from_bytes(bytes: [u8;64]) -> Option<NonceKeyPair> {
Some(NonceKeyPair::from_secret(SecretNonce::from_bytes(bytes)?))
}
}
secp256kfun::impl_display_serialize! {
fn to_bytes(value: &NonceKeyPair) -> [u8;64] {
value.secret.to_bytes()
}
}