Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions ec/tests/point_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! 2. Short Weierstrass over a quadratic extension (F₁₉²)
//! 3. General Weierstrass over a binary extension field (F₂⁴)

use crypto_bigint::{Uint, const_prime_monty_params};
use crypto_bigint::{const_prime_monty_params, Uint};

use fp::field_ops::FieldOps;
use fp::fp_element::FpElement;
Expand Down Expand Up @@ -135,16 +135,9 @@ impl IrreduciblePoly<Fp19Mod, 1, 2> for QuadPoly {
}

impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
// Still only need 1 limb for 19^2
const ORDER: Uint<1> = Uint::<1>::from_u64(360);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
[F19::from_u64(3), F19::from_u64(3)]
}
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(45);
}

type F19_2 = FpExt<Fp19Mod, 1, 2, 1, QuadPoly, TSQuad>;
Expand Down
9 changes: 1 addition & 8 deletions ec/tests/point_weierstrass_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! 2. Short Weierstrass over a quadratic extension (F₁₉²)
//! 3. General Weierstrass over a binary extension field (F₂⁴)

use crypto_bigint::{Uint, const_prime_monty_params};
use crypto_bigint::{const_prime_monty_params, Uint};

use fp::field_ops::FieldOps;
use fp::fp_element::FpElement;
Expand Down Expand Up @@ -135,16 +135,9 @@ impl IrreduciblePoly<Fp19Mod, 1, 2> for QuadPoly {
}

impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
// Still only need 1 limb for 19^2
const ORDER: Uint<1> = Uint::<1>::from_u64(360);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
[F19::from_u64(3), F19::from_u64(3)]
}
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(45);
}

type F19_2 = FpExt<Fp19Mod, 1, 2, 1, QuadPoly, TSQuad>;
Expand Down
35 changes: 2 additions & 33 deletions fp/examples/fp_demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Run with: cargo run --bin demo
//!
use crypto_bigint::{Uint, const_prime_monty_params};
use crypto_bigint::{const_prime_monty_params, Uint};

