From faebd2b78390634f91c58be78e1ea5bc977db10b Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 3 Dec 2019 13:37:12 -0800 Subject: [PATCH 1/4] Add byte encodings for Binding, SpendAuth basepoints. These were extracted by adding printlns to the test suite for librustzcash. --- src/constants.rs | 15 +++++++++++++++ src/lib.rs | 9 +-------- 2 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 src/constants.rs diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..f6bda44 --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,15 @@ +/// The byte-encoding of the basepoint for `SpendAuthSig`. +// Extracted ad-hoc from librustzcash +// XXX add tests for this value. +pub const SPENDAUTHSIG_BASEPOINT_BYTES: [u8; 32] = [ + 48, 181, 242, 170, 173, 50, 86, 48, 188, 221, 219, 206, 77, 103, 101, 109, 5, 253, 28, 194, + 208, 55, 187, 83, 117, 182, 233, 109, 158, 1, 161, 215, +]; + +/// The byte-encoding of the basepoint for `BindingSig`. +// Extracted ad-hoc from librustzcash +// XXX add tests for this value. +pub const BINDINGSIG_BASEPOINT_BYTES: [u8; 32] = [ + 139, 106, 11, 56, 185, 250, 174, 60, 59, 128, 59, 71, 176, 241, 70, 173, 80, 171, 34, 30, 110, + 42, 251, 230, 219, 222, 69, 203, 169, 211, 129, 237, +]; diff --git a/src/lib.rs b/src/lib.rs index 011ed63..ef2ad7f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ //! Docs require the `nightly` feature until RFC 1990 lands. +mod constants; mod error; mod public_key; mod secret_key; @@ -44,11 +45,3 @@ mod private { impl Sealed for Binding {} impl Sealed for SpendAuth {} } - -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} From 36b3842f3d3c65b5962dfca0f1e9cf1b3aa568b9 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 3 Dec 2019 13:39:26 -0800 Subject: [PATCH 2/4] fmt --- src/public_key.rs | 7 +++++-- src/secret_key.rs | 7 +++++-- src/signature.rs | 8 +++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/public_key.rs b/src/public_key.rs index 42ba6a7..978ee3a 100644 --- a/src/public_key.rs +++ b/src/public_key.rs @@ -1,6 +1,6 @@ use std::{convert::TryFrom, marker::PhantomData}; -use crate::{Error, SigType, SpendAuth, Binding, Randomizer, Signature}; +use crate::{Binding, Error, Randomizer, SigType, Signature, SpendAuth}; /// A refinement type indicating that the inner `[u8; 32]` represents an /// encoding of a RedJubJub public key. @@ -12,7 +12,10 @@ pub struct PublicKeyBytes { impl From<[u8; 32]> for PublicKeyBytes { fn from(bytes: [u8; 32]) -> PublicKeyBytes { - PublicKeyBytes { bytes, _marker: PhantomData } + PublicKeyBytes { + bytes, + _marker: PhantomData, + } } } diff --git a/src/secret_key.rs b/src/secret_key.rs index 304743e..90df0a2 100644 --- a/src/secret_key.rs +++ b/src/secret_key.rs @@ -1,6 +1,6 @@ use std::{convert::TryFrom, marker::PhantomData}; -use crate::{Error, PublicKey, SigType, Binding, SpendAuth, Randomizer, Signature}; +use crate::{Binding, Error, PublicKey, Randomizer, SigType, Signature, SpendAuth}; /// A refinement type indicating that the inner `[u8; 32]` represents an /// encoding of a RedJubJub secret key. @@ -12,7 +12,10 @@ pub struct SecretKeyBytes { impl From<[u8; 32]> for SecretKeyBytes { fn from(bytes: [u8; 32]) -> SecretKeyBytes { - SecretKeyBytes{ bytes, _marker: PhantomData } + SecretKeyBytes { + bytes, + _marker: PhantomData, + } } } diff --git a/src/signature.rs b/src/signature.rs index 0429113..e902eb1 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData, convert, fmt}; +use std::{convert, fmt, marker::PhantomData}; use crate::SigType; @@ -11,7 +11,8 @@ pub struct Signature { impl From<[u8; 64]> for Signature { fn from(bytes: [u8; 64]) -> Signature { Signature { - bytes, _marker: PhantomData, + bytes, + _marker: PhantomData, } } } @@ -39,7 +40,8 @@ impl Clone for Signature { let mut bytes = [0; 64]; bytes[..].copy_from_slice(&self.bytes[..]); Signature { - bytes, _marker: PhantomData, + bytes, + _marker: PhantomData, } } } From 06a0a6404d33eb6166cacebf53be48e978568e26 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 3 Dec 2019 14:51:38 -0800 Subject: [PATCH 3/4] Serialize PublicKey, SecretKey --- src/error.rs | 9 ++++++--- src/lib.rs | 3 +++ src/public_key.rs | 21 ++++++++++++++++++--- src/secret_key.rs | 35 +++++++++++++++++++++++++++++------ 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/error.rs b/src/error.rs index a7c55d8..617773a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,7 +3,10 @@ use thiserror::Error; /// An error related to RedJubJub signatures. #[derive(Error, Debug)] pub enum Error { - /// This is a stub variant to check that thiserror derive works. - #[error("Stub error-- remove this.")] - StubError, + /// The encoding of a secret key was malformed. + #[error("Malformed secret key encoding.")] + MalformedSecretKey, + /// The encoding of a public key was malformed. + #[error("Malformed public key encoding.")] + MalformedPublicKey, } diff --git a/src/lib.rs b/src/lib.rs index ef2ad7f..7ca40cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,9 @@ mod signature; /// An element of the JubJub scalar field used for randomization of public and secret keys. pub type Randomizer = jubjub::Fr; +/// A better name than Fr. +type Scalar = jubjub::Fr; + pub use error::Error; pub use public_key::{PublicKey, PublicKeyBytes}; pub use secret_key::{SecretKey, SecretKeyBytes}; diff --git a/src/public_key.rs b/src/public_key.rs index 978ee3a..a08bfba 100644 --- a/src/public_key.rs +++ b/src/public_key.rs @@ -29,13 +29,17 @@ impl From> for [u8; 32] { // XXX PartialEq, Eq? #[derive(Copy, Clone, Debug)] pub struct PublicKey { - // fields + // XXX-jubjub: this should just be Point + point: jubjub::ExtendedPoint, + // XXX should this just store a PublicKeyBytes? + bytes: [u8; 32], _marker: PhantomData, } impl From> for PublicKeyBytes { fn from(pk: PublicKey) -> PublicKeyBytes { - unimplemented!(); + let PublicKey { bytes, _marker, .. } = pk; + PublicKeyBytes { bytes, _marker } } } @@ -43,7 +47,18 @@ impl TryFrom> for PublicKey { type Error = Error; fn try_from(bytes: PublicKeyBytes) -> Result { - unimplemented!(); + // XXX-jubjub: this should not use CtOption + // XXX-jubjub: this takes ownership of bytes, while Fr doesn't. + let maybe_point = jubjub::AffinePoint::from_bytes(bytes.bytes); + if maybe_point.is_some().into() { + Ok(PublicKey { + point: maybe_point.unwrap().into(), + bytes: bytes.bytes, + _marker: PhantomData, + }) + } else { + Err(Error::MalformedPublicKey) + } } } diff --git a/src/secret_key.rs b/src/secret_key.rs index 90df0a2..d9a64dd 100644 --- a/src/secret_key.rs +++ b/src/secret_key.rs @@ -1,6 +1,6 @@ use std::{convert::TryFrom, marker::PhantomData}; -use crate::{Binding, Error, PublicKey, Randomizer, SigType, Signature, SpendAuth}; +use crate::{Binding, Error, PublicKey, Randomizer, Scalar, SigType, Signature, SpendAuth}; /// A refinement type indicating that the inner `[u8; 32]` represents an /// encoding of a RedJubJub secret key. @@ -29,27 +29,50 @@ impl From> for [u8; 32] { // XXX PartialEq, Eq? #[derive(Copy, Clone, Debug)] pub struct SecretKey { - // fields + sk: Scalar, _marker: PhantomData, } impl From> for SecretKeyBytes { - fn from(pk: SecretKey) -> SecretKeyBytes { - unimplemented!(); + fn from(sk: SecretKey) -> SecretKeyBytes { + SecretKeyBytes { + bytes: sk.sk.to_bytes(), + _marker: PhantomData, + } } } // XXX could this be a From impl? +// not unless there's an infallible conversion from bytes to scalars, +// which is not currently present in jubjub impl TryFrom> for SecretKey { type Error = Error; fn try_from(bytes: SecretKeyBytes) -> 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.bytes); + if maybe_sk.is_some().into() { + Ok(SecretKey { + sk: maybe_sk.unwrap(), + _marker: PhantomData, + }) + } else { + Err(Error::MalformedSecretKey) + } + } +} + +impl<'a> From<&'a SecretKey> for PublicKey { + fn from(sk: &'a SecretKey) -> PublicKey { + // XXX refactor jubjub API + //let basepoint: jubjub::ExtendedPoint = jubjub::AffinePoint::from_bytes(&crate::constants::SPENDAUTHSIG_BASEPOINT_BYTES).unwrap().into(); unimplemented!(); } } -impl<'a, T: SigType> From<&'a SecretKey> for PublicKey { - fn from(sk: &'a SecretKey) -> PublicKey { +impl<'a> From<&'a SecretKey> for PublicKey { + fn from(sk: &'a SecretKey) -> PublicKey { unimplemented!(); } } From 01cddd493be144b516e801943a2edc2bb29f06b1 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 3 Dec 2019 15:01:54 -0800 Subject: [PATCH 4/4] Add SecretKey -> PublicKey conversion. --- src/public_key.rs | 6 +++--- src/secret_key.rs | 29 +++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/public_key.rs b/src/public_key.rs index a08bfba..c6d773c 100644 --- a/src/public_key.rs +++ b/src/public_key.rs @@ -30,10 +30,10 @@ impl From> for [u8; 32] { #[derive(Copy, Clone, Debug)] pub struct PublicKey { // XXX-jubjub: this should just be Point - point: jubjub::ExtendedPoint, + pub(crate) point: jubjub::ExtendedPoint, // XXX should this just store a PublicKeyBytes? - bytes: [u8; 32], - _marker: PhantomData, + pub(crate) bytes: [u8; 32], + pub(crate) _marker: PhantomData, } impl From> for PublicKeyBytes { diff --git a/src/secret_key.rs b/src/secret_key.rs index d9a64dd..54a6fdd 100644 --- a/src/secret_key.rs +++ b/src/secret_key.rs @@ -65,15 +65,36 @@ impl TryFrom> for SecretKey { impl<'a> From<&'a SecretKey> for PublicKey { fn from(sk: &'a SecretKey) -> PublicKey { - // XXX refactor jubjub API - //let basepoint: jubjub::ExtendedPoint = jubjub::AffinePoint::from_bytes(&crate::constants::SPENDAUTHSIG_BASEPOINT_BYTES).unwrap().into(); - unimplemented!(); + // 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 { - unimplemented!(); + 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 = jubjub::AffinePoint::from(&point).to_bytes(); + PublicKey { + point, + bytes, + _marker: PhantomData, } }