diff --git a/bls12_381/Cargo.toml b/bls12_381/Cargo.toml index 6e77fb51b..db808a2a5 100644 --- a/bls12_381/Cargo.toml +++ b/bls12_381/Cargo.toml @@ -20,6 +20,19 @@ name = "groups" harness = false required-features = ["groups"] +[dependencies.byteorder] +version = "1" +default-features = false + +[dependencies.ff] +path = "../ff" +version = "0.6" +default-features = false + +[dependencies.rand_core] +version = "0.5" +default-features = false + [dependencies.subtle] version = "2.2.1" default-features = false diff --git a/bls12_381/src/fp.rs b/bls12_381/src/fp.rs index 28aa24bf8..02d1d7855 100644 --- a/bls12_381/src/fp.rs +++ b/bls12_381/src/fp.rs @@ -162,7 +162,7 @@ impl Fp { self.ct_eq(&Fp::zero()) } - /// Attempts to convert a little-endian byte representation of + /// Attempts to convert a big-endian byte representation of /// a scalar into an `Fp`, failing if the input is not canonical. pub fn from_bytes(bytes: &[u8; 48]) -> CtOption { let mut tmp = Fp([0, 0, 0, 0, 0, 0]); diff --git a/bls12_381/src/scalar.rs b/bls12_381/src/scalar.rs index 91f88a49b..e13231dd9 100644 --- a/bls12_381/src/scalar.rs +++ b/bls12_381/src/scalar.rs @@ -4,7 +4,9 @@ use core::convert::TryFrom; use core::fmt; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use rand_core::RngCore; +use ff::{Field, PrimeField}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use crate::util::{adc, mac, sbb}; @@ -28,6 +30,12 @@ impl fmt::Debug for Scalar { } } +impl fmt::Display for Scalar { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + impl From for Scalar { fn from(val: u64) -> Scalar { Scalar([val, 0, 0, 0]) * R2 @@ -70,6 +78,22 @@ const MODULUS: Scalar = Scalar([ 0x73ed_a753_299d_7d48, ]); +const MODULUS_BYTES: [u8; 32] = [ + 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0x02, 0xa4, 0xbd, 0x53, + 0x05, 0xd8, 0xa1, 0x09, 0x08, 0xd8, 0x39, 0x33, 0x48, 0x7d, 0x9d, 0x29, 0x53, 0xa7, 0xed, 0x73, +]; + +// The number of bits needed to represent the modulus. +const MODULUS_BITS: u32 = 255; + +// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue) +const GENERATOR: Scalar = Scalar([ + 0x0000_000e_ffff_fff1, + 0x17e3_63d3_0018_9c0f, + 0xff9c_5787_6f84_57b0, + 0x3513_3220_8fc5_a8c4, +]); + impl<'a> Neg for &'a Scalar { type Output = Scalar; @@ -145,6 +169,7 @@ const R3: Scalar = Scalar([ 0x6e2a_5bb9_c8db_33e9, ]); +// 2^S * t = MODULUS - 1 with t odd const S: u32 = 32; /// GENERATOR^t where t * 2^s + 1 = q @@ -613,12 +638,95 @@ impl Scalar { } } +impl From for [u8; 32] { + fn from(value: Scalar) -> [u8; 32] { + value.to_bytes() + } +} + impl<'a> From<&'a Scalar> for [u8; 32] { fn from(value: &'a Scalar) -> [u8; 32] { value.to_bytes() } } +impl Field for Scalar { + fn random(rng: &mut R) -> Self { + let mut buf = [0; 64]; + rng.fill_bytes(&mut buf); + Self::from_bytes_wide(&buf) + } + + fn zero() -> Self { + Self::zero() + } + + fn one() -> Self { + Self::one() + } + + fn is_zero(&self) -> bool { + self.ct_eq(&Self::zero()).into() + } + + #[must_use] + fn square(&self) -> Self { + self.square() + } + + #[must_use] + fn double(&self) -> Self { + self.double() + } + + fn invert(&self) -> CtOption { + self.invert() + } + + fn sqrt(&self) -> CtOption { + self.sqrt() + } +} + +impl PrimeField for Scalar { + type Repr = [u8; 32]; + type ReprEndianness = byteorder::LittleEndian; + + fn from_repr(r: Self::Repr) -> Option { + let res = Self::from_bytes(&r); + if res.is_some().into() { + Some(res.unwrap()) + } else { + None + } + } + + fn to_repr(&self) -> Self::Repr { + self.to_bytes() + } + + fn is_odd(&self) -> bool { + self.to_bytes()[0] & 1 == 1 + } + + fn char() -> Self::Repr { + MODULUS_BYTES + } + + const NUM_BITS: u32 = MODULUS_BITS; + const CAPACITY: u32 = Self::NUM_BITS - 1; + + fn multiplicative_generator() -> Self { + GENERATOR + } + + const S: u32 = S; + + fn root_of_unity() -> Self { + ROOT_OF_UNITY + } +} + #[test] fn test_inv() { // Compute -(q^{-1} mod 2^64) mod 2^64 by exponentiating diff --git a/jubjub/Cargo.toml b/jubjub/Cargo.toml index 31221efc7..19976d748 100644 --- a/jubjub/Cargo.toml +++ b/jubjub/Cargo.toml @@ -18,6 +18,19 @@ path = "../bls12_381" version = "0.1" default-features = false +[dependencies.byteorder] +version = "1" +default-features = false + +[dependencies.ff] +path = "../ff" +version = "0.6" +default-features = false + +[dependencies.rand_core] +version = "0.5" +default-features = false + [dependencies.subtle] version = "^2.2.1" default-features = false diff --git a/jubjub/src/fr.rs b/jubjub/src/fr.rs index e46953027..827793326 100644 --- a/jubjub/src/fr.rs +++ b/jubjub/src/fr.rs @@ -5,6 +5,8 @@ use core::convert::TryInto; use core::fmt; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use ff::{Field, PrimeField}; +use rand_core::RngCore; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use crate::util::{adc, mac, sbb}; @@ -28,6 +30,12 @@ impl fmt::Debug for Fr { } } +impl fmt::Display for Fr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + impl From for Fr { fn from(val: u64) -> Fr { Fr([val, 0, 0, 0]) * R2 @@ -70,6 +78,33 @@ pub const MODULUS: Fr = Fr([ 0x0e7d_b4ea_6533_afa9, ]); +const MODULUS_BYTES: [u8; 32] = [ + 0xb7, 0x2c, 0xf7, 0xd6, 0x5e, 0x0e, 0x97, 0xd0, 0x82, 0x10, 0xc8, 0xcc, 0x93, 0x20, 0x68, 0xa6, + 0x00, 0x3b, 0x34, 0x01, 0x01, 0x3b, 0x67, 0x06, 0xa9, 0xaf, 0x33, 0x65, 0xea, 0xb4, 0x7d, 0x0e, +]; + +// The number of bits needed to represent the modulus. +const MODULUS_BITS: u32 = 252; + +// GENERATOR = 6 (multiplicative generator of r-1 order, that is also quadratic nonresidue) +const GENERATOR: Fr = Fr([ + 0x720b_1b19_d49e_a8f1, + 0xbf4a_a361_01f1_3a58, + 0x5fa8_cc96_8193_ccbb, + 0x0e70_cbdc_7dcc_f3ac, +]); + +// 2^S * t = MODULUS - 1 with t odd +const S: u32 = 1; + +// 2^S root of unity computed by GENERATOR^t +const ROOT_OF_UNITY: Fr = Fr([ + 0xaa9f_02ab_1d61_24de, + 0xb352_4a64_6611_2932, + 0x7342_2612_15ac_260b, + 0x04d6_b87b_1da2_59e2, +]); + impl<'a> Neg for &'a Fr { type Output = Fr; @@ -575,12 +610,95 @@ impl Fr { } } +impl From for [u8; 32] { + fn from(value: Fr) -> [u8; 32] { + value.to_bytes() + } +} + impl<'a> From<&'a Fr> for [u8; 32] { fn from(value: &'a Fr) -> [u8; 32] { value.to_bytes() } } +impl Field for Fr { + fn random(rng: &mut R) -> Self { + let mut buf = [0; 64]; + rng.fill_bytes(&mut buf); + Self::from_bytes_wide(&buf) + } + + fn zero() -> Self { + Self::zero() + } + + fn one() -> Self { + Self::one() + } + + fn is_zero(&self) -> bool { + self.ct_eq(&Self::zero()).into() + } + + #[must_use] + fn square(&self) -> Self { + self.square() + } + + #[must_use] + fn double(&self) -> Self { + self.double() + } + + fn invert(&self) -> CtOption { + self.invert() + } + + fn sqrt(&self) -> CtOption { + self.sqrt() + } +} + +impl PrimeField for Fr { + type Repr = [u8; 32]; + type ReprEndianness = byteorder::LittleEndian; + + fn from_repr(r: Self::Repr) -> Option { + let res = Self::from_bytes(&r); + if res.is_some().into() { + Some(res.unwrap()) + } else { + None + } + } + + fn to_repr(&self) -> Self::Repr { + self.to_bytes() + } + + fn is_odd(&self) -> bool { + self.to_bytes()[0] & 1 == 1 + } + + fn char() -> Self::Repr { + MODULUS_BYTES + } + + const NUM_BITS: u32 = MODULUS_BITS; + const CAPACITY: u32 = Self::NUM_BITS - 1; + + fn multiplicative_generator() -> Self { + GENERATOR + } + + const S: u32 = S; + + fn root_of_unity() -> Self { + ROOT_OF_UNITY + } +} + #[test] fn test_inv() { // Compute -(r^{-1} mod 2^64) mod 2^64 by exponentiating