diff --git a/src/field/crandall_field.rs b/src/field/crandall_field.rs index 26a436a5..1d55ee3b 100644 --- a/src/field/crandall_field.rs +++ b/src/field/crandall_field.rs @@ -322,6 +322,9 @@ impl Extendable<2> for CrandallField { // `R. = GF(p)[]; assert (x^2 - 3).is_irreducible()`. const W: Self = Self(3); + // DTH_ROOT = W^((ORDER - 1)/2) + const DTH_ROOT: Self = Self(18446744071293632512); + const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 2] = [Self(6483724566312148654), Self(12194665049945415126)]; @@ -333,6 +336,9 @@ impl Extendable<4> for CrandallField { const W: Self = Self(3); + // DTH_ROOT = W^((ORDER - 1)/4) + const DTH_ROOT: Self = Self(6183774639018825925); + const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 4] = [ Self(12476589904174392631), Self(896937834427772243), diff --git a/src/field/extension_field/mod.rs b/src/field/extension_field/mod.rs index 7e5ea228..08443386 100644 --- a/src/field/extension_field/mod.rs +++ b/src/field/extension_field/mod.rs @@ -14,10 +14,16 @@ pub mod target; pub trait OEF: FieldExtension { // Element W of BaseField, such that `X^d - W` is irreducible over BaseField. const W: Self::BaseField; + + // Element of BaseField such that DTH_ROOT^D == 1. Implementors + // should set this to W^((p - 1)/D), where W is as above and p is + // the order of the BaseField. + const DTH_ROOT: Self::BaseField; } impl OEF<1> for F { const W: Self::BaseField = F::ZERO; + const DTH_ROOT: Self::BaseField = F::ZERO; } pub trait Frobenius: OEF { @@ -26,16 +32,26 @@ pub trait Frobenius: OEF { self.repeated_frobenius(1) } - /// Repeated Frobenius automorphisms: x -> x^(p^k). + /// Repeated Frobenius automorphisms: x -> x^(p^count). + /// + /// Follows precomputation suggestion in Section 11.3.3 of the + /// Handbook of Elliptic and Hyperelliptic Curve Cryptography. fn repeated_frobenius(&self, count: usize) -> Self { if count == 0 { return *self; } else if count >= D { + // x |-> x^(p^D) is the identity, so x^(p^count) == + // x^(p^(count % D)) return self.repeated_frobenius(count % D); } let arr = self.to_basefield_array(); - let k = (Self::BaseField::order() - 1u32) / (D as u64); - let z0 = Self::W.exp_biguint(&(k * count as u64)); + + // z0 = DTH_ROOT^count = W^(k * count) where k = floor((p^D-1)/D) + let mut z0 = Self::DTH_ROOT; + for _ in 1..count { + z0 *= Self::DTH_ROOT; + } + let mut res = [Self::BaseField::ZERO; D]; for (i, z) in z0.powers().take(D).enumerate() { res[i] = arr[i] * z; @@ -50,6 +66,8 @@ pub trait Extendable: PrimeField + Sized { const W: Self; + const DTH_ROOT: Self; + const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; D]; /// Chosen so that when raised to the power `1<<(Self::TWO_ADICITY-Self::BaseField::TWO_ADICITY)`, @@ -61,6 +79,7 @@ pub trait Extendable: PrimeField + Sized { impl + FieldExtension<1, BaseField = F>> Extendable<1> for F { type Extension = F; const W: Self = F::ZERO; + const DTH_ROOT: Self = F::ZERO; const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 1] = [F::MULTIPLICATIVE_GROUP_GENERATOR]; const EXT_POWER_OF_TWO_GENERATOR: [Self; 1] = [F::POWER_OF_TWO_GENERATOR]; } diff --git a/src/field/extension_field/quadratic.rs b/src/field/extension_field/quadratic.rs index 3ac7b89b..a60a1a7f 100644 --- a/src/field/extension_field/quadratic.rs +++ b/src/field/extension_field/quadratic.rs @@ -21,6 +21,7 @@ impl> Default for QuadraticExtension { impl> OEF<2> for QuadraticExtension { const W: F = F::W; + const DTH_ROOT: F = F::DTH_ROOT; } impl> Frobenius<2> for QuadraticExtension {} diff --git a/src/field/extension_field/quartic.rs b/src/field/extension_field/quartic.rs index 97fc195e..0a16ff02 100644 --- a/src/field/extension_field/quartic.rs +++ b/src/field/extension_field/quartic.rs @@ -22,6 +22,7 @@ impl> Default for QuarticExtension { impl> OEF<4> for QuarticExtension { const W: F = F::W; + const DTH_ROOT: F = F::DTH_ROOT; } impl> Frobenius<4> for QuarticExtension {} diff --git a/src/field/goldilocks_field.rs b/src/field/goldilocks_field.rs index ac7b7816..fbf31659 100644 --- a/src/field/goldilocks_field.rs +++ b/src/field/goldilocks_field.rs @@ -224,6 +224,9 @@ impl Extendable<2> for GoldilocksField { // `R. = GF(p)[]; assert (x^2 - 7).is_irreducible()`. const W: Self = Self(7); + // DTH_ROOT = W^((ORDER - 1)/2) + const DTH_ROOT: Self = Self(18446744069414584320); + const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 2] = [Self(18081566051660590251), Self(16121475356294670766)]; @@ -235,6 +238,9 @@ impl Extendable<4> for GoldilocksField { const W: Self = Self(7); + // DTH_ROOT = W^((ORDER - 1)/4) + const DTH_ROOT: Self = Self(281474976710656); + const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 4] = [ Self(5024755240244648895), Self(13227474371289740625),