diff --git a/src/lib.rs b/src/lib.rs index a016790..a2d2e0b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,9 +42,23 @@ impl SigType for Binding {} pub struct SpendAuth {} impl SigType for SpendAuth {} -mod private { +pub(crate) mod private { use super::*; - pub trait Sealed {} - impl Sealed for Binding {} - impl Sealed for SpendAuth {} + pub trait Sealed { + fn basepoint() -> jubjub::ExtendedPoint; + } + impl Sealed for Binding { + fn basepoint() -> jubjub::ExtendedPoint { + jubjub::AffinePoint::from_bytes(constants::BINDINGSIG_BASEPOINT_BYTES) + .unwrap() + .into() + } + } + impl Sealed for SpendAuth { + fn basepoint() -> jubjub::ExtendedPoint { + jubjub::AffinePoint::from_bytes(constants::SPENDAUTHSIG_BASEPOINT_BYTES) + .unwrap() + .into() + } + } } diff --git a/src/public_key.rs b/src/public_key.rs index b076238..4bbcadb 100644 --- a/src/public_key.rs +++ b/src/public_key.rs @@ -1,6 +1,6 @@ use std::{convert::TryFrom, marker::PhantomData}; -use crate::{Binding, Error, Randomizer, SigType, Signature, SpendAuth}; +use crate::{Binding, Error, Randomizer, Scalar, SigType, Signature, SpendAuth}; /// A refinement type for `[u8; 32]` indicating that the bytes represent /// an encoding of a RedJubJub public key. @@ -62,6 +62,15 @@ impl TryFrom> for PublicKey { } impl PublicKey { + pub(crate) fn from_secret(s: &Scalar) -> PublicKey { + let point = &T::basepoint() * s; + let bytes = PublicKeyBytes { + bytes: jubjub::AffinePoint::from(&point).to_bytes(), + _marker: PhantomData, + }; + PublicKey { bytes, point } + } + /// Randomize this public key with the given `randomizer`. pub fn randomize(&self, randomizer: Randomizer) -> PublicKey { unimplemented!(); diff --git a/src/secret_key.rs b/src/secret_key.rs index db8a913..5a913d7 100644 --- a/src/secret_key.rs +++ b/src/secret_key.rs @@ -10,7 +10,7 @@ use rand_core::{CryptoRng, RngCore}; #[derive(Copy, Clone, Debug)] pub struct SecretKey { sk: Scalar, - _marker: PhantomData, + pk: PublicKey, } impl From> for [u8; 32] { @@ -19,21 +19,17 @@ impl From> for [u8; 32] { } } -impl TryFrom<[u8; 32]> for SecretKey { - type Error = Error; - - fn try_from(bytes: [u8; 32]) -> Result { - // XXX-jubjub: it does not make sense for this to be a CtOption... - // XXX-jubjub: this takes a borrow but point deser doesn't - let maybe_sk = Scalar::from_bytes(&bytes); - if maybe_sk.is_some().into() { - Ok(SecretKey { - sk: maybe_sk.unwrap(), - _marker: PhantomData, - }) - } else { - Err(Error::MalformedSecretKey) - } +impl From<[u8; 32]> for SecretKey { + fn from(bytes: [u8; 32]) -> Self { + let sk = { + // XXX-jubjub: would be nice to unconditionally deser + // This incantation ensures deserialization is infallible. + let mut wide = [0; 64]; + wide[0..32].copy_from_slice(&bytes); + Scalar::from_bytes_wide(&wide) + }; + let pk = PublicKey::from_secret(&sk); + SecretKey { sk, pk } } } @@ -54,40 +50,6 @@ where } */ -impl<'a> From<&'a SecretKey> for PublicKey { - fn from(sk: &'a SecretKey) -> PublicKey { - // XXX-jubjub: this is pretty baroque - // XXX-jubjub: provide basepoint tables for generators - let basepoint: jubjub::ExtendedPoint = - jubjub::AffinePoint::from_bytes(crate::constants::SPENDAUTHSIG_BASEPOINT_BYTES) - .unwrap() - .into(); - pk_from_sk_inner(sk, basepoint) - } -} - -impl<'a> From<&'a SecretKey> for PublicKey { - fn from(sk: &'a SecretKey) -> PublicKey { - let basepoint: jubjub::ExtendedPoint = - jubjub::AffinePoint::from_bytes(crate::constants::BINDINGSIG_BASEPOINT_BYTES) - .unwrap() - .into(); - pk_from_sk_inner(sk, basepoint) - } -} - -fn pk_from_sk_inner( - sk: &SecretKey, - basepoint: jubjub::ExtendedPoint, -) -> PublicKey { - let point = &basepoint * &sk.sk; - let bytes = PublicKeyBytes { - bytes: jubjub::AffinePoint::from(&point).to_bytes(), - _marker: PhantomData, - }; - PublicKey { bytes, point } -} - impl SecretKey { /// Randomize this public key with the given `randomizer`. pub fn randomize(&self, randomizer: Randomizer) -> PublicKey {