diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 3d7775e69..b4a498fb4 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -36,8 +36,9 @@ pub fn prime_field( // We may be provided with a generator of p - 1 order. It is required that this generator be quadratic // nonresidue. - let generator: Option = fetch_attr("PrimeFieldGenerator", &ast.attrs) - .map(|i| i.parse().expect("PrimeFieldGenerator must be a number.")); + let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs) + .expect("Please supply a PrimeFieldGenerator attribute") + .parse().expect("PrimeFieldGenerator should be a number"); // The arithmetic in this library only works if the modulus*2 is smaller than the backing // representation. Compute the number of limbs we need. @@ -256,7 +257,8 @@ fn prime_field_repr_impl( } fn biguint_to_u64_vec( - mut v: BigUint + mut v: BigUint, + limbs: usize ) -> Vec { let m = BigUint::one() << 64; @@ -267,6 +269,10 @@ fn biguint_to_u64_vec( v = v >> 64; } + while ret.len() < limbs { + ret.push(0); + } + ret } @@ -322,7 +328,7 @@ fn prime_field_constants_and_sqrt( repr: &syn::Ident, modulus: BigUint, limbs: usize, - generator: Option + generator: BigUint ) -> quote::Tokens { let modulus_num_bits = biguint_num_bits(modulus.clone()); @@ -332,19 +338,23 @@ fn prime_field_constants_and_sqrt( let r = (BigUint::one() << (limbs * 64)) % &modulus; // modulus - 1 = 2^s * t - let mut s = 0; + let mut s: usize = 0; let mut t = &modulus - BigUint::from_str("1").unwrap(); while t.is_even() { t = t >> 1; s += 1; } + // Compute root of unity given the generator + let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus, limbs); + let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs); + let sqrt_impl = if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() { - let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2); + let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs); // Compute -R as (m - r) - let rneg = biguint_to_u64_vec(&modulus - &r); + let rneg = biguint_to_u64_vec(&modulus - &r, limbs); quote!{ impl ::ff::SqrtField for #name { @@ -368,11 +378,9 @@ fn prime_field_constants_and_sqrt( } } } else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() { - let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1); - let generator = generator.expect("PrimeFieldGenerator attribute should be provided; should be a generator of order p - 1 and quadratic nonresidue."); - let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus); - let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1); - let t = biguint_to_u64_vec(t.clone()); + let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); + let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs); + let t = biguint_to_u64_vec(t.clone(), limbs); quote!{ impl ::ff::SqrtField for #name { @@ -425,10 +433,10 @@ fn prime_field_constants_and_sqrt( }; // Compute R^2 mod m - let r2 = biguint_to_u64_vec((&r * &r) % &modulus); + let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs); - let r = biguint_to_u64_vec(r); - let modulus = biguint_to_u64_vec(modulus); + let r = biguint_to_u64_vec(r, limbs); + let modulus = biguint_to_u64_vec(modulus, limbs); // Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1 let mut inv = 1u64; @@ -458,6 +466,16 @@ fn prime_field_constants_and_sqrt( /// -(m^{-1} mod m) mod m const INV: u64 = #inv; + /// Multiplicative generator of `MODULUS` - 1 order, also quadratic + /// nonresidue. + const GENERATOR: #repr = #repr(#generator); + + /// 2^s * t = MODULUS - 1 with t odd + const S: usize = #s; + + /// 2^s root of unity computed by GENERATOR^t + const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); + #sqrt_impl } } @@ -736,6 +754,18 @@ fn prime_field_impl( fn capacity() -> u32 { Self::num_bits() - 1 } + + fn multiplicative_generator() -> Self { + #name(GENERATOR) + } + + fn s() -> usize { + S + } + + fn root_of_unity() -> Self { + #name(ROOT_OF_UNITY) + } } impl ::ff::Field for #name { diff --git a/src/lib.rs b/src/lib.rs index c29117f47..99a7e7c34 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -147,6 +147,17 @@ pub trait PrimeField: Field /// Returns how many bits of information can be reliably stored in the /// field element. fn capacity() -> u32; + + /// Returns the multiplicative generator of `char()` - 1 order. This element + /// must also be quadratic nonresidue. + fn multiplicative_generator() -> Self; + + /// Returns s such that 2^s * t = `char()` - 1 with t odd. + fn s() -> usize; + + /// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()` + /// by t. + fn root_of_unity() -> Self; } pub struct BitIterator {