// Pull in the library types
use fp::f2_element::F2Element;
Expand Down Expand Up @@ -38,15 +38,10 @@ impl IrreduciblePoly<Fp19Mod, 1, 2> for Poly19Quad {

// Tonelli-Shanks constants for F_{19^2}
// |F_{19^2}*| = 19^2 - 1 = 360 = 2^3 * 45
// so we have to supply 2^3 root of unity
struct TS19Quad;

impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TS19Quad {
const ORDER: Uint<1> = Uint::<1>::from_u64(360);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(45);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
[Fp19::from_u64(3), Fp19::from_u64(3)]
}
Expand Down Expand Up @@ -80,13 +75,6 @@ struct TS97283Quad;

impl TonelliShanksConstants<Fp97283Mod, 1, 2, 1> for TS97283Quad {
// p^2 - 1 = 9463982088 = 2^3 * 1182997761
const ORDER: Uint<1> = Uint::<1>::from_u64(9_463_982_088);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(4_731_991_044);
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(1_182_997_761);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(591_498_880);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);

fn root_of_unity() -> [FpElement<Fp97283Mod, 1>; 2] {
// An element of exact order 8 in F_{p^2}
[Fp97283::from_u64(96_901), Fp97283::from_u64(382)]
Expand Down Expand Up @@ -116,13 +104,6 @@ struct TS97283Cubic;

impl TonelliShanksConstants<Fp97283Mod, 1, 3, 1> for TS97283Cubic {
// p^3 - 1 = 920684569564186 = 2^1 * 460342284782093
const ORDER: Uint<1> = Uint::<1>::from_u64(920_684_569_564_186);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(460_342_284_782_093);
const S: u64 = 1;
const T: Uint<1> = Uint::<1>::from_u64(460_342_284_782_093);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(230_171_142_391_046);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(1);

fn root_of_unity() -> [FpElement<Fp97283Mod, 1>; 3] {
// Same convention as your F19^3 example when S = 1
[
Expand Down Expand Up @@ -158,18 +139,6 @@ struct TS97283Quartic;

impl TonelliShanksConstants<Fp97283Mod, 1, 4, 2> for TS97283Quartic {
// p^4 - 1 = 89566956980912803920 = 2^4 * 5597934811307050245
const ORDER: Uint<2> = Uint::<2>::from_words([0xdafdc0d3fc005050, 0x0000000000000004]);

const HALF_ORDER: Uint<2> = Uint::<2>::from_words([0x6d7ee069fe002828, 0x0000000000000002]);

const S: u64 = 4;

const T: Uint<2> = Uint::<2>::from_words([0x4dafdc0d3fc00505, 0x0000000000000000]);

const PROJENATOR_EXP: Uint<2> = Uint::<2>::from_words([0x26d7ee069fe00282, 0x0000000000000000]);

const TWOSM1: Uint<2> = Uint::<2>::from_words([0x0000000000000008, 0x0000000000000000]);

fn root_of_unity() -> [FpElement<Fp97283Mod, 1>; 4] {
// An element of exact order 16 in F_{p^4}
[
Expand Down
12 changes: 0 additions & 12 deletions fp/src/_doctest_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ pub mod _doctest_fp_ext {
}

impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
const ORDER: Uint<1> = Uint::<1>::from_u64(360);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(45);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
[Fp19::from_u64(3), Fp19::from_u64(3)]
}
Expand Down Expand Up @@ -52,12 +46,6 @@ pub mod _doctest_field_ops {
}

impl TonelliShanksConstants<Fp19Modulus, 1, 2, 1> for TSQuad {
const ORDER: Uint<1> = Uint::<1>::from_u64(360);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(45);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp19Modulus, 1>; 2] {
[F19::from_u64(3), F19::from_u64(3)]
}
Expand Down
104 changes: 104 additions & 0 deletions fp/src/_ts_consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! Helper `const` functions for computing Tonelli--Shanks constants

use crypto_bigint::{
modular::{ConstMontyForm, ConstPrimeMontyParams},
Uint,
};

/// Puts a `Uint<A>` into a `Uint<B>` where $B > A$.
///
/// # Arguments
///
/// * `x` - An integer. (Type: `Uint<A>`)
///
/// # Returns
///
/// Coerces `x` into a `Uint<B>`. (Type: `Uint<B>`)
const fn put_into_bigger_unit<const A: usize, const B: usize>(x: Uint<A>) -> Uint<B> {
let input = x.to_words();
let mut output = [0u64; B];
let mut i = 0;
while i < A && i < B {
output[i] = input[i];
i += 1;
}
Uint::<B>::from_words(output)
}

/// Gets the field order $q = p^M$
///
/// # Returns
///
/// The order of the field. (Type: `Uint<N>`)
const fn field_order<MOD, const LIMBS: usize, const M: usize, const N: usize>() -> Uint<N>
where
MOD: ConstPrimeMontyParams<LIMBS>,
{
let minus_one = ConstMontyForm::<MOD, LIMBS>::ZERO.sub(&ConstMontyForm::<MOD, LIMBS>::ONE);
let p_minus_1: Uint<LIMBS> = minus_one.retrieve();
let p = p_minus_1.wrapping_add(&Uint::<LIMBS>::ONE);
let p = put_into_bigger_unit::<LIMBS, N>(p);

let mut q = Uint::<N>::ONE;
let mut i = 0;
while i < M {
q = q.wrapping_mul(&p);
i += 1;
}
q
}

/// The size $p^M - 1$ of the finite field's multiplicative group.
///
/// # Returns
///
/// The number $p^M - 1$ as a `Uint<N>`. (Type: `Uint<N>`).
pub const fn multiplicative_group_order<MOD, const LIMBS: usize, const M: usize, const N: usize>(
) -> Uint<N>
where
MOD: ConstPrimeMontyParams<LIMBS>,
{
field_order::<MOD, LIMBS, M, N>().wrapping_sub(&Uint::<N>::ONE)
}

/// Compute the 2-adic valuation of a `UInt<N>`
///
/// # Arguments
///
/// * `x` - Integer. (Type: `&Uint<N>`)
///
/// # Returns
///
/// The 2-adic valuation of $x$. That is the integer $v$ such that $x
/// = y 2^v$ with $y$ odd. (Type: `u64`)
pub const fn two_adic_valuation<const N: usize>(x: &Uint<N>) -> u64 {
let words = x.to_words();
let mut i = 0;
while i < N {
let w = words[i];
if w != 0 {
return (i as u64) * 64 + w.trailing_zeros() as u64;
}
i += 1;
}
0
}

/// Computes $2^{\texttt{shift}}$
///
/// # Arguments
///
/// * `shift` - An integer (Type: `u64`).
///
/// # Returns
///
/// The value $2^{\texttt{shift}}$ (Type: `Uint<N>`).
pub const fn one_shl<const N: usize>(shift: u64) -> Uint<N> {
let mut words = [0u64; N];
let word = (shift / 64) as usize;
let bit = shift % 64;
if word < N {
words[word] = 1u64 << bit;
}
Uint::<N>::from_words(words)
}
53 changes: 21 additions & 32 deletions fp/src/fp_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,8 @@
//! /* Setup the Tonelli--Shanks constants */
//! struct TSQuad;
//! impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
//! // p^2 - 1
//! const ORDER: Uint<1> = Uint::<1>::from_u64(360);
//! // (p^2 - 1) / 2
//! const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
//! // p^2 - 1 = 2^S * T with T odd
//! const S: u64 = 3;
//! const T: Uint<1> = Uint::<1>::from_u64(45);
//! // (T - 1) / 2
//! const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
//! // 2^(S - 1)
//! const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
//! // 2^S root of unity
//! // 2^S root of unity where
//! // (p^2 - 1) = 2^S * (odd)
//! fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
//! [Fp19::from_u64(3), Fp19::from_u64(3)]
//! }
Expand Down Expand Up @@ -96,6 +86,7 @@ use crate::fp_element::FpElement;
use crypto_bigint::{modular::ConstPrimeMontyParams, Uint};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

use crate::_ts_consts::{multiplicative_group_order, one_shl, two_adic_valuation};
// ===========================================================================
// IrreduciblePoly — one thing callers need to implement for a new field
// ===========================================================================
Expand Down Expand Up @@ -183,6 +174,9 @@ implement for a new field
/// listed below all are derived by writing $p^M - 1 = 2^S T$ for some
/// odd $T$.
///
/// The implementation is such that everything other than a $2^S$-root
/// of unity will be computed at compile time automatically.
///
/// # Example: $\mathbb{F}_{19^2}$
/// Note that we have a factorisation $19^2 - 1 = 2^3 \cdot 45$
/// ```
Expand All @@ -199,59 +193,60 @@ implement for a new field
/// impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
/// // p^2 - 1
/// const ORDER: Uint<1> = Uint::<1>::from_u64(360);
/// // (p^2 - 1) / 2
/// const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
/// // p^2 - 1 = 2^S * T with T odd
/// const S: u64 = 3;
/// const T: Uint<1> = Uint::<1>::from_u64(45);
/// // (T - 1) / 2
/// const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
/// // 2^(S - 1)
/// const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
/// // 2^S root of unity
/// fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
/// [Fp19::from_u64(3), Fp19::from_u64(3)]
/// }
/// }
///
/// /* Alternatively we can do some of the work for you */
/// struct TSQuadAuto;
/// impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuadAuto {
/// // 2^S root of unity
/// fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
/// [Fp19::from_u64(3), Fp19::from_u64(3)]
/// }
/// }
/// ```
///
/// # Todo
///
/// - [ ] Implement `root_of_unity` as a `const`.
/// - [ ] Compute these constants at compile time to bury this from
/// the end user.
pub trait TonelliShanksConstants<MOD, const LIMBS: usize, const M: usize, const N: usize>:
'static
where
MOD: ConstPrimeMontyParams<LIMBS>,
{
/// The order of the multiplicative $\mathbb{F}\_{p^M}^*$, that is
/// the integer $p^M - 1$.
const ORDER: Uint<N>;
const ORDER: Uint<N> = multiplicative_group_order::<MOD, LIMBS, M, N>();

/// Half of `ORDER`, that is the integer $(p^M - 1) / 2$.
const HALF_ORDER: Uint<N>;
const HALF_ORDER: Uint<N> = Self::ORDER.wrapping_shr(1);

/// The constant $S$ in the 2-primary factorisation of `ORDER`,
/// that is where $p^M - 1 = 2^S T$ with $T$ odd.
const S: u64;
const S: u64 = two_adic_valuation(&Self::ORDER);

/// The constant $T$ in the 2-primary factorisation of `ORDER`,
/// that is where $p^M - 1 = 2^S T$ with $T$ odd.
const T: Uint<N>;
const T: Uint<N> = Self::ORDER.wrapping_shr(Self::S as u32);

/// The integer $2^{S - 1}$.
const TWOSM1: Uint<N>;
const TWOSM1: Uint<N> = one_shl::<N>(Self::S - 1);

/// The integer $(T - 1) / 2$ which is the exponent of the
/// "projenator" in the Tonelli--Shanks algorithm.
const PROJENATOR_EXP: Uint<N>;
const PROJENATOR_EXP: Uint<N> = Self::T.wrapping_sub(&Uint::<N>::ONE).wrapping_shr(1);

/// A choice of $2^S$ root of unity in $\mathbb{F}\_{p^M}$,
/// respresented as a vector of `FpElement` of length $M$.
///
/// # Todo
///
/// - [ ] Write this to be a `const`.
fn root_of_unity() -> [FpElement<MOD, LIMBS>; M];
}
Expand Down Expand Up @@ -293,12 +288,6 @@ where
/// /* Write out the precomputed Tonelli--Shanks constants */
/// struct TSQuad;
/// impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
/// const ORDER: Uint<1> = Uint::<1>::from_u64(360);
/// const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
/// const S: u64 = 3;
/// const T: Uint<1> = Uint::<1>::from_u64(45);
/// const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
/// const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
/// fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
/// [Fp19::from_u64(3), Fp19::from_u64(3)]
/// }
Expand Down
3 changes: 3 additions & 0 deletions fp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
//! └── lib.rs
//! ```

/// Helper functions for Tonelli--Shanks
pub mod _ts_consts;

/// Binary base field $\mathbb{F}_2$ and its arithmetic.
pub mod f2_element;
/// Binary extension fields $\mathbb{F}\_{2^m}$ built from irreducible polynomials.
Expand Down
Loading
Loading