diff --git a/src/jubjub/fs.rs b/src/jubjub/fs.rs index 051978b..eb10e65 100644 --- a/src/jubjub/fs.rs +++ b/src/jubjub/fs.rs @@ -1,7 +1,10 @@ -use pairing::{Field, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError, LegendreSymbol}; +use byteorder::{ByteOrder, LittleEndian}; +use pairing::{BitIterator, Field, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError, LegendreSymbol}; use pairing::LegendreSymbol::*; use pairing::{adc, sbb, mac_with_carry}; +use super::ToUniform; + // s = 6554484396890773809930967563523245729705921265872317281365359162392183254199 const MODULUS: FsRepr = FsRepr([0xd0970e5ed6f72cb7, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9]); @@ -548,6 +551,31 @@ impl Fs { (self.0).0[3] = r7; self.reduce(); } + + fn mul_bits>(&self, bits: BitIterator) -> Self { + let mut res = Self::zero(); + for bit in bits { + res.double(); + + if bit { + res.add_assign(self) + } + } + res + } +} + +impl ToUniform for Fs { + /// Convert a little endian byte string into a uniform + /// field element. The number is reduced mod s. The caller + /// is responsible for ensuring the input is 64 bytes of + /// Random Oracle output. + fn to_uniform(digest: &[u8]) -> Self { + assert_eq!(digest.len(), 64); + let mut repr: [u64; 8] = [0; 8]; + LittleEndian::read_u64_into(digest, &mut repr); + Self::one().mul_bits(BitIterator::new(repr)) + } } impl SqrtField for Fs { diff --git a/src/jubjub/mod.rs b/src/jubjub/mod.rs index 3b786c1..1c21192 100644 --- a/src/jubjub/mod.rs +++ b/src/jubjub/mod.rs @@ -85,12 +85,16 @@ pub enum FixedGenerators { Max = 6 } +pub trait ToUniform { + fn to_uniform(digest: &[u8]) -> Self; +} + /// This is an extension to the pairing Engine trait which /// offers a scalar field for the embedded curve (Jubjub) /// and some pre-computed parameters. pub trait JubjubEngine: Engine { /// The scalar field of the Jubjub curve - type Fs: PrimeField + SqrtField; + type Fs: PrimeField + SqrtField + ToUniform; /// The parameters of Jubjub and the Sapling protocol type Params: JubjubParams; }