From 6ad3ef846588151c431641675af03b8875f7b8c1 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 5 May 2020 01:27:55 +1200 Subject: [PATCH 1/5] Implement EdDSA-optimized lattice basis reduction in dimension 2 Uses Algorithm 4 from Pornin 2020 to find a suitable short vector. References: - Pornin 2020: https://eprint.iacr.org/2020/454 --- curve25519-dalek/src/scalar.rs | 2 + .../src/scalar/lattice_reduction.rs | 414 ++++++++++++++++++ 2 files changed, 416 insertions(+) create mode 100644 curve25519-dalek/src/scalar/lattice_reduction.rs diff --git a/curve25519-dalek/src/scalar.rs b/curve25519-dalek/src/scalar.rs index 5e0d1c96..7605b3b9 100644 --- a/curve25519-dalek/src/scalar.rs +++ b/curve25519-dalek/src/scalar.rs @@ -111,6 +111,8 @@ //! reduces a \\(512\\)-bit integer, if the optional `digest` feature //! has been enabled. +pub(crate) mod lattice_reduction; + use core::borrow::Borrow; use core::fmt::Debug; use core::iter::{Product, Sum}; diff --git a/curve25519-dalek/src/scalar/lattice_reduction.rs b/curve25519-dalek/src/scalar/lattice_reduction.rs new file mode 100644 index 00000000..73be6604 --- /dev/null +++ b/curve25519-dalek/src/scalar/lattice_reduction.rs @@ -0,0 +1,414 @@ +// -*- mode: rust; -*- +// +// This file is part of curve25519-dalek. +// Copyright (c) 2020-2024 Jack Grigg +// See LICENSE for licensing information. +// +// Author: +// Jack Grigg +#![allow(non_snake_case)] + +use core::cmp::Ordering; +use core::mem; +use core::ops::{Add, AddAssign, Shl, Sub, SubAssign}; + +use crate::{constants::BASEPOINT_ORDER_PRIVATE, scalar::Scalar}; + +/// The low 127 bits of \\( \ell \\). +const ELL_LOWER_HALF: i128 = 0x14de_f9de_a2f7_9cd6_5812_631a_5cf5_d3ed; + +/// Finds a short non-zero vector \\((d_0, d_1)\\) such that \\(d_0 = d_1 k \mod \ell\\). +/// \\(d_0\\) and \\(d_1)\\) may be negative. +/// +/// Implements Algorithm 4 from [Pornin 2020](https://eprint.iacr.org/2020/454). +pub(crate) fn find_short_vector(k: &Scalar) -> (i128, i128) { + let mut N_u = BigInt::ell_squared(); + let mut N_v = BigInt::mul(k, k) + BigInt::one(); + let mut p = BigInt::mul(&BASEPOINT_ORDER_PRIVATE, k); + + /// The target bit length of `N_v` for the vector to be considered short. + const T: usize = 254; // len(\ell) + 1 + + let (mut u_0, mut u_1) = (ELL_LOWER_HALF, 0); + let (mut v_0, mut v_1) = ( + i128::from_le_bytes(k.to_bytes()[..16].try_into().expect("size matches")), + 1, + ); + + loop { + if N_u < N_v { + mem::swap(&mut u_0, &mut v_0); + mem::swap(&mut u_1, &mut v_1); + mem::swap(&mut N_u, &mut N_v); + } + + let len_N_v = N_v.bit_len(); + if len_N_v <= T { + return (v_0, v_1); + } + + let s = p.bit_len().saturating_sub(len_N_v); + if p > BigInt::zero() { + u_0 = u_0.wrapping_sub(v_0.wrapping_shl(s as u32)); + u_1 = u_1.wrapping_sub(v_1.wrapping_shl(s as u32)); + N_u += (N_v << (2 * s)) - (p << (s + 1)); + p -= N_v << s; + } else { + u_0 = u_0.wrapping_add(v_0.wrapping_shl(s as u32)); + u_1 = u_1.wrapping_add(v_1.wrapping_shl(s as u32)); + N_u += (N_v << (2 * s)) + (p << (s + 1)); + p += N_v << s; + } + } +} + +/// Represents a signed two's complement 512-bit integer in eight 64-bit limbs. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct BigInt([u64; 8]); + +impl Ord for BigInt { + fn cmp(&self, other: &Self) -> Ordering { + // If the signs differ, we can quickly determine ordering. + let a_is_neg = self.is_negative(); + let b_is_neg = other.is_negative(); + match (a_is_neg, b_is_neg) { + (true, false) => return Ordering::Less, + (false, true) => return Ordering::Greater, + _ => (), + } + + // Compare the integers ignoring sign. Because we use two's complement, and the + // integers have the same sign, this is guaranteed to give the correct result. + self.0 + .iter() + .zip(other.0.iter()) + .rev() + .find_map(|(a, b)| match a.cmp(b) { + Ordering::Equal => None, + ord => Some(ord), + }) + .unwrap_or(Ordering::Equal) + } +} + +impl PartialOrd for BigInt { + fn partial_cmp(&self, other: &BigInt) -> Option { + Some(self.cmp(other)) + } +} + +impl BigInt { + const fn zero() -> BigInt { + BigInt([0; 8]) + } + + const fn one() -> BigInt { + BigInt([1, 0, 0, 0, 0, 0, 0, 0]) + } + + /// \\( \ell^2 \\) + const fn ell_squared() -> BigInt { + BigInt([ + 0xe2ed_f685_ab12_8969, + 0x6803_9276_2298_a31d, + 0x3dce_ec73_d217_f5be, + 0xa1b3_9941_1b7c_309a, + 0xcb02_4c63_4b9e_ba7d, + 0x029b_df3b_d45e_f39a, + 0x0000_0000_0000_0000, + 0x0100_0000_0000_0000, + ]) + } + + /// Returns `true` if the sign bit is set. + fn is_negative(&self) -> bool { + self.0[7] >> 63 != 0 + } + + /// Returns the minimal size (in bits) of the binary representation of this value, in + /// two's complement, excluding the sign bit. + fn bit_len(&self) -> usize { + // The implementation starts with two observations: + // - In two's complement, positive integers are padded above the most significant + // bit with 0-bits, and negative integers are padded above the MSB with 1-bits. + // - We can efficiently count the number of leading zeroes in any limb. + + // Create a mask from the sign bit that matches the padding: + // - All zeroes if positive. + // - All ones if positive. + let sign_mask = -((self.0[7] >> 63) as i64) as u64; + + self.0 + .iter() + .enumerate() + // Find the most significant limb that does not match the mask (and therefore + // contains the most significant bit). + .rev() + .find(|(_, w)| **w != sign_mask) + // XOR the limb with the mask, resulting in a word that has leading zeroes + // followed by the most significant bit as a 1. + .map(|(i, w)| (i, w ^ sign_mask)) + // Compute the position of the most significant bit. + .map(|(i, w)| ((i + 1) * 64) - w.leading_zeros() as usize) + // If all limbs were padding, the bit length is zero. + .unwrap_or(0) + } + + /// Returns `a * b` as an unreduced 512-bit integer. + fn mul(a: &Scalar, b: &Scalar) -> BigInt { + /// Converts a [`Scalar`] into a set of little-endian 64-bit limbs. + fn to_limbs(s: &Scalar) -> [u64; 4] { + let mut limbs = [0; 4]; + for (i, l) in s + .as_bytes() + .chunks(8) + .map(|c| u64::from_le_bytes(c.try_into().expect("size matches"))) + .enumerate() + { + limbs[i] = l; + } + limbs + } + + /// Computes a + (b * c) + carry, returning the result along with the new carry. + #[inline(always)] + const fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let ret = (a as u128) + ((b as u128) * (c as u128)) + (carry as u128); + (ret as u64, (ret >> 64) as u64) + } + + let a = to_limbs(a); + let b = to_limbs(b); + + let (w0, carry) = mac(0, a[0], b[0], 0); + let (w1, carry) = mac(0, a[0], b[1], carry); + let (w2, carry) = mac(0, a[0], b[2], carry); + let (w3, w4) = mac(0, a[0], b[3], carry); + + let (w1, carry) = mac(w1, a[1], b[0], 0); + let (w2, carry) = mac(w2, a[1], b[1], carry); + let (w3, carry) = mac(w3, a[1], b[2], carry); + let (w4, w5) = mac(w4, a[1], b[3], carry); + + let (w2, carry) = mac(w2, a[2], b[0], 0); + let (w3, carry) = mac(w3, a[2], b[1], carry); + let (w4, carry) = mac(w4, a[2], b[2], carry); + let (w5, w6) = mac(w5, a[2], b[3], carry); + + let (w3, carry) = mac(w3, a[3], b[0], 0); + let (w4, carry) = mac(w4, a[3], b[1], carry); + let (w5, carry) = mac(w5, a[3], b[2], carry); + let (w6, w7) = mac(w6, a[3], b[3], carry); + + // The top 7 bits of the top limb should be zero. This includes the sign bit; + // Scalars are always unsigned, so we don't need to apply a correction here. + debug_assert_eq!(w7 >> 57, 0); + + BigInt([w0, w1, w2, w3, w4, w5, w6, w7]) + } +} + +impl Add for BigInt { + type Output = BigInt; + + fn add(mut self, rhs: BigInt) -> Self::Output { + self += rhs; + self + } +} + +impl AddAssign for BigInt { + fn add_assign(&mut self, rhs: BigInt) { + /// Computes a + b + carry, returning the result along with the new carry. + #[inline(always)] + const fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { + let ret = (a as u128) + (b as u128) + (carry as u128); + (ret as u64, (ret >> 64) as u64) + } + + // a + b + let mut carry: u64 = 0; + for i in 0..8 { + let (res, new_carry) = adc(self.0[i], rhs.0[i], carry); + self.0[i] = res; + carry = new_carry; + } + } +} + +impl Sub for BigInt { + type Output = BigInt; + + fn sub(mut self, rhs: BigInt) -> Self::Output { + self -= rhs; + self + } +} + +impl SubAssign for BigInt { + fn sub_assign(&mut self, rhs: BigInt) { + /// Computes a - (b + borrow), returning the result along with the new borrow. + #[inline(always)] + const fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let ret = (a as u128).wrapping_sub((b as u128) + ((borrow >> 63) as u128)); + (ret as u64, (ret >> 64) as u64) + } + + // a - b + let mut borrow: u64 = 0; + for i in 0..8 { + let (res, new_borrow) = sbb(self.0[i], rhs.0[i], borrow); + self.0[i] = res; + borrow = new_borrow; + } + } +} + +impl Shl for BigInt { + type Output = BigInt; + + fn shl(mut self, s: usize) -> Self::Output { + let (k, s) = if s >= 64 { + let k = s / 64; + self.0.rotate_right(k); + for w in &mut self.0[..k] { + *w = 0; + } + (k, s - (k * 64)) + } else { + (0, s) + }; + + /// Computes (a << b) | carry, returning the result along with the new carry. + #[inline(always)] + const fn slc(a: u64, b: usize, carry: u64) -> (u64, u64) { + let ret = ((a as u128) << b) | (carry as u128); + (ret as u64, (ret >> 64) as u64) + } + + let mut carry: u64 = 0; + for i in k..8 { + let (res, new_carry) = slc(self.0[i], s, carry); + self.0[i] = res; + carry = new_carry; + } + + self + } +} + +#[cfg(test)] +mod tests { + use super::{find_short_vector, BigInt}; + use crate::scalar::Scalar; + + #[test] + fn test_find_short_vector() { + let mut rng = rand::thread_rng(); + + for _ in 0..500 { + let k = Scalar::random(&mut rng); + + let (d_0, d_1) = find_short_vector(&k); + + let d_0 = if d_0.is_negative() { + -Scalar::from(d_0.abs() as u128) + } else { + Scalar::from(d_0.abs() as u128) + }; + + let d_1 = if d_1.is_negative() { + -Scalar::from(d_1.abs() as u128) + } else { + Scalar::from(d_1.abs() as u128) + }; + + assert_eq!(d_0, d_1 * k); + } + } + + #[test] + fn ord() { + let zero = BigInt::zero(); + let one = BigInt::one(); + let neg_one = zero - one; + let neg_ell_sq = zero - BigInt::ell_squared(); + + assert!(zero < one); + assert!(one < BigInt::ell_squared()); + assert!(neg_one < zero); + assert!(neg_one < one); + assert!(neg_ell_sq < neg_one); + } + + #[test] + fn bit_len() { + let zero = BigInt::zero(); + let one = BigInt::one(); + let neg_one = zero - one; + + assert_eq!(zero.bit_len(), 0); + assert_eq!(one.bit_len(), 1); + assert_eq!(neg_one.bit_len(), 0); + assert_eq!(BigInt::ell_squared().bit_len(), 505); + } + + #[test] + fn addition() { + assert_eq!(BigInt::zero() + BigInt::one(), BigInt::one()); + } + + #[test] + fn subtraction() { + assert_eq!(BigInt::one() - BigInt::one(), BigInt::zero()); + } + + #[test] + fn shl() { + assert_eq!(BigInt::one() << 1, BigInt([2, 0, 0, 0, 0, 0, 0, 0])); + assert_eq!( + BigInt([ + 0xffff_ffff_ffff_ffff, + 0x0000_0000_0000_0000, + 0xffff_ffff_ffff_ffff, + 0x0000_0000_0000_0000, + 0xffff_ffff_ffff_ffff, + 0x0000_0000_0000_0000, + 0xffff_ffff_ffff_ffff, + 0x0000_0000_0000_0000, + ]) << 24, + BigInt([ + 0xffff_ffff_ff00_0000, + 0x0000_0000_00ff_ffff, + 0xffff_ffff_ff00_0000, + 0x0000_0000_00ff_ffff, + 0xffff_ffff_ff00_0000, + 0x0000_0000_00ff_ffff, + 0xffff_ffff_ff00_0000, + 0x0000_0000_00ff_ffff, + ]) + ); + assert_eq!( + BigInt([ + 0xffff_ffff_ffff_ffff, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x01ff_ffff_ffff_ffff, + ]) << 48, + BigInt([ + 0xffff_0000_0000_0000, + 0x0000_ffff_ffff_ffff, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, + 0xffff_0000_0000_0000, + ]) + ); + } +} From f5025a6af64571350385e2bc4a1b30aefd85863b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 5 May 2020 01:44:30 +1200 Subject: [PATCH 2/5] =?UTF-8?q?Add=20serial=20backend=20for=20computing=20?= =?UTF-8?q?=CE=B4(aA=20+=20bB=20-=20C)=20in=20variable=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This corresponds to the signature verification optimisation presented in Antipa et al 2005. It uses windowed non-adjacent form Straus for the multiscalar multiplication. References: - Antipa et al 2005: http://cacr.uwaterloo.ca/techreports/2005/cacr2005-28.pdf --- .gitattributes | 2 + .github/workflows/workspace.yml | 20 + .../src/backend/serial/fiat_u32/mod.rs | 2 +- .../src/backend/serial/fiat_u64/mod.rs | 2 +- .../serial/scalar_mul/abglsv_pornin.rs | 192 +++ .../src/backend/serial/scalar_mul/mod.rs | 2 + .../affine_odd_multiples_of_b_shl_128.rs | 905 ++++++++++ .../u32/{constants.rs => constants/mod.rs} | 73 + .../affine_odd_multiples_of_b_shl_128.rs | 1481 +++++++++++++++++ .../u64/{constants.rs => constants/mod.rs} | 85 + 10 files changed, 2762 insertions(+), 2 deletions(-) create mode 100644 .gitattributes create mode 100644 curve25519-dalek/src/backend/serial/scalar_mul/abglsv_pornin.rs create mode 100644 curve25519-dalek/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs rename curve25519-dalek/src/backend/serial/u32/{constants.rs => constants/mod.rs} (98%) create mode 100644 curve25519-dalek/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs rename curve25519-dalek/src/backend/serial/u64/{constants.rs => constants/mod.rs} (98%) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..64fc4e12 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +curve25519-dalek/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs linguist-generated=true +curve25519-dalek/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs linguist-generated=true diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index b8e44dc5..3bb25f19 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -90,6 +90,26 @@ jobs: components: clippy - run: cargo clippy --target x86_64-unknown-linux-gnu --all-features + generated: + name: Check generated tables + runs-on: ubuntu-latest + strategy: + matrix: + bits: ['32', '64'] + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - run: cargo test table_generators + env: + RUSTFLAGS: '--cfg curve25519_dalek_bits="${{ matrix.bits }}" --cfg curve25519_dalek_generate_tables' + - name: Verify working directory is not clean + run: if $(git diff --quiet); then false; else true; fi + - run: cargo fmt + - name: Verify working directory is clean + run: git diff --exit-code + rustfmt: name: Check formatting runs-on: ubuntu-latest diff --git a/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs b/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs index 974316e5..2ee654ed 100644 --- a/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs +++ b/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs @@ -22,5 +22,5 @@ pub mod scalar; pub mod field; -#[path = "../u32/constants.rs"] +#[path = "../u32/constants/mod.rs"] pub mod constants; diff --git a/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs b/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs index 8c830624..c2484c1e 100644 --- a/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs +++ b/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs @@ -24,5 +24,5 @@ pub mod scalar; pub mod field; -#[path = "../u64/constants.rs"] +#[path = "../u64/constants/mod.rs"] pub mod constants; diff --git a/curve25519-dalek/src/backend/serial/scalar_mul/abglsv_pornin.rs b/curve25519-dalek/src/backend/serial/scalar_mul/abglsv_pornin.rs new file mode 100644 index 00000000..ad1bbd5e --- /dev/null +++ b/curve25519-dalek/src/backend/serial/scalar_mul/abglsv_pornin.rs @@ -0,0 +1,192 @@ +// -*- mode: rust; -*- +// +// This file is part of curve25519-dalek. +// Copyright (c) 2020-2024 Jack Grigg +// See LICENSE for licensing information. +// +// Author: +// Jack Grigg +#![allow(non_snake_case)] + +use core::cmp::Ordering; + +use crate::{ + backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint}, + constants, + edwards::EdwardsPoint, + scalar::{lattice_reduction::find_short_vector, Scalar}, + traits::Identity, + window::NafLookupTable5, +}; + +/// Computes \\([δa]A + [δb]B - [δ]C\\) in variable time. +/// +/// - \\(B\\) is the Ed25519 basepoint. +/// - \\(δ\\) is a value invertible \\( \mod \ell \\), which is selected internally to +/// this function. +/// +/// This corresponds to the signature verification optimisation presented in +/// [Antipa et al 2005](http://cacr.uwaterloo.ca/techreports/2005/cacr2005-28.pdf). +pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar, C: &EdwardsPoint) -> EdwardsPoint { + // Starting with the target equation: + // + // [(δa mod l)]A + [(δb mod l)]B - [δ]C + // + // We can split δb mod l into two halves e_0 (128 bits) and e_1 (125 bits), and + // rewrite the equation as: + // + // [(δa mod l)]A + [e_0]B + [e_1 2^128]B - [δ]C + // + // B and [2^128]B are precomputed, and their resulting scalar multiplications each + // have half as many doublings. We therefore want to find a pair of signed integers + // + // (d_0, d_1) = (δa mod l, δ) + // + // that both have as few bits as possible, similarly reducing the number of doublings + // in the scalar multiplications [d_0]A and [d_1]C. This is equivalent to finding a + // short vector in a lattice of dimension 2. + + // Find a short vector. + let (d_0, d_1) = find_short_vector(a); + + // Move the signs of d_0 and d_1 into their corresponding bases and scalars. + let A = if d_0.is_negative() { -A } else { *A }; + let (b, negC) = if d_1.is_negative() { + (-b, *C) + } else { + (*b, -C) + }; + let d_0 = Scalar::from(d_0.unsigned_abs()); + let d_1 = Scalar::from(d_1.unsigned_abs()); + + // Calculate the remaining scalars. + let (e_0, e_1) = { + let db = b * d_1; + let mut e_0 = [0; 32]; + let mut e_1 = [0; 32]; + e_0[..16].copy_from_slice(&db.as_bytes()[..16]); + e_1[..16].copy_from_slice(&db.as_bytes()[16..]); + (Scalar { bytes: e_0 }, Scalar { bytes: e_1 }) + }; + + // Now we can compute the following using Straus's method: + // [d_0]A + [e_0]B + [e_1][2^128]B + [d_1][-C] + // + // We inline it here so we can use precomputed multiples of [2^128]B. + + let d_0_naf = d_0.non_adjacent_form(5); + + #[cfg(feature = "precomputed-tables")] + let e_0_naf = e_0.non_adjacent_form(8); + #[cfg(not(feature = "precomputed-tables"))] + let e_0_naf = e_0.non_adjacent_form(5); + + #[cfg(feature = "precomputed-tables")] + let e_1_naf = e_1.non_adjacent_form(8); + #[cfg(not(feature = "precomputed-tables"))] + let e_1_naf = e_1.non_adjacent_form(5); + + let d_1_naf = d_1.non_adjacent_form(5); + + // Find starting index + let mut i: usize = 255; + for j in (0..256).rev() { + i = j; + if d_0_naf[i] != 0 || e_0_naf[i] != 0 || e_1_naf[i] != 0 || d_1_naf[i] != 0 { + break; + } + } + + let table_A = NafLookupTable5::::from(&A); + + #[cfg(feature = "precomputed-tables")] + let table_B = &constants::AFFINE_ODD_MULTIPLES_OF_BASEPOINT; + #[cfg(not(feature = "precomputed-tables"))] + let table_B = + &NafLookupTable5::::from(&constants::ED25519_BASEPOINT_POINT); + + #[cfg(feature = "precomputed-tables")] + let table_B_SHL_128 = &constants::AFFINE_ODD_MULTIPLES_OF_B_SHL_128; + #[cfg(not(feature = "precomputed-tables"))] + let table_B_SHL_128 = + &NafLookupTable5::::from(&constants::ED25519_BASEPOINT_SHL_128); + + let table_negC = NafLookupTable5::::from(&negC); + + let mut r = ProjectivePoint::identity(); + loop { + let mut t = r.double(); + + match d_0_naf[i].cmp(&0) { + Ordering::Greater => t = &t.as_extended() + &table_A.select(d_0_naf[i] as usize), + Ordering::Less => t = &t.as_extended() - &table_A.select(-d_0_naf[i] as usize), + Ordering::Equal => {} + } + + match e_0_naf[i].cmp(&0) { + Ordering::Greater => t = &t.as_extended() + &table_B.select(e_0_naf[i] as usize), + Ordering::Less => t = &t.as_extended() - &table_B.select(-e_0_naf[i] as usize), + Ordering::Equal => {} + } + + match e_1_naf[i].cmp(&0) { + Ordering::Greater => { + t = &t.as_extended() + &table_B_SHL_128.select(e_1_naf[i] as usize); + } + Ordering::Less => t = &t.as_extended() - &table_B_SHL_128.select(-e_1_naf[i] as usize), + Ordering::Equal => {} + } + + match d_1_naf[i].cmp(&0) { + Ordering::Greater => t = &t.as_extended() + &table_negC.select(d_1_naf[i] as usize), + Ordering::Less => t = &t.as_extended() - &table_negC.select(-d_1_naf[i] as usize), + Ordering::Equal => {} + } + + r = t.as_projective(); + + if i == 0 { + break; + } + i -= 1; + } + + r.as_extended() +} + +#[cfg(test)] +mod tests { + use super::mul; + use crate::{constants::ED25519_BASEPOINT_POINT, scalar::Scalar, traits::IsIdentity}; + + #[test] + fn test_mul() { + let a = Scalar::from(2u8); + let A = ED25519_BASEPOINT_POINT.double(); // [2]B + let b = Scalar::from(4u8); + let C = A.double().double(); // [8]B + + // The equation evaluates to the identity, so will be unaffected by δ. + assert_eq!( + mul(&a, &A, &b, &C), + (a * A) + (b * ED25519_BASEPOINT_POINT) - C + ); + + // Now test some random values. + let mut rng = rand::thread_rng(); + + for _ in 0..100 { + let a = Scalar::random(&mut rng); + let A = &Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT; + let b = Scalar::random(&mut rng); + + // With a correctly-constructed C, we get the identity. + let C = (a * A) + (b * ED25519_BASEPOINT_POINT); + assert!(mul(&a, &A, &b, &C).is_identity()); + + // With a random C, with high probability we do not get the identity. + let C = &Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT; + assert!(!mul(&a, &A, &b, &C).is_identity()); + } + } +} diff --git a/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs b/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs index 7747decc..75745a84 100644 --- a/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs +++ b/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs @@ -17,6 +17,8 @@ //! scalar multiplication implementations, since it only uses one //! curve model. +pub mod abglsv_pornin; + #[allow(missing_docs)] pub mod variable_base; diff --git a/curve25519-dalek/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs b/curve25519-dalek/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs new file mode 100644 index 00000000..bdb3a558 --- /dev/null +++ b/curve25519-dalek/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs @@ -0,0 +1,905 @@ +//! Generated file, do not alter! + +use super::super::field::FieldElement2625; +use crate::{backend::serial::curve_models::AffineNielsPoint, window::NafLookupTable8}; + +/// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. +pub(crate) const AFFINE_ODD_MULTIPLES_OF_B_SHL_128: NafLookupTable8 = + NafLookupTable8([ + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 78483087, 12660714, 17861383, 21013599, 78044431, 34653658, 53222787, 24462691, + 106490683, 44912934, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 54378055, 10311866, 1510375, 10778093, 64989409, 24408729, 32676002, 11149336, + 40985213, 4985767, + ]), + xy2d: FieldElement2625::from_limbs([ + 48012542, 341146, 60911379, 33315398, 15756972, 24757770, 66125820, 13794113, + 47694557, 17933176, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 84856310, 43593691, 86477162, 29503840, 46478228, 51067577, 99101545, 17696455, + 104957364, 28042459, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 31932008, 28568291, 47496481, 16366579, 22023614, 88450, 11371999, 29810185, + 4882241, 22927527, + ]), + xy2d: FieldElement2625::from_limbs([ + 29796488, 37186, 19818052, 10115756, 55279832, 3352735, 18551198, 3272828, + 61917932, 29392022, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 28425947, 27718999, 66531773, 28857233, 120000172, 40425360, 75030413, 26986644, + 26333139, 47822096, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 56041645, 11871230, 27385719, 22994888, 62522949, 22365119, 10004785, 24844944, + 45347639, 8930323, + ]), + xy2d: FieldElement2625::from_limbs([ + 45911060, 17158396, 25654215, 31829035, 12282011, 11008919, 1541940, 4757911, + 40617363, 17145491, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 91688613, 3711569, 68451186, 22374305, 107212592, 47679386, 44564334, 14074918, + 21964432, 41789689, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 60580251, 31142934, 9442965, 27628844, 12025639, 32067012, 64127349, 31885225, + 13006805, 2355433, + ]), + xy2d: FieldElement2625::from_limbs([ + 50803946, 19949172, 60476436, 28412082, 16974358, 22643349, 27202043, 1719366, + 1141648, 20758196, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 37210296, 44023235, 55519479, 42847119, 52808359, 17552182, 88695747, 34499834, + 78272570, 49224323, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 31206520, 15824593, 16020985, 1311600, 11901613, 18681950, 17190048, 20972874, + 36367312, 16736695, + ]), + xy2d: FieldElement2625::from_limbs([ + 57913035, 17785021, 13803590, 19987782, 53527313, 27679244, 51081104, 8751993, + 57229443, 21797682, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 80927297, 33318055, 61724740, 27489984, 64579957, 63418509, 41055839, 40318490, + 88977149, 20265728, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 30168086, 8879691, 8082410, 20908532, 49048412, 1925828, 36719081, 18852706, + 45403594, 13481125, + ]), + xy2d: FieldElement2625::from_limbs([ + 20368198, 29299801, 56989850, 18531975, 6143432, 18332713, 22947777, 26680478, + 52840559, 5738077, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 130447597, 21992360, 57848361, 43570921, 45383173, 38670251, 23891453, 31807629, + 41897809, 42587261, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 1787335, 11391558, 5886665, 12683293, 60262716, 18956364, 47438617, 31589710, + 22825755, 12694491, + ]), + xy2d: FieldElement2625::from_limbs([ + 33951444, 14270088, 4920710, 22678367, 26741607, 22171118, 23619815, 25557760, + 19219336, 29816249, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 61220352, 34382991, 66089102, 46738595, 25007773, 55051220, 73991614, 29070951, + 62931443, 26042728, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 21329464, 2335990, 20644175, 1930420, 56815309, 32391427, 15310865, 28790024, + 54737184, 4184911, + ]), + xy2d: FieldElement2625::from_limbs([ + 26287248, 13875740, 41814500, 13003275, 7041512, 17215295, 42960689, 20033689, + 37163595, 12870103, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 68193200, 33339813, 50381793, 42051400, 76192926, 16239220, 12032273, 16542902, + 96457053, 33898990, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 24560414, 14945001, 59061724, 26829073, 23182461, 18717946, 56584298, 8818117, + 17813773, 20552368, + ]), + xy2d: FieldElement2625::from_limbs([ + 63182233, 6011282, 37889543, 8399715, 51847769, 29593899, 2092783, 7373662, + 23171764, 17710703, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 13444892, 9836395, 90791302, 35776835, 85927515, 23529127, 14581960, 23200973, + 53645696, 33910843, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 65096205, 1475314, 54929102, 27983414, 44523583, 29294032, 3501931, 13372947, + 13208996, 17110041, + ]), + xy2d: FieldElement2625::from_limbs([ + 64000871, 2761261, 5801138, 5962570, 43035492, 15584129, 7363601, 16097392, + 1078139, 22776171, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 107709840, 7646719, 105182720, 41146601, 99677072, 23817494, 45078078, 22928132, + 97583560, 25997654, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 2781153, 29712397, 27020591, 19336993, 33059880, 4657864, 28164594, 23935349, + 24375165, 11676026, + ]), + xy2d: FieldElement2625::from_limbs([ + 56837570, 28337377, 2926746, 20505276, 37539773, 9598054, 11901939, 598381, + 36379162, 15296905, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 46995309, 40308926, 60473593, 15928239, 55901041, 44691821, 29475691, 55077638, + 82659815, 39314104, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 5369604, 25110572, 27571709, 11584708, 47374981, 17929736, 60715320, 718583, + 49513265, 6722706, + ]), + xy2d: FieldElement2625::from_limbs([ + 57733, 21623609, 44351609, 1972472, 13986911, 18533088, 47288033, 406994, 26790316, + 14261482, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 101772520, 36120786, 90638000, 13003754, 87427219, 22355445, 60959041, 52965400, + 27134134, 41129629, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 23373170, 29635630, 11272593, 28267438, 42719132, 12823366, 35648442, 24477254, + 46279733, 17904936, + ]), + xy2d: FieldElement2625::from_limbs([ + 11957902, 26975823, 46146194, 10657190, 19638080, 1803064, 20654157, 20548921, + 3185740, 33479098, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 50283917, 15871189, 62497439, 13345484, 82185757, 16442304, 71623347, 13685984, + 58414432, 33356771, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 19209683, 24356479, 65049682, 21531501, 56744610, 25436389, 38918410, 30035332, + 11608073, 13154738, + ]), + xy2d: FieldElement2625::from_limbs([ + 33828345, 13840682, 22225567, 10774340, 39885410, 4150556, 22366803, 4481197, + 19878688, 31424932, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 46553143, 38790856, 94244775, 65292104, 61802259, 23133297, 68375138, 27751434, + 88095999, 14030619, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 14243923, 22854008, 36070614, 1654216, 52834063, 24822185, 3574227, 15790094, + 64864551, 9134566, + ]), + xy2d: FieldElement2625::from_limbs([ + 44476109, 27292813, 23724837, 23969618, 27874245, 18745945, 663316, 7855995, + 39509344, 16080188, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 75359075, 25779128, 47994231, 30102561, 86558139, 18508086, 104463695, 12881720, + 52443094, 43071260, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 66651739, 8260339, 19961735, 25951458, 60005972, 6355401, 18584483, 29931146, + 57135727, 921837, + ]), + xy2d: FieldElement2625::from_limbs([ + 30104170, 27060986, 16307509, 33539099, 42057945, 27800295, 20081964, 12462670, + 44271889, 17833563, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 90350267, 7278379, 49908519, 52622428, 85665385, 24952565, 120391416, 28964002, + 20976802, 23040241, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 32647164, 1420817, 24190147, 10350549, 32809921, 6894923, 64824432, 28102545, + 58680763, 25605516, + ]), + xy2d: FieldElement2625::from_limbs([ + 57977988, 30968293, 7367972, 4138199, 7908177, 26571398, 63730661, 29575382, + 31018325, 15308767, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 62943393, 50029990, 93172148, 48106981, 84469370, 35613000, 80992021, 31643756, + 48788541, 3799579, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 56075958, 1393937, 12295232, 16431309, 26394598, 13665766, 46201697, 6415747, + 18650838, 32327878, + ]), + xy2d: FieldElement2625::from_limbs([ + 784807, 24480169, 66644888, 17875629, 66259715, 26389335, 64055900, 2647502, + 1306126, 23654251, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 104078590, 45063481, 74341733, 40717040, 109638725, 10680184, 122626222, 60499210, + 59697328, 12105459, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 43048526, 31748374, 44167750, 11763184, 49871390, 25959575, 59028581, 4677073, + 13708090, 9495219, + ]), + xy2d: FieldElement2625::from_limbs([ + 41785112, 17696151, 40615522, 3254808, 42342956, 5200193, 28013286, 9421228, + 27588636, 17339599, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 94795701, 52678334, 82607448, 43012809, 71791189, 39844037, 37189789, 44422485, + 60844240, 40135017, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 11527618, 23976286, 14247767, 26471047, 17758654, 29095438, 36970092, 28589382, + 12167163, 15585355, + ]), + xy2d: FieldElement2625::from_limbs([ + 15942866, 14798707, 63523191, 6188121, 33624216, 24668448, 9433873, 6436284, + 54116773, 18362830, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 82900214, 33835816, 65105805, 27938470, 91596138, 46311016, 68815245, 9811576, + 98564974, 17704095, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 11801582, 1314226, 66894287, 22980545, 27703601, 19047530, 41596360, 28685470, + 37715547, 4975180, + ]), + xy2d: FieldElement2625::from_limbs([ + 50423393, 21700483, 4699214, 26701965, 56496604, 31127464, 16228456, 23849659, + 53026774, 25950524, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 32369563, 24930592, 94725702, 42361613, 38680580, 7569249, 72180761, 30273244, + 63220873, 23227458, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 9088835, 2805536, 47737552, 33018644, 10510925, 30934313, 49432118, 8041469, + 19231146, 9809053, + ]), + xy2d: FieldElement2625::from_limbs([ + 34115736, 25175302, 17150343, 33247133, 27739793, 19098327, 4584842, 21379561, + 55354309, 7698262, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 90989856, 65809069, 120502104, 22957707, 29847549, 29359055, 50217410, 48434886, + 93137803, 53418300, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 25193315, 33523972, 66800639, 12860474, 56450712, 21553566, 49052401, 1719511, + 5659667, 22614350, + ]), + xy2d: FieldElement2625::from_limbs([ + 2911809, 16198940, 20998442, 3089175, 25152772, 27105195, 21966784, 7685256, + 28401885, 11652283, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 80771992, 42502959, 39447297, 30747045, 18608838, 27674829, 97864578, 22094529, + 86927109, 39237527, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 39769689, 14249923, 42962975, 15426006, 672629, 26455777, 42470727, 18725616, + 25194727, 25633950, + ]), + xy2d: FieldElement2625::from_limbs([ + 59183571, 3365425, 21068135, 32059424, 5589463, 2614683, 65101164, 11137009, + 54038242, 2461597, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 98338182, 9015296, 43474352, 30869681, 72577834, 14051401, 94071910, 59591187, + 92100521, 26964042, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 35427521, 26197936, 30354229, 23271699, 33288703, 9623615, 6691012, 2059119, + 40889003, 28755974, + ]), + xy2d: FieldElement2625::from_limbs([ + 27342920, 20751908, 14996450, 5797295, 30717687, 13054865, 226771, 27682349, + 48095984, 29346363, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 27379050, 37749095, 40022303, 40597831, 90970263, 37365456, 37970858, 24378738, + 65886055, 15142357, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 10217035, 21016207, 34195010, 14487849, 41232611, 28496955, 46022678, 15664757, + 21803752, 20094156, + ]), + xy2d: FieldElement2625::from_limbs([ + 53935798, 20699065, 42158539, 23200855, 22903705, 2311002, 16067670, 28061993, + 41744952, 10935798, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 54248761, 45696634, 30727738, 33003536, 102631462, 50311252, 67582762, 60004751, + 92888883, 35515158, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 11490309, 18528616, 57983294, 9643555, 16219067, 20786358, 63937207, 2914433, + 23306259, 6761912, + ]), + xy2d: FieldElement2625::from_limbs([ + 26379367, 13324915, 10844683, 1858502, 38003233, 5215061, 6869041, 4791630, + 30392263, 10697757, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 102505573, 8143772, 34028108, 30177714, 90825807, 28400103, 81499550, 16650363, + 58008365, 51960220, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 24113549, 28209454, 25784277, 11960072, 33833233, 13654592, 7723457, 19919661, + 17713746, 5191478, + ]), + xy2d: FieldElement2625::from_limbs([ + 4953861, 5794837, 8861628, 2147745, 30270316, 3207516, 53926061, 29539108, + 58093888, 26161321, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 66842784, 54187799, 92817031, 9770455, 57674931, 38293760, 21252864, 23644635, + 68693882, 36403139, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 33156288, 5814992, 41992705, 27855948, 41426696, 5903691, 10488928, 30508233, + 26522953, 12195090, + ]), + xy2d: FieldElement2625::from_limbs([ + 52552366, 7413773, 56691548, 17293291, 37436115, 18900414, 18728450, 20750426, + 10931351, 28017687, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 10232466, 55198051, 102647744, 55137680, 95295298, 50722936, 88706143, 7750869, + 63532952, 24985679, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 5707284, 3380857, 46030300, 23150779, 33460955, 3864642, 35206179, 29839964, + 44063029, 22086736, + ]), + xy2d: FieldElement2625::from_limbs([ + 842948, 26141409, 44216907, 4923146, 3726600, 28931331, 52882196, 9582183, + 36458817, 6599319, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 105094167, 13798314, 86987595, 39546785, 53945028, 34257279, 100672436, 43019368, + 81691601, 25161759, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 58944838, 30793517, 41293886, 20641791, 15327632, 17951896, 27404681, 2976412, + 34049395, 13945398, + ]), + xy2d: FieldElement2625::from_limbs([ + 32029034, 33353168, 58802940, 12319599, 24257359, 1780332, 53443432, 24095036, + 22515003, 31967896, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 58243953, 33967455, 45550831, 41334279, 122435196, 41337129, 42593362, 9819656, + 18554526, 27484534, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 43763452, 32991502, 22104074, 28927102, 7987515, 12405169, 7210918, 24891298, + 54452521, 11999455, + ]), + xy2d: FieldElement2625::from_limbs([ + 59281033, 19037506, 7123414, 12174108, 17334422, 9281553, 30699002, 2519320, + 64378107, 3278962, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 58145902, 8575052, 85562403, 44660441, 11144335, 42185320, 99129046, 8393160, + 82317049, 10140754, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 35697739, 6001093, 66722847, 27516266, 58767778, 9734277, 12081618, 32980146, + 37719008, 23969672, + ]), + xy2d: FieldElement2625::from_limbs([ + 44591363, 12242921, 51473547, 26008522, 12899284, 14371043, 32943275, 32223964, + 18950596, 27259362, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 86140977, 26826485, 42712265, 18544405, 21375347, 19234315, 62839893, 45416394, + 78199812, 29029380, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 41183857, 31117345, 63391660, 11439254, 10765209, 1575223, 25250311, 20821975, + 29077696, 21289615, + ]), + xy2d: FieldElement2625::from_limbs([ + 66255562, 24236975, 39294735, 25666746, 64333078, 5083371, 6484637, 8865543, + 15364200, 148821, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 52772590, 33690199, 12792611, 29791370, 54503025, 40769070, 74699612, 10513607, + 18827608, 48012340, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 1870952, 23378551, 11363387, 3148048, 49393637, 19366436, 42194490, 5710917, + 6687964, 169158, + ]), + xy2d: FieldElement2625::from_limbs([ + 66476906, 26650813, 39675811, 7513133, 40777681, 2510748, 57958980, 2727892, + 3378300, 14343225, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 52141093, 46319994, 65446821, 25180251, 85385079, 17099729, 28873832, 37720652, + 98637767, 28389711, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 51721811, 12335950, 59018551, 3985099, 44692799, 20663271, 59957201, 11244343, + 39478345, 6300998, + ]), + xy2d: FieldElement2625::from_limbs([ + 7428779, 5956366, 58457006, 19112672, 61412158, 9602768, 18921316, 23847081, + 59083739, 5882219, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 64976576, 22546711, 55250663, 30558214, 73845850, 54929748, 75993565, 42147497, + 43680828, 44130579, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 8698714, 17270076, 26019578, 30949157, 30061149, 25115415, 34398326, 25669598, + 26172027, 94156, + ]), + xy2d: FieldElement2625::from_limbs([ + 16812578, 932160, 17475210, 3542066, 28486877, 9649433, 18707028, 25902127, + 8293152, 4142649, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 71365237, 25998181, 71415223, 29425216, 44498257, 6586768, 74573845, 44266997, + 48241910, 15169928, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 17013933, 17212797, 35968333, 20882944, 4298970, 4155062, 15475151, 7562163, + 59210100, 14044241, + ]), + xy2d: FieldElement2625::from_limbs([ + 36138626, 11102269, 35681933, 15692178, 32663985, 19047540, 53036551, 3150389, + 50129717, 1527760, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 87084966, 20606529, 89395876, 41302439, 70282424, 59159062, 68747120, 28558053, + 57416882, 32107797, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 42244104, 24952545, 35301767, 4084322, 59332636, 4778779, 33379512, 18905452, + 47626353, 15990057, + ]), + xy2d: FieldElement2625::from_limbs([ + 54784856, 25661025, 66218717, 22082164, 47464083, 10571945, 29164007, 6332786, + 14568145, 7445860, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 82248917, 17401609, 101645640, 54662246, 61294654, 28674130, 90561077, 60301966, + 55825273, 30098173, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 50592072, 10213970, 61259718, 29405475, 7363183, 7596441, 40134051, 26972205, + 37799492, 15582323, + ]), + xy2d: FieldElement2625::from_limbs([ + 53713651, 4575382, 35359251, 19454133, 36072657, 1099894, 61954381, 13580095, + 16625112, 18141435, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 93652408, 46881170, 29635343, 39072408, 82010792, 35953836, 114266157, 49930412, + 45553469, 33423081, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 30442164, 21155251, 45105050, 21767823, 10714435, 1361568, 47399377, 14306779, + 31627351, 17934909, + ]), + xy2d: FieldElement2625::from_limbs([ + 20175779, 16011303, 45815298, 31190206, 24039076, 11158365, 49168181, 29512535, + 12114940, 24485800, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 69304392, 42471737, 54195250, 39300734, 57558018, 31135824, 60142524, 44133379, + 124856927, 29802650, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 23993165, 10490772, 30568031, 8364054, 43428543, 15952531, 14237198, 587376, + 59866535, 32331757, + ]), + xy2d: FieldElement2625::from_limbs([ + 57234974, 659782, 48314480, 19212804, 2923396, 8803287, 37926831, 6023544, + 57304674, 24381104, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 38193757, 12061190, 30629409, 34632439, 116329776, 29405843, 24192088, 35017815, + 111646203, 40207885, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 51391808, 10839243, 43685497, 8196682, 16569292, 5244981, 23306856, 9875215, + 49030136, 12239954, + ]), + xy2d: FieldElement2625::from_limbs([ + 52668909, 17095554, 7396123, 29694616, 59299050, 13005892, 32714158, 26712806, + 3889590, 23741773, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 56490873, 18205634, 120864811, 10603067, 21226381, 31182218, 88885574, 26589264, + 47569607, 33341490, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 39016960, 16975240, 2411072, 8304213, 11938115, 23469378, 38149461, 1544510, + 36594619, 20387425, + ]), + xy2d: FieldElement2625::from_limbs([ + 46268863, 3005513, 33179125, 25148215, 61554499, 27426156, 43008974, 7994625, + 10109463, 10837973, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 48833742, 42833901, 37121378, 43071628, 65064972, 46070195, 88470798, 47675439, + 77200202, 20662537, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 38935657, 11110238, 43741993, 21966133, 26032120, 25796314, 36047179, 15611858, + 52676039, 26536791, + ]), + xy2d: FieldElement2625::from_limbs([ + 16798883, 27361511, 30519922, 14850330, 61373012, 3905098, 44395806, 9455219, + 57736859, 4453716, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 72532086, 22731042, 98554024, 13816950, 104970318, 39423268, 80808680, 8547069, + 60471005, 32945262, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 35430437, 20821858, 56223625, 20738239, 43958773, 15909227, 26044112, 2092337, + 9926615, 5395656, + ]), + xy2d: FieldElement2625::from_limbs([ + 23557717, 21927777, 21390487, 31224749, 66915231, 24804490, 26724506, 21532347, + 17112260, 10443128, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 108365633, 12209673, 36704746, 49458270, 72737566, 32463785, 93558012, 44736180, + 61930565, 27094248, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 44500635, 22048620, 54380533, 13131957, 55724526, 21775618, 53827001, 25387743, + 6530484, 3937192, + ]), + xy2d: FieldElement2625::from_limbs([ + 26431571, 18672034, 59084918, 21743473, 21106478, 33005740, 22689506, 14090085, + 3719264, 1853939, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 38712807, 45765405, 116616213, 54507239, 85142463, 19977741, 65887619, 29357403, + 30963061, 29876053, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 18477271, 32934077, 56180796, 6569160, 18246501, 13599351, 55071120, 17332564, + 28766858, 2856869, + ]), + xy2d: FieldElement2625::from_limbs([ + 52990275, 28908529, 56393003, 3900290, 66400472, 32631651, 63471407, 1061910, + 30229766, 15340150, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 73673249, 14115827, 59173424, 53411052, 60174187, 23064925, 64442983, 44412407, + 12608150, 47381197, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 64030251, 20780798, 56807783, 366481, 29913015, 11995198, 3865826, 29603203, + 56318531, 17288546, + ]), + xy2d: FieldElement2625::from_limbs([ + 13830666, 3302361, 929055, 14504565, 2573746, 1270641, 28891673, 13567572, + 47282484, 6382988, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 92177929, 43037799, 88839246, 57074261, 75813605, 35192923, 28831092, 7128602, + 77988680, 44584700, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 33033322, 12259625, 14698428, 809029, 53073715, 4780051, 59871529, 661065, + 30515610, 30654028, + ]), + xy2d: FieldElement2625::from_limbs([ + 29173840, 19506002, 31974753, 4902710, 25243628, 17298474, 58000810, 25399779, + 27471618, 17977737, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 85361859, 25787010, 58173401, 31655993, 107585337, 34543142, 44918496, 41203798, + 68044845, 35625548, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 64782360, 15953591, 32938646, 18803730, 49898861, 18382621, 42882260, 23480136, + 51260411, 2169796, + ]), + xy2d: FieldElement2625::from_limbs([ + 50015595, 5921724, 53355427, 30162044, 24672572, 1399251, 805303, 14919738, + 25401049, 12772803, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 17425001, 40352395, 77244241, 56133123, 57106317, 19058256, 34741762, 53972869, + 83562056, 12039106, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 14817754, 9542259, 57761540, 23747206, 47099614, 13225331, 55444726, 32770616, + 22514517, 21542355, + ]), + xy2d: FieldElement2625::from_limbs([ + 21240431, 12773031, 16563615, 4446043, 48563754, 11502768, 3633017, 14242116, + 45622248, 21081013, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 32090817, 30127786, 81273876, 57048285, 61133580, 37891487, 86402056, 50794938, + 109743002, 26950008, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 51522874, 16213907, 28555325, 3463280, 27172004, 26155085, 47291612, 8212088, + 53308400, 15020549, + ]), + xy2d: FieldElement2625::from_limbs([ + 33881262, 24586722, 34508824, 199915, 43770467, 2682535, 26214544, 7866506, + 51870356, 18050447, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 87250926, 49886960, 78420604, 41435562, 60002880, 40385369, 72448508, 23781756, + 36003287, 44606358, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 24440657, 14434315, 4565748, 9108120, 40912290, 17501285, 56148631, 17268257, + 14785615, 19189748, + ]), + xy2d: FieldElement2625::from_limbs([ + 16757731, 13140446, 13347348, 25184760, 25899188, 33267487, 46495668, 6251761, + 43798011, 16342785, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 49631729, 29965402, 71000443, 53431863, 52486219, 36758719, 48047023, 27251121, + 72047108, 44200863, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 36530298, 31365791, 58300880, 10105707, 48515287, 19636716, 28880723, 14835227, + 60718108, 29597105, + ]), + xy2d: FieldElement2625::from_limbs([ + 27637508, 17321887, 46280601, 7004781, 31640645, 8683429, 48358703, 22311914, + 21535936, 24164111, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 49072063, 23425151, 59146321, 13686342, 71724674, 48501183, 46766198, 34599345, + 41392256, 46625920, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 49699511, 11702554, 11359056, 5626696, 28416700, 4633620, 12074530, 825817, + 36470334, 17101489, + ]), + xy2d: FieldElement2625::from_limbs([ + 62353170, 16993130, 22352153, 24764280, 23538971, 19460129, 35643077, 2228978, + 23705775, 33502453, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 116378079, 16835249, 79705512, 36640536, 72615427, 38652261, 54039027, 28469861, + 7654742, 36538300, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 51545051, 15960288, 39171656, 3921551, 29623090, 23910347, 53721413, 14757664, + 7462803, 2143562, + ]), + xy2d: FieldElement2625::from_limbs([ + 49303011, 25554059, 39712200, 6805176, 54723390, 22587343, 55546433, 21944529, + 24359345, 12667971, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 40624581, 37947525, 69893340, 47413706, 75866770, 36829289, 60701745, 41851961, + 61009017, 29297729, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 44943669, 9231716, 30864445, 29989047, 7347279, 19668663, 47292564, 7825963, + 55562255, 22733503, + ]), + xy2d: FieldElement2625::from_limbs([ + 13021548, 30198807, 15157252, 25752324, 54347976, 33239795, 27862109, 24283328, + 13344309, 28647349, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 69556589, 32138352, 59722077, 33563009, 7846747, 54947391, 110971242, 33977608, + 79294533, 48801604, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 43750523, 18043037, 50546441, 12101302, 63824276, 30118402, 47717109, 25808249, + 12719357, 6391399, + ]), + xy2d: FieldElement2625::from_limbs([ + 13619568, 8999236, 36589956, 30809580, 56123842, 11704013, 39860742, 27269550, + 2116555, 28568490, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 95255182, 27937031, 127009370, 37862584, 38689760, 40709673, 50098271, 55780713, + 51035924, 29789745, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 29985376, 31370396, 2747691, 7847854, 34243868, 8774272, 37339040, 26328869, + 51560033, 27228592, + ]), + xy2d: FieldElement2625::from_limbs([ + 30876475, 21537640, 4539980, 29553785, 855985, 27273299, 41341297, 3682654, + 43314878, 10814508, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 34169829, 48196523, 50056438, 35882871, 70320564, 56622897, 29434716, 21885563, + 89507810, 48584335, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 5081532, 14861685, 36155677, 15692063, 50820299, 4155562, 66935564, 8712250, + 28973640, 28997828, + ]), + xy2d: FieldElement2625::from_limbs([ + 35114172, 30087209, 41707345, 6647766, 63014516, 9247373, 23252128, 28071218, + 22767233, 480104, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 78982479, 34154848, 72823891, 34567153, 59035892, 10284055, 90407846, 27233563, + 93234373, 2887288, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 46466944, 2391816, 11852959, 12300167, 52148735, 2930553, 52378324, 7503278, + 15499851, 32203866, + ]), + xy2d: FieldElement2625::from_limbs([ + 21828848, 3391258, 51030616, 10876888, 35122819, 15430350, 25047117, 4572787, + 48142143, 17249585, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 85433874, 34154451, 68108678, 31204715, 50327085, 27146827, 108705542, 50688738, + 76948456, 35402092, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 47016842, 63515, 4215156, 3124182, 327530, 20078653, 66226358, 10746729, 41643300, + 1659641, + ]), + xy2d: FieldElement2625::from_limbs([ + 15253980, 14513491, 23436037, 18162975, 45293733, 16229423, 16336653, 28843675, + 13237657, 28057080, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement2625::from_limbs([ + 85599554, 15502924, 100973106, 35529510, 74403155, 41935868, 55268069, 32792709, + 75234901, 12056290, + ]), + y_minus_x: FieldElement2625::from_limbs([ + 51996126, 24896653, 58774089, 31366771, 53263657, 959406, 43648031, 12151798, + 14767999, 9940390, + ]), + xy2d: FieldElement2625::from_limbs([ + 38045873, 4834854, 7790538, 18120107, 56151073, 20062117, 44784044, 653149, + 26024782, 12810424, + ]), + }, + ]); diff --git a/curve25519-dalek/src/backend/serial/u32/constants.rs b/curve25519-dalek/src/backend/serial/u32/constants/mod.rs similarity index 98% rename from curve25519-dalek/src/backend/serial/u32/constants.rs rename to curve25519-dalek/src/backend/serial/u32/constants/mod.rs index 03e094e4..345c67f5 100644 --- a/curve25519-dalek/src/backend/serial/u32/constants.rs +++ b/curve25519-dalek/src/backend/serial/u32/constants/mod.rs @@ -24,6 +24,11 @@ use crate::{ window::{LookupTable, NafLookupTable8}, }; +#[cfg(feature = "precomputed-tables")] +mod affine_odd_multiples_of_b_shl_128; +#[cfg(feature = "precomputed-tables")] +pub(crate) use self::affine_odd_multiples_of_b_shl_128::AFFINE_ODD_MULTIPLES_OF_B_SHL_128; + /// The value of minus one, equal to `-&FieldElement::ONE` pub(crate) const MINUS_ONE: FieldElement2625 = FieldElement2625::from_limbs([ 67108844, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, @@ -127,6 +132,40 @@ pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint { ]), }; +/// `[2^128]B`, as an `EdwardsPoint`. +#[cfg(any(test, not(feature = "precomputed-tables")))] +pub(crate) const ED25519_BASEPOINT_SHL_128: EdwardsPoint = EdwardsPoint { + X: FieldElement2625::from_limbs([ + 2664042, 23449881, 8588504, 31570262, 52025907, 14016958, 17934911, 10536770, 36081707, + 18715816, + ]), + Y: FieldElement2625::from_limbs([ + 53612635, 17322216, 64979144, 12220533, 27384794, 7796776, 63981171, 31808137, 3318544, + 10876052, + ]), + Z: FieldElement2625::from_limbs([ + 38318927, 6633020, 30360108, 27133620, 43190211, 599215, 50990868, 21586734, 34463843, + 14390137, + ]), + T: FieldElement2625::from_limbs([ + 46012201, 27645749, 48994527, 27092089, 44549182, 4023192, 8388284, 20428666, 53367776, + 2097936, + ]), +}; + +#[test] +fn b_shl_128() { + let s = crate::Scalar { + bytes: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(s * ED25519_BASEPOINT_POINT, ED25519_BASEPOINT_SHL_128); +} + /// The 8-torsion subgroup \\(\mathcal E \[8\]\\). /// /// In the case of Curve25519, it is cyclic; the \\(i\\)-th element of @@ -4799,3 +4838,37 @@ pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8::from(&ED25519_BASEPOINT_SHL_128); + let mut table_file = File::create(format!( + "{}/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs", + env!("CARGO_MANIFEST_DIR") + )) + .expect("can open file"); + + let table_file_contents = format!( + "//! Generated file, do not alter! + + use super::super::field::FieldElement2625; + use crate::{{backend::serial::curve_models::AffineNielsPoint, window::NafLookupTable8}}; + + /// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. + pub(crate) const AFFINE_ODD_MULTIPLES_OF_B_SHL_128: NafLookupTable8 = + {:?}; + ", + table + ).replace("FieldElement2625(", "FieldElement2625::from_limbs("); + + write!(table_file, "{}", table_file_contents).unwrap(); + } +} diff --git a/curve25519-dalek/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs b/curve25519-dalek/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs new file mode 100644 index 00000000..d567306c --- /dev/null +++ b/curve25519-dalek/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs @@ -0,0 +1,1481 @@ +//! Generated file, do not alter! + +use super::super::field::FieldElement51; +use crate::{backend::serial::curve_models::AffineNielsPoint, window::NafLookupTable8}; + +/// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. +pub(crate) const AFFINE_ODD_MULTIPLES_OF_B_SHL_128: NafLookupTable8 = + NafLookupTable8([ + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 849646212451983, + 1410198775302919, + 2325567699868943, + 1641663456615811, + 3014056086137659, + ]), + y_minus_x: FieldElement51::from_limbs([ + 692017667358279, + 723305578826727, + 1638042139863265, + 748219305990306, + 334589200523901, + ]), + xy2d: FieldElement51::from_limbs([ + 22893968530686, + 2235758574399251, + 1661465835630252, + 925707319443452, + 1203475116966621, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2925523165433334, + 1979969272514922, + 3427087126180756, + 1187589090978665, + 1881897672213940, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1917185587363432, + 1098342571752737, + 5935801044414, + 2000527662351839, + 1538640296181569, + ]), + xy2d: FieldElement51::from_limbs([ + 2495540013192, + 678856913479236, + 224998292422872, + 219635787698590, + 1972465269000940, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1860190562533083, + 1936576191345085, + 2712900106391212, + 1811043097042829, + 3209286562992083, + ]), + y_minus_x: FieldElement51::from_limbs([ + 796664815624365, + 1543160838872951, + 1500897791837765, + 1667315977988401, + 599303877030711, + ]), + xy2d: FieldElement51::from_limbs([ + 1151480509533204, + 2136010406720455, + 738796060240027, + 319298003765044, + 1150614464349587, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 249079270936229, + 1501514259790706, + 3199709537890096, + 944551802437486, + 2804458577667728, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2089966982947227, + 1854140343916181, + 2151980759220007, + 2139781292261749, + 158070445864917, + ]), + xy2d: FieldElement51::from_limbs([ + 1338766321464554, + 1906702607371284, + 1519569445519894, + 115384726262267, + 1393058953390992, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2954349327665336, + 2875421537282295, + 1177907047549607, + 2315244756624323, + 3303388475971642, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1061970490698872, + 88020002043385, + 1253724453706413, + 1407465766145184, + 1123180624931792, + ]), + xy2d: FieldElement51::from_limbs([ + 1193532613439179, + 1341357357703238, + 1857522674746129, + 587336359047056, + 1462817734082691, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2235936902666817, + 1844821659342916, + 4255944160143733, + 2705728103151199, + 1360010073190141, + ]), + y_minus_x: FieldElement51::from_limbs([ + 595906005849110, + 1403147838510058, + 129240178387804, + 1265183719705065, + 904703029595594, + ]), + xy2d: FieldElement51::from_limbs([ + 1966276380904262, + 1243659846916250, + 1230287549611464, + 1790496592504769, + 385075881855087, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1475882426726637, + 2923995069592105, + 2595116660588037, + 2134573872614909, + 2857982748479313, + ]), + y_minus_x: FieldElement51::from_limbs([ + 764474518357447, + 851161390895817, + 1272140113873212, + 2119949599628057, + 851912892893979, + ]), + xy2d: FieldElement51::from_limbs([ + 957649428811476, + 1521919451665798, + 1487878569331559, + 1715152263604455, + 2000934618350472, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2307403528152576, + 3136574081495182, + 3694424861021853, + 1950918571001278, + 1747697954472435, + ]), + y_minus_x: FieldElement51::from_limbs([ + 156765656544824, + 129548313887055, + 2173751926124237, + 1932065820483601, + 280844677888288, + ]), + xy2d: FieldElement51::from_limbs([ + 931185174846608, + 872635055344100, + 1155298897916392, + 1344438153479985, + 863698029056587, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2237397044595632, + 2822021733991393, + 1089795682639006, + 1110175372515601, + 2274922806104413, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1002942064149278, + 1800468670264796, + 1256140115655805, + 591773871073386, + 1379246086803725, + ]), + xy2d: FieldElement51::from_limbs([ + 403410369385881, + 563695369463303, + 1986012995068505, + 494838082432751, + 1188545182143156, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 660109307750172, + 2400942845156742, + 1579013069809243, + 1556990956306632, + 2275718204658048, + ]), + y_minus_x: FieldElement51::from_limbs([ + 99006711679501, + 1877935179310798, + 1965889254023231, + 897443285004139, + 1148235427712420, + ]), + xy2d: FieldElement51::from_limbs([ + 185305152918375, + 400141305021618, + 1045833236654948, + 1080277697846289, + 1528482963157883, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 513162733127056, + 2761301755753984, + 1598365065343888, + 1538680937240126, + 1744673124188616, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1993965212168161, + 1297683660426543, + 312583994766376, + 1606274108998130, + 783564865269629, + ]), + xy2d: FieldElement51::from_limbs([ + 1901689236047298, + 1376085781293210, + 644114538090429, + 40156681051123, + 1026557953645082, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2705086279915373, + 1068926085284089, + 2999217393302385, + 3696197747458923, + 2638324941277671, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1685141966679812, + 777436621223421, + 1203244262154885, + 48223349535032, + 451153212179249, + ]), + xy2d: FieldElement51::from_limbs([ + 1451135835627909, + 132370399543417, + 1243734496078943, + 27312952282849, + 957071882766764, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2424025017019624, + 872667249313456, + 1500248605591699, + 3554447886264641, + 2760162706065590, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1988813486597490, + 1896995663643025, + 860561567635356, + 1642640745427898, + 1201579961232437, + ]), + xy2d: FieldElement51::from_limbs([ + 1810316848952974, + 715191960478354, + 121001596397376, + 1379014765389901, + 2246744237710412, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1065097514403213, + 895600333267615, + 1103424425168413, + 918450910585523, + 2238535066932576, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1634535655939539, + 1444954637374546, + 1707007226796706, + 2015637049301258, + 882799535005705, + ]), + xy2d: FieldElement51::from_limbs([ + 928832479833593, + 723053739975327, + 278539138013794, + 300728062397011, + 2108891507675936, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2603210326300727, + 4381679021854631, + 1552449344046867, + 1862367278486114, + 941578990402815, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1533706528970835, + 111012592641238, + 1665788690181903, + 1059655274367443, + 613010412257575, + ]), + xy2d: FieldElement51::from_limbs([ + 1831589720270541, + 1608573858218789, + 1258019101430725, + 527206900702996, + 1079123189095776, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1730008070349667, + 2020148720194935, + 1242056712832443, + 864477700029775, + 2890463382091734, + ]), + y_minus_x: FieldElement51::from_limbs([ + 554342033196635, + 1741572885485447, + 426503801380436, + 2008645224862627, + 61863490998895, + ]), + xy2d: FieldElement51::from_limbs([ + 1816032059284074, + 2250770849781045, + 1865646258372825, + 836355646188844, + 1196790198274321, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 488443836801723, + 3531431413910311, + 1674538376701545, + 1943741391505144, + 1546204420773026, + ]), + y_minus_x: FieldElement51::from_limbs([ + 95349447469052, + 694613609356483, + 462710482707393, + 1885929935283312, + 1718357149574587, + ]), + xy2d: FieldElement51::from_limbs([ + 2078247021227140, + 277709841263908, + 1783176342580049, + 1984770352116709, + 1027353993629013, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3357455857774753, + 3228404938551732, + 2389948058101370, + 2123576598845205, + 254985479156797, + ]), + y_minus_x: FieldElement51::from_limbs([ + 93545584633526, + 1102686493318208, + 917094058344422, + 430553539083105, + 2169487186761430, + ]), + xy2d: FieldElement51::from_limbs([ + 1642836332902823, + 1199613222120344, + 1770958359825155, + 177670915713628, + 1587409914686990, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3024159121874174, + 2732474374184293, + 716735125189701, + 4060033378623662, + 812383661385904, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2130597356035662, + 789413959430726, + 1742117638044190, + 313873114903653, + 637213374229306, + ]), + xy2d: FieldElement51::from_limbs([ + 1187568632567576, + 218426508033634, + 348979087153708, + 632247936578278, + 1163640818694172, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3535183246948277, + 2886540832046424, + 2673888132035157, + 2981142541596829, + 2693415458334928, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1609021327926722, + 1776441907308375, + 1952561809521086, + 1918600985452140, + 1045915481253883, + ]), + xy2d: FieldElement51::from_limbs([ + 993124431381714, + 415277834127735, + 1655471555547288, + 431931717055249, + 1232308715241893, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2270683257173238, + 1874919048703885, + 3107879766041962, + 658443788224909, + 1188101802163054, + ]), + y_minus_x: FieldElement51::from_limbs([ + 88196225700846, + 1542198335945167, + 1278258128009521, + 1925049346602440, + 333878715711067, + ]), + xy2d: FieldElement51::from_limbs([ + 1456294812804705, + 1791938542416974, + 2088928804737500, + 1600523538505832, + 1741510238871510, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1673063740337051, + 2842839820363334, + 507963740403716, + 2031603086615577, + 1558768383208585, + ]), + y_minus_x: FieldElement51::from_limbs([ + 188276342959939, + 2215843737397968, + 2075966614561357, + 539653898913334, + 658274422976938, + ]), + xy2d: FieldElement51::from_limbs([ + 1689485952192664, + 2231177344037255, + 1281667057010321, + 1434758056113546, + 516621672948677, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 4416371952477472, + 1540665757316952, + 1970252859011069, + 3250410227646914, + 3584841522949003, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2249755702881123, + 863051867442175, + 1446435385859736, + 115394478897905, + 1517623344258067, + ]), + xy2d: FieldElement51::from_limbs([ + 1087092464315969, + 207311045945642, + 1818998870101252, + 515748821675968, + 781971503538397, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2852325375900568, + 2063399300754177, + 1857226354193094, + 1482738839669634, + 2633185950066437, + ]), + y_minus_x: FieldElement51::from_limbs([ + 956296184387161, + 1035221781680159, + 1775417141379957, + 1256654859930951, + 1720265289527527, + ]), + xy2d: FieldElement51::from_limbs([ + 225849907810771, + 2151471546202471, + 175468411439575, + 747392087448940, + 165195032334050, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 605006371521926, + 2071629267426736, + 942973631296298, + 3999096958053478, + 1809526319568809, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1758113759532225, + 1561737313594165, + 645829903512063, + 138185143621828, + 1929780789242539, + ]), + xy2d: FieldElement51::from_limbs([ + 1392636999055432, + 389049896719330, + 876097190541047, + 1857730994468307, + 1969401131557616, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2533298909857130, + 2724474359296287, + 2507553395972247, + 1636029450904490, + 1016186442438503, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1410373787575883, + 972263122388546, + 1912398318741731, + 1051244093128726, + 1348496004002536, + ]), + xy2d: FieldElement51::from_limbs([ + 1389090791947958, + 1556983065037259, + 155088741825433, + 1883208487873622, + 733889022458424, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3066649250612537, + 2214829839670842, + 3376331070769190, + 4026850741795626, + 2383382001049395, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1243434382742533, + 647168078954814, + 1394948888296379, + 195584351771319, + 453784256094227, + ]), + xy2d: FieldElement51::from_limbs([ + 894219934925927, + 124721968806411, + 349976857403937, + 321560852877361, + 717914350010311, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 546519390100581, + 2025192138685004, + 1905898740638799, + 1117387027617182, + 3486991395398445, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1893104436113805, + 802626871062485, + 916344191336721, + 1336785828698561, + 348394208774738, + ]), + xy2d: FieldElement51::from_limbs([ + 388884933089029, + 144132735973308, + 215252785292140, + 1982336035379373, + 1755656591143232, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3636481700393120, + 655684228630151, + 2569850789563571, + 1586764615797504, + 2442973373017978, + ]), + y_minus_x: FieldElement51::from_limbs([ + 390237540445376, + 1869381067915777, + 396190037843720, + 2047372869766240, + 818398662800713, + ]), + xy2d: FieldElement51::from_limbs([ + 497529936536238, + 1160533170522972, + 1268385350105811, + 1392537535104514, + 1880235157408919, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3704278507856530, + 3700227171043264, + 3403958709000002, + 520152102308959, + 1676760597491608, + ]), + y_minus_x: FieldElement51::from_limbs([ + 226885478323732, + 1553622525435356, + 259351767847643, + 2002526121047075, + 1482215806490933, + ]), + xy2d: FieldElement51::from_limbs([ + 1754320262192324, + 330386779583051, + 1941548761144584, + 643049468652308, + 442872837722433, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 925989282749463, + 2653939903189835, + 2298967131366084, + 2886981017150388, + 1688577144423377, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2066518003379526, + 1385247186229310, + 1204731362533776, + 199743655520649, + 935859851857267, + ]), + xy2d: FieldElement51::from_limbs([ + 2238293247310186, + 826754352628476, + 119476082320207, + 1616990547442536, + 2145329207545147, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2279517376265073, + 2773896553499887, + 2774087890646652, + 658986001624146, + 1844455872863902, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2214022264637180, + 1941264976136202, + 832496807305531, + 1670426739476390, + 805269848121641, + ]), + xy2d: FieldElement51::from_limbs([ + 1277585460334217, + 816990565216726, + 622874495320214, + 169068733951482, + 220047479297275, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 575462056606830, + 2997111546811427, + 2831008913820815, + 563255532099286, + 680534563360505, + ]), + y_minus_x: FieldElement51::from_limbs([ + 402726569686091, + 1846585419504671, + 653256330099106, + 2213260144695762, + 1608577496091616, + ]), + xy2d: FieldElement51::from_limbs([ + 821608564943107, + 1745402417212555, + 964424383124436, + 2162513650560171, + 1829344836135364, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1800295019604017, + 1244493995818185, + 1290793050843507, + 3047842671156309, + 1948128792624132, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2088249714829937, + 767675404339116, + 105711436841881, + 1397339113736711, + 1428721906725056, + ]), + xy2d: FieldElement51::from_limbs([ + 1626515925301962, + 1722466205931279, + 341139317433622, + 594956525957789, + 9987223613544, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2260911035596526, + 1999265010496291, + 2735966028539505, + 705556297012060, + 3222053614209368, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1568908001447016, + 211261936460859, + 1299659569082341, + 383253194462778, + 11352007904476, + ]), + xy2d: FieldElement51::from_limbs([ + 1788505851583338, + 504197860386723, + 168493486847953, + 183065791193668, + 962557539224700, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3108482229967909, + 1689818105291685, + 1147543473282935, + 2531390133933160, + 1905201353136071, + ]), + y_minus_x: FieldElement51::from_limbs([ + 827851642582611, + 267435525836087, + 1386688688026943, + 754595145113553, + 422852857324617, + ]), + xy2d: FieldElement51::from_limbs([ + 399724963257003, + 1282629764381614, + 644430913147710, + 1600350534547300, + 394749093972955, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1513084227122880, + 2050727082659559, + 3686273061932122, + 2828470720106973, + 2961553068033084, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1158975190252378, + 2076962794047226, + 1685466999599709, + 1722657595514998, + 6318728370811, + ]), + xy2d: FieldElement51::from_limbs([ + 62556215478818, + 237704042948234, + 647562515360989, + 1738262336860756, + 278008476633888, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1744708464341621, + 1974692890129847, + 442030562409809, + 2970707955935253, + 1018036683283702, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1155131269946541, + 1401430684783949, + 278841494968538, + 507488183787983, + 942493118462324, + ]), + xy2d: FieldElement51::from_limbs([ + 745060696551042, + 1053084274947725, + 1278258804058545, + 211419079984647, + 102526288194357, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1382880839258022, + 2771759851115172, + 3970097516407992, + 1916498563628912, + 2154717839629490, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1674536991102984, + 274094244931975, + 320698489329692, + 1268723440506040, + 1073074608191601, + ]), + xy2d: FieldElement51::from_limbs([ + 1722082291610456, + 1481909006920413, + 709471266684563, + 424986103579111, + 499683220671185, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1167802294011093, + 3668321334394184, + 1924288351782974, + 4046796525787701, + 2019854254330745, + ]), + y_minus_x: FieldElement51::from_limbs([ + 685447974222152, + 1973368083890118, + 509788533316207, + 1810074077259171, + 1045712032810564, + ]), + xy2d: FieldElement51::from_limbs([ + 307048742099699, + 1305544801094163, + 73812672933073, + 911344810416461, + 1217451110804952, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3146142155343288, + 2622104944259855, + 2412821172413096, + 3350773342638125, + 2242985042843453, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1419704892687028, + 1460813918388122, + 91373292453187, + 960111733588433, + 1203591400560727, + ]), + xy2d: FieldElement51::from_limbs([ + 1074500375665571, + 2093139338401282, + 748825223286436, + 1980552746778421, + 1643214234246140, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2850230091481160, + 2637427667301426, + 2089489835901954, + 2961740989313980, + 2000022110546527, + ]), + y_minus_x: FieldElement51::from_limbs([ + 704023815396173, + 561302192942687, + 1070556276763327, + 39418150338062, + 2169747543260583, + ]), + xy2d: FieldElement51::from_limbs([ + 44277277742622, + 1289349499009136, + 590778592959364, + 404233233020847, + 1636188249810530, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 809412797581917, + 2324143669468705, + 1973392835022128, + 2350005808604248, + 2698305597838843, + ]), + y_minus_x: FieldElement51::from_limbs([ + 727409335741760, + 550070061274745, + 351984733180876, + 662714483712616, + 821409457382392, + ]), + xy2d: FieldElement51::from_limbs([ + 1147263261059565, + 1992771954072347, + 872810696725738, + 1792666097626542, + 1593283419265462, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1221759472630649, + 711559902150699, + 2092603248206733, + 1784375390521670, + 2237509565536967, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1139189111544320, + 557286303255104, + 1575003308304707, + 103650349686101, + 1368176968229819, + ]), + xy2d: FieldElement51::from_limbs([ + 201696609436095, + 1687668173456885, + 1840538234601283, + 536510244864974, + 727324066202135, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2874534485632206, + 2890488062831970, + 3091718515773452, + 3199444640462094, + 1386639462628170, + ]), + y_minus_x: FieldElement51::from_limbs([ + 745595489885289, + 1474122275844905, + 1731161353959416, + 1047694091356491, + 1780853950891463, + ]), + xy2d: FieldElement51::from_limbs([ + 1836199937332387, + 996588806845042, + 262066751961684, + 634529050357022, + 298883879075483, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1525454478688374, + 927239916998824, + 2645650835617870, + 573584171928296, + 2210919167473373, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1397331272179749, + 1391719716874121, + 1067650195046901, + 140414385219280, + 362096354621399, + ]), + xy2d: FieldElement51::from_limbs([ + 1471548228073045, + 2095457455465623, + 1664601212914591, + 1445011373148314, + 700826473798852, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 819377393207105, + 3319088351810026, + 2178607805227806, + 3002194313057532, + 1818264266144837, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1479657885468315, + 881270770747381, + 1461337042602478, + 1703742646080953, + 264220489000372, + ]), + xy2d: FieldElement51::from_limbs([ + 1253059016740947, + 1459179831529590, + 2214977737985838, + 945569620702946, + 124415743934560, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3071264378762727, + 3657919005682709, + 1340683588938687, + 1970142031207811, + 2004948008596853, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2210168512835799, + 440848921215036, + 912637014993765, + 1163168735318416, + 191721261953674, + ]), + xy2d: FieldElement51::from_limbs([ + 1940018594091331, + 261744087563563, + 2189873095454936, + 71263637241647, + 1029460070319366, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 947297188063777, + 3584355083938352, + 1547860975169387, + 2980466245718631, + 3179698318238358, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1394575810823723, + 24594180395367, + 804984141148087, + 1986637327957218, + 1160214738590275, + ]), + xy2d: FieldElement51::from_limbs([ + 221617709058570, + 973384880893215, + 85271276635570, + 910504373049881, + 428355120888116, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2888217892128265, + 3830188908188750, + 2361757159183077, + 478392410959220, + 2992028646769480, + ]), + y_minus_x: FieldElement51::from_limbs([ + 822729539849322, + 54293031831484, + 320783845545779, + 44363381051689, + 2057157026619802, + ]), + xy2d: FieldElement51::from_limbs([ + 1309025664575568, + 329015330596193, + 1160880964317164, + 1704550372541866, + 1206465534832386, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1730537032418499, + 2124397787195353, + 2318151126196025, + 2765140121183968, + 2390790123702317, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1070627433512984, + 1261896992201366, + 1233636862551405, + 1575725296407764, + 145612595932155, + ]), + xy2d: FieldElement51::from_limbs([ + 397400220577131, + 2024140562113443, + 93902169733436, + 1001246669162935, + 857168324826841, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2708003405554281, + 3767030194546513, + 1278977967087501, + 3622057960152578, + 807930810797640, + ]), + y_minus_x: FieldElement51::from_limbs([ + 640370176301530, + 1593648075595524, + 887536986533598, + 2199198867784950, + 1445682994449237, + ]), + xy2d: FieldElement51::from_limbs([ + 857183621487215, + 298368911588767, + 771937741899306, + 955772229349241, + 1414722880021480, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2021841525385921, + 3828445680772116, + 2542854708974348, + 3408790672532488, + 1808584531413914, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1088096931294522, + 232416815069245, + 1755238069345444, + 551103944039644, + 1008012033354736, + ]), + xy2d: FieldElement51::from_limbs([ + 1649987016785070, + 13416103055384, + 180021920260707, + 527912307523728, + 1211345044732564, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3347857301264366, + 2780693573442172, + 2710216295813696, + 1595966701533692, + 2993482048560599, + ]), + y_minus_x: FieldElement51::from_limbs([ + 968670506708817, + 611235590941428, + 1174491395802530, + 1158853166678679, + 1287802203511887, + ]), + xy2d: FieldElement51::from_limbs([ + 881840420271075, + 1690120647059988, + 2232543286603956, + 419548625205172, + 1096745779744251, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2010944137155057, + 3585751698334075, + 2466835926671435, + 1828791821083567, + 2966269775796740, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2104922639001722, + 678182574987728, + 1317797751965911, + 995575260032851, + 1986228154956828, + ]), + xy2d: FieldElement51::from_limbs([ + 1162452186543876, + 470082941759385, + 582735087455301, + 1497327250564399, + 1621626060315840, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1572035321710527, + 918474923081809, + 3254859365510786, + 2321922784860278, + 3129012565547136, + ]), + y_minus_x: FieldElement51::from_limbs([ + 785345154538167, + 377601187992400, + 310957002824380, + 55419652816418, + 1147661535968830, + ]), + xy2d: FieldElement51::from_limbs([ + 1140389712457490, + 1661902720930073, + 1305947174022427, + 149584217104069, + 2248311585749167, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1129794551925215, + 2458904827016616, + 2593909399356931, + 1910580083986931, + 2452043813145942, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1071076848337883, + 263170871899720, + 1604596254638898, + 990370120055109, + 143852018196371, + ]), + xy2d: FieldElement51::from_limbs([ + 1714903919381987, + 456687670392264, + 1515810984231742, + 1472672467751489, + 850133167354289, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2546615334986181, + 3181880017583324, + 2471571822584466, + 2808637619584049, + 1966137371978873, + ]), + y_minus_x: FieldElement51::from_limbs([ + 619530018474293, + 2012530907477053, + 1319941637676111, + 525191533928596, + 1525619616632847, + ]), + xy2d: FieldElement51::from_limbs([ + 2026607644946796, + 1728209224157188, + 2230684936390856, + 1629626584081501, + 1922491061345845, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2156768363108717, + 2252375466133853, + 3687456997620571, + 2280198785288554, + 3275020285112389, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1210847759930491, + 812104680687369, + 2021211807539604, + 1731962319936245, + 428919538980093, + ]), + xy2d: FieldElement51::from_limbs([ + 603928518447472, + 2067595950707076, + 785443072795074, + 1830028562151942, + 1917198912211915, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1874822509197966, + 2540915127353946, + 2731979947531232, + 3743380332638303, + 1999155996835604, + ]), + y_minus_x: FieldElement51::from_limbs([ + 2105231668775520, + 526660569525547, + 588831460590876, + 1766900526333856, + 1827279928999521, + ]), + xy2d: FieldElement51::from_limbs([ + 1445366584517435, + 1983320942790220, + 1830280114278321, + 247138767786353, + 725749389913790, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 3234413941449701, + 2408058759924982, + 3799898364379572, + 1468715300365148, + 3260439619553250, + ]), + y_minus_x: FieldElement51::from_limbs([ + 997350802557372, + 1053076557902109, + 278875095921867, + 584669267319564, + 1946011324521032, + ]), + xy2d: FieldElement51::from_limbs([ + 2019118452034748, + 446124066105169, + 620580760028788, + 1883827574328480, + 32219256809089, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2292093128355151, + 2319762442368083, + 690151307399412, + 1827613566010278, + 193762710955205, + ]), + y_minus_x: FieldElement51::from_limbs([ + 160512101123968, + 825450246233247, + 196666134870527, + 503536515234516, + 2161164879168075, + ]), + xy2d: FieldElement51::from_limbs([ + 227583493739760, + 729935648565848, + 1035513294745219, + 306874565931085, + 1157600101963583, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 2292066492587538, + 2094113043202438, + 1821792771501613, + 3401663733479174, + 2375794254291944, + ]), + y_minus_x: FieldElement51::from_limbs([ + 4262466513802, + 209660309164404, + 1347455593807722, + 721200841132214, + 111376663801124, + ]), + xy2d: FieldElement51::from_limbs([ + 973983908938204, + 1218896642546437, + 1089138186199205, + 1935666279171853, + 1882878779194777, + ]), + }, + AffineNielsPoint { + y_plus_x: FieldElement51::from_limbs([ + 1040383703917890, + 2384345155549746, + 2814268536737107, + 2200681503740645, + 809084001189461, + ]), + y_minus_x: FieldElement51::from_limbs([ + 1670786152228318, + 2104988427932233, + 64384700038441, + 815493402985503, + 667088295384959, + ]), + xy2d: FieldElement51::from_limbs([ + 324461597591729, + 1216019804118986, + 1346345937456161, + 43832132196780, + 859693028023118, + ]), + }, + ]); diff --git a/curve25519-dalek/src/backend/serial/u64/constants.rs b/curve25519-dalek/src/backend/serial/u64/constants/mod.rs similarity index 98% rename from curve25519-dalek/src/backend/serial/u64/constants.rs rename to curve25519-dalek/src/backend/serial/u64/constants/mod.rs index baeb1dd5..70395bc6 100644 --- a/curve25519-dalek/src/backend/serial/u64/constants.rs +++ b/curve25519-dalek/src/backend/serial/u64/constants/mod.rs @@ -22,6 +22,11 @@ use crate::{ window::{LookupTable, NafLookupTable8}, }; +#[cfg(feature = "precomputed-tables")] +mod affine_odd_multiples_of_b_shl_128; +#[cfg(feature = "precomputed-tables")] +pub(crate) use self::affine_odd_multiples_of_b_shl_128::AFFINE_ODD_MULTIPLES_OF_B_SHL_128; + /// The value of minus one, equal to `-&FieldElement::ONE` pub(crate) const MINUS_ONE: FieldElement51 = FieldElement51::from_limbs([ 2251799813685228, @@ -173,6 +178,52 @@ pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint { ]), }; +/// `[2^128]B`, as an `EdwardsPoint`. +#[cfg(any(test, not(feature = "precomputed-tables")))] +pub(crate) const ED25519_BASEPOINT_SHL_128: EdwardsPoint = EdwardsPoint { + X: FieldElement51::from_limbs([ + 1573694877509226, + 2118644427590872, + 940662180141619, + 707110682864191, + 1255997186674731, + ]), + Y: FieldElement51::from_limbs([ + 1162474291335259, + 820106152083656, + 523232807607258, + 2134608004007539, + 729879497843472, + ]), + Z: FieldElement51::from_limbs([ + 445134475408207, + 1820906444767788, + 40212681131971, + 1448661247201044, + 965705781338211, + ]), + T: FieldElement51::from_limbs([ + 1855274855831337, + 1818119365171423, + 269991889323070, + 1370944576683708, + 140790155072480, + ]), +}; + +#[test] +fn b_shl_128() { + let s = crate::Scalar { + bytes: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(s * ED25519_BASEPOINT_POINT, ED25519_BASEPOINT_SHL_128); +} + /// The 8-torsion subgroup \\(\mathcal E \[8\]\\). /// /// In the case of Curve25519, it is cyclic; the \\(i\\)-th element of @@ -7767,3 +7818,37 @@ pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8::from(&ED25519_BASEPOINT_SHL_128); + let mut table_file = File::create(format!( + "{}/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs", + env!("CARGO_MANIFEST_DIR") + )) + .expect("can open file"); + + let table_file_contents = format!( + "//! Generated file, do not alter! + + use super::super::field::FieldElement51; + use crate::{{backend::serial::curve_models::AffineNielsPoint, window::NafLookupTable8}}; + + /// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. + pub(crate) const AFFINE_ODD_MULTIPLES_OF_B_SHL_128: NafLookupTable8 = + {:?}; + ", + table + ).replace("FieldElement51(", "FieldElement51::from_limbs("); + + write!(table_file, "{}", table_file_contents).unwrap(); + } +} From 1c2e3a1cc5fd2efe78e73fd92dae8e17c03231b8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 5 May 2020 01:55:44 +1200 Subject: [PATCH 3/5] EdwardsPoint::vartime_check_double_scalar_mul_basepoint Checks whether [8a]A + [8b]B = [8]C in variable time. This can be used to implement RFC 8032-compatible Ed25519 signature validation. Note that it includes a multiplication by the cofactor. --- curve25519-dalek/CHANGELOG.md | 4 ++++ curve25519-dalek/benches/dalek_benchmarks.rs | 19 +++++++++++++++++++ curve25519-dalek/src/backend/mod.rs | 18 ++++++++++++++++++ curve25519-dalek/src/edwards.rs | 17 +++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index a4c8452c..15e56985 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -5,6 +5,10 @@ major series. ## 4.x series +### Unreleased + +* Add `EdwardsPoint::vartime_check_double_scalar_mul_basepoint`. + ### 4.1.2 * Fix nightly SIMD build diff --git a/curve25519-dalek/benches/dalek_benchmarks.rs b/curve25519-dalek/benches/dalek_benchmarks.rs index 62a6280f..80bc0acc 100644 --- a/curve25519-dalek/benches/dalek_benchmarks.rs +++ b/curve25519-dalek/benches/dalek_benchmarks.rs @@ -56,6 +56,24 @@ mod edwards_benches { }); } + fn vartime_check_double_scalar_mul_basepoint(c: &mut BenchmarkGroup) { + c.bench_function( + "Variable-time 8(aA+bB)=8C, A&C variable, B fixed", + |bench| { + let mut rng = thread_rng(); + let A = &Scalar::random(&mut rng) * constants::ED25519_BASEPOINT_TABLE; + let C = &Scalar::random(&mut rng) * constants::ED25519_BASEPOINT_TABLE; + bench.iter_batched( + || (Scalar::random(&mut rng), Scalar::random(&mut rng)), + |(a, b)| { + EdwardsPoint::vartime_check_double_scalar_mul_basepoint(&a, &A, &b, &C) + }, + BatchSize::SmallInput, + ); + }, + ); + } + pub(crate) fn edwards_benches() { let mut c = Criterion::default(); let mut g = c.benchmark_group("edwards benches"); @@ -65,6 +83,7 @@ mod edwards_benches { consttime_fixed_base_scalar_mul(&mut g); consttime_variable_base_scalar_mul(&mut g); vartime_double_base_scalar_mul(&mut g); + vartime_check_double_scalar_mul_basepoint(&mut g); } } diff --git a/curve25519-dalek/src/backend/mod.rs b/curve25519-dalek/src/backend/mod.rs index 9ad1dd3d..a8af946d 100644 --- a/curve25519-dalek/src/backend/mod.rs +++ b/curve25519-dalek/src/backend/mod.rs @@ -249,3 +249,21 @@ pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> Edwa BackendKind::Serial => serial::scalar_mul::vartime_double_base::mul(a, A, b), } } + +/// Computes \\([δa]A + [δb]B - [δ]C\\) in variable time. +/// +/// - \\(B\\) is the Ed25519 basepoint. +/// - \\(δ\\) is a value invertible \\( \mod \ell \\), which is selected internally to +/// this function. +/// +/// This corresponds to the signature verification optimisation presented in +/// [Antipa et al 2005](http://cacr.uwaterloo.ca/techreports/2005/cacr2005-28.pdf). +#[allow(non_snake_case)] +pub fn scalar_mul_abglsv_pornin( + a: &Scalar, + A: &EdwardsPoint, + b: &Scalar, + C: &EdwardsPoint, +) -> EdwardsPoint { + serial::scalar_mul::abglsv_pornin::mul(a, A, b, C) +} diff --git a/curve25519-dalek/src/edwards.rs b/curve25519-dalek/src/edwards.rs index 856fac12..99c4b6f4 100644 --- a/curve25519-dalek/src/edwards.rs +++ b/curve25519-dalek/src/edwards.rs @@ -906,6 +906,23 @@ impl EdwardsPoint { ) -> EdwardsPoint { crate::backend::vartime_double_base_mul(a, A, b) } + + /// Checks whether \\([8a]A + [8b]B = [8]C\\) in variable time. + /// + /// This can be used to implement [RFC 8032]-compatible Ed25519 signature validation. + /// Note that it includes a multiplication by the cofactor. + /// + /// [RFC 8032]: https://tools.ietf.org/html/rfc8032 + pub fn vartime_check_double_scalar_mul_basepoint( + a: &Scalar, + A: &EdwardsPoint, + b: &Scalar, + C: &EdwardsPoint, + ) -> bool { + crate::backend::scalar_mul_abglsv_pornin(a, A, b, C) + .mul_by_cofactor() + .is_identity() + } } #[cfg(feature = "precomputed-tables")] From 8768bc9ede3d32909d6f685451485a800b240d16 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 5 May 2020 17:51:14 +1200 Subject: [PATCH 4/5] RistrettoPoint::vartime_check_double_scalar_mul_basepoint Checks whether [a]A + [b]B = C in variable time. --- curve25519-dalek/CHANGELOG.md | 1 + curve25519-dalek/src/ristretto.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index 15e56985..93d31f3f 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -8,6 +8,7 @@ major series. ### Unreleased * Add `EdwardsPoint::vartime_check_double_scalar_mul_basepoint`. +* Add `RistrettoPoint::vartime_check_double_scalar_mul_basepoint`. ### 4.1.2 diff --git a/curve25519-dalek/src/ristretto.rs b/curve25519-dalek/src/ristretto.rs index c9d16aba..50a2c77b 100644 --- a/curve25519-dalek/src/ristretto.rs +++ b/curve25519-dalek/src/ristretto.rs @@ -1062,6 +1062,18 @@ impl RistrettoPoint { a, &A.0, b, )) } + + /// Checks whether \\([a]A + [b]B = C\\) in variable time. + pub fn vartime_check_double_scalar_mul_basepoint( + a: &Scalar, + A: &RistrettoPoint, + b: &Scalar, + C: &RistrettoPoint, + ) -> bool { + use crate::traits::IsIdentity; + + crate::backend::scalar_mul_abglsv_pornin(a, &A.0, b, &C.0).is_identity() + } } /// A precomputed table of multiples of a basepoint, used to accelerate From 01a9e9e7a6ffa813977f3a61b898b2ec407d7a17 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 5 May 2020 18:42:34 +1200 Subject: [PATCH 5/5] =?UTF-8?q?Add=20vector=20backend=20for=20computing=20?= =?UTF-8?q?=CE=B4(aA=20+=20bB=20-=20C)=20in=20variable=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 2 + curve25519-dalek/src/backend/mod.rs | 10 +- .../src/backend/vector/avx2/constants.rs | 65 + .../constants/b_shl_128_odd_lookup_table.rs | 1101 +++++++++ .../src/backend/vector/ifma/constants.rs | 61 + .../constants/b_shl_128_odd_lookup_table.rs | 2036 +++++++++++++++++ .../src/backend/vector/ifma/edwards.rs | 21 + .../vector/scalar_mul/abglsv_pornin.rs | 213 ++ .../src/backend/vector/scalar_mul/mod.rs | 2 + 9 files changed, 3510 insertions(+), 1 deletion(-) create mode 100644 curve25519-dalek/src/backend/vector/avx2/constants/b_shl_128_odd_lookup_table.rs create mode 100644 curve25519-dalek/src/backend/vector/ifma/constants/b_shl_128_odd_lookup_table.rs create mode 100644 curve25519-dalek/src/backend/vector/scalar_mul/abglsv_pornin.rs diff --git a/.gitattributes b/.gitattributes index 64fc4e12..d80d9f5d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,4 @@ curve25519-dalek/src/backend/serial/u32/constants/affine_odd_multiples_of_b_shl_128.rs linguist-generated=true curve25519-dalek/src/backend/serial/u64/constants/affine_odd_multiples_of_b_shl_128.rs linguist-generated=true +curve25519-dalek/src/backend/vector/avx2/constants/b_shl_128_odd_lookup_table.rs linguist-generated=true +curve25519-dalek/src/backend/vector/ifma/constants/b_shl_128_odd_lookup_table.rs linguist-generated=true diff --git a/curve25519-dalek/src/backend/mod.rs b/curve25519-dalek/src/backend/mod.rs index a8af946d..59cee206 100644 --- a/curve25519-dalek/src/backend/mod.rs +++ b/curve25519-dalek/src/backend/mod.rs @@ -265,5 +265,13 @@ pub fn scalar_mul_abglsv_pornin( b: &Scalar, C: &EdwardsPoint, ) -> EdwardsPoint { - serial::scalar_mul::abglsv_pornin::mul(a, A, b, C) + match get_selected_backend() { + #[cfg(curve25519_dalek_backend = "simd")] + BackendKind::Avx2 => vector::scalar_mul::abglsv_pornin::spec_avx2::mul(a, A, b, C), + #[cfg(all(curve25519_dalek_backend = "simd", nightly))] + BackendKind::Avx512 => { + vector::scalar_mul::abglsv_pornin::spec_avx512ifma_avx512vl::mul(a, A, b, C) + } + BackendKind::Serial => serial::scalar_mul::abglsv_pornin::mul(a, A, b, C), + } } diff --git a/curve25519-dalek/src/backend/vector/avx2/constants.rs b/curve25519-dalek/src/backend/vector/avx2/constants.rs index 25c7bde2..4d86d2d1 100644 --- a/curve25519-dalek/src/backend/vector/avx2/constants.rs +++ b/curve25519-dalek/src/backend/vector/avx2/constants.rs @@ -19,6 +19,11 @@ use crate::backend::vector::avx2::field::FieldElement2625x4; #[cfg(feature = "precomputed-tables")] use crate::window::NafLookupTable8; +#[cfg(feature = "precomputed-tables")] +mod b_shl_128_odd_lookup_table; +#[cfg(feature = "precomputed-tables")] +pub(crate) use b_shl_128_odd_lookup_table::B_SHL_128_ODD_LOOKUP_TABLE; + /// The identity element as an `ExtendedPoint`. pub(crate) static EXTENDEDPOINT_IDENTITY: ExtendedPoint = ExtendedPoint(FieldElement2625x4([ u32x8::new_const(0, 1, 0, 0, 1, 0, 0, 0), @@ -1189,3 +1194,63 @@ pub(crate) static BASEPOINT_ODD_LOOKUP_TABLE: NafLookupTable8 = Naf ), ])), ]); + +#[cfg(all(test, feature = "precomputed-tables", curve25519_dalek_generate_tables))] +mod table_generators { + use std::fs::File; + use std::io::Write; + + use crate::{ + backend::vector::avx2::edwards::CachedPoint, constants::ED25519_BASEPOINT_SHL_128, + window::NafLookupTable8, + }; + + #[test] + fn b_shl_128_odd_lookup_table() { + let table = NafLookupTable8::::from(&ED25519_BASEPOINT_SHL_128); + let mut table_file = File::create(format!( + "{}/src/backend/vector/avx2/constants/b_shl_128_odd_lookup_table.rs", + env!("CARGO_MANIFEST_DIR") + )) + .expect("can open file"); + + writeln!( + table_file, + "//! Generated file, do not alter! + + use crate::{{ + backend::vector::{{ + avx2::{{edwards::CachedPoint, field::FieldElement2625x4}}, + packed_simd::u32x8, + }}, + window::NafLookupTable8, + }}; + + /// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. + pub(crate) static B_SHL_128_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([", + ) + .expect("can write file"); + + for row in table.0 { + writeln!(table_file, "CachedPoint(FieldElement2625x4([").expect("can write file"); + for vector in row.0 .0 { + writeln!( + table_file, + "u32x8::new_const({}, {}, {}, {}, {}, {}, {}, {}),", + vector.extract::<0>(), + vector.extract::<1>(), + vector.extract::<2>(), + vector.extract::<3>(), + vector.extract::<4>(), + vector.extract::<5>(), + vector.extract::<6>(), + vector.extract::<7>(), + ) + .expect("can write file"); + } + writeln!(table_file, "])),").expect("can write file"); + } + + writeln!(table_file, "]);").expect("can write file"); + } +} diff --git a/curve25519-dalek/src/backend/vector/avx2/constants/b_shl_128_odd_lookup_table.rs b/curve25519-dalek/src/backend/vector/avx2/constants/b_shl_128_odd_lookup_table.rs new file mode 100644 index 00000000..7e48dae9 --- /dev/null +++ b/curve25519-dalek/src/backend/vector/avx2/constants/b_shl_128_odd_lookup_table.rs @@ -0,0 +1,1101 @@ +//! Generated file, do not alter! + +use crate::{ + backend::vector::{ + avx2::{edwards::CachedPoint, field::FieldElement2625x4}, + packed_simd::u32x8, + }, + window::NafLookupTable8, +}; + +/// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. +pub(crate) static B_SHL_128_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([ + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 66534737, 44155216, 17527085, 25046477, 50454485, 25275908, 24427949, 19365218, + ), + u32x8::new_const( + 15981845, 36873404, 8477272, 11176021, 40772245, 51234208, 6101715, 20397724, + ), + u32x8::new_const( + 35665917, 53574296, 1951442, 2105772, 44081965, 9258257, 14333944, 20637141, + ), + u32x8::new_const( + 16279886, 64719067, 15989606, 21668724, 19140425, 62032528, 31894001, 14000444, + ), + u32x8::new_const( + 36500306, 17827321, 19052241, 838783, 31029387, 53863823, 8190087, 6168061, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 58297975, 1271791, 26327207, 12780927, 21326724, 55825376, 1881468, 19837539, + ), + u32x8::new_const( + 41889841, 51572094, 29732198, 3211604, 26179218, 66326610, 23747079, 9590379, + ), + u32x8::new_const( + 3826490, 25399835, 21583051, 18952539, 65295023, 42750425, 2246330, 32346254, + ), + u32x8::new_const( + 52190758, 32188098, 24570211, 20678866, 40932593, 8178429, 27967937, 28257661, + ), + u32x8::new_const( + 30236672, 9815342, 29650636, 24107060, 43660614, 37629440, 12674453, 2006553, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 61053967, 64436103, 447268, 25700182, 19255118, 14993526, 899478, 2434175, + ), + u32x8::new_const( + 35812815, 10060004, 31384605, 25670757, 9561857, 60752897, 21085685, 27549514, + ), + u32x8::new_const( + 18488525, 64357302, 10815830, 2935874, 29965756, 65776827, 18067405, 29757081, + ), + u32x8::new_const( + 9151450, 55058906, 9505908, 19318842, 16283246, 36644461, 27208985, 12764280, + ), + u32x8::new_const( + 935064, 62208992, 28617878, 9642406, 33296477, 20692366, 14092783, 29523038, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 43982257, 1870168, 4563592, 25651161, 16953299, 59521203, 32759146, 23740415, + ), + u32x8::new_const( + 58238384, 34563808, 32443148, 21494201, 4125650, 52067840, 14679425, 9739512, + ), + u32x8::new_const( + 22799713, 45658991, 31646134, 20985007, 25125757, 30914923, 23225832, 25549240, + ), + u32x8::new_const( + 57964769, 17027909, 11726313, 16601782, 55202345, 44469180, 19529404, 17872655, + ), + u32x8::new_const( + 29135281, 26779810, 23911498, 19293297, 15382461, 22625292, 27273113, 11918932, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 20356928, 44286797, 22416632, 26923729, 37256426, 26174151, 8631283, 13726744, + ), + u32x8::new_const( + 15050322, 50131342, 17556728, 23214692, 57865782, 26708371, 14597005, 31489486, + ), + u32x8::new_const( + 10930030, 52761167, 17112689, 22969526, 21350113, 19294179, 2468751, 28829631, + ), + u32x8::new_const( + 21428704, 20303938, 30589121, 12662814, 5328394, 19277415, 17102411, 16988972, + ), + u32x8::new_const( + 18480836, 42343373, 1078384, 27210912, 44126946, 66557826, 6700400, 7552628, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 26298451, 31358962, 2410750, 1222016, 6602808, 44151217, 19067066, 20265648, + ), + u32x8::new_const( + 55489773, 8500419, 18022394, 14157663, 64952743, 30690464, 4133387, 4111644, + ), + u32x8::new_const( + 62382671, 36329179, 8557628, 5794859, 23898950, 33060808, 8782720, 32408648, + ), + u32x8::new_const( + 42610331, 38124770, 7134858, 18736387, 7942085, 52164416, 31680501, 29556327, + ), + u32x8::new_const( + 5234530, 9444407, 25023918, 10390934, 8479340, 52612004, 32163536, 23949516, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 23655649, 20966851, 549747, 32424363, 65477828, 28514773, 964955, 24097969, + ), + u32x8::new_const( + 10190745, 12573645, 17574436, 8670785, 40257066, 24017385, 18903364, 2903730, + ), + u32x8::new_const( + 65255895, 6342458, 8253517, 21684439, 25311893, 11419775, 17555636, 8477305, + ), + u32x8::new_const( + 28276837, 53282575, 15032193, 7864586, 13987263, 58062910, 14566708, 20452982, + ), + u32x8::new_const( + 23280558, 4071800, 13973538, 14314990, 3800625, 49289684, 21965196, 25337015, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 12346933, 43640065, 11294461, 3235676, 17615927, 5260789, 4540788, 21895087, + ), + u32x8::new_const( + 24450060, 4710546, 4707754, 6116116, 59999924, 32574139, 18219955, 32529652, + ), + u32x8::new_const( + 48787857, 56833627, 595516, 15964297, 18845497, 56029604, 13864576, 18463356, + ), + u32x8::new_const( + 7335332, 5495540, 24018875, 1219221, 18695805, 51707846, 5336005, 18884320, + ), + u32x8::new_const( + 27774957, 50806778, 32219720, 17063358, 30418813, 19859422, 2807745, 31952068, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 13259319, 12877556, 32674830, 3068639, 40926836, 65568244, 13903527, 14246844, + ), + u32x8::new_const( + 19760282, 4231746, 20039156, 9584931, 46137502, 1007141, 31889743, 5315799, + ), + u32x8::new_const( + 23010987, 43988832, 31439412, 33402306, 29485440, 42366801, 23756164, 21161315, + ), + u32x8::new_const( + 60133774, 47482282, 31793796, 16342946, 16989226, 49155307, 12280554, 9322415, + ), + u32x8::new_const( + 63950295, 10259675, 9331214, 33529833, 42349434, 33997731, 14870340, 26362289, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 14245366, 28236390, 32495195, 1903618, 26355961, 61847836, 31074990, 5570006, + ), + u32x8::new_const( + 57631483, 13510128, 4526364, 31354578, 2795194, 13226700, 12678920, 3005534, + ), + u32x8::new_const( + 6378678, 2937737, 9993021, 9886484, 40403775, 22317549, 32563938, 8897450, + ), + u32x8::new_const( + 22521910, 54884501, 71688, 14321146, 31184732, 61942577, 13054737, 11887222, + ), + u32x8::new_const( + 11674503, 10927348, 32617792, 6999186, 31816101, 38204839, 6870421, 24244858, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 54308752, 26550372, 9833703, 22389196, 26743928, 49945379, 10830897, 5168929, + ), + u32x8::new_const( + 54610408, 48564793, 708135, 86797, 49829472, 32258710, 23415696, 28707108, + ), + u32x8::new_const( + 23451141, 55435527, 11375487, 4377688, 20300614, 1360735, 3355272, 8526708, + ), + u32x8::new_const( + 7089618, 36909523, 23755702, 473790, 55390180, 25751283, 21113075, 30940031, + ), + u32x8::new_const( + 12390903, 47157487, 4087908, 21204034, 52363722, 6900482, 10266331, 20897802, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 18414961, 66085639, 31050037, 24091943, 59468097, 20758977, 1448180, 6046066, + ), + u32x8::new_const( + 49330019, 224100, 30459210, 23494631, 13921995, 1055950, 21420652, 25038857, + ), + u32x8::new_const( + 50755258, 12280676, 5008385, 27882827, 58183519, 3566388, 3745404, 30180350, + ), + u32x8::new_const( + 64792686, 7862574, 5430600, 2395677, 14541577, 23097280, 28702697, 17238068, + ), + u32x8::new_const( + 23614637, 35825532, 24119920, 19778800, 24895200, 29808533, 24020780, 30901767, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 66516001, 15248829, 14766533, 32492378, 44335444, 23305651, 28345377, 8650968, + ), + u32x8::new_const( + 3783259, 49027054, 4840824, 18074115, 59840645, 29268315, 17125524, 294884, + ), + u32x8::new_const( + 29684067, 19479287, 20003629, 1649311, 14467317, 2964989, 19605906, 1799442, + ), + u32x8::new_const( + 39235804, 41079588, 11058213, 23850874, 12892344, 64031356, 20883668, 25284200, + ), + u32x8::new_const( + 48318169, 54964663, 15389651, 11904227, 32563747, 27920903, 3780026, 29767761, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 9612690, 1382466, 21002366, 10768543, 9730112, 22849137, 20953575, 32803264, + ), + u32x8::new_const( + 9261889, 47750389, 18497060, 32515218, 56673410, 54581909, 26270427, 19202199, + ), + u32x8::new_const( + 65838570, 56663266, 27121361, 5277123, 32779170, 62796787, 32062043, 14718896, + ), + u32x8::new_const( + 26498712, 3601984, 23778799, 31003011, 28041711, 35652266, 12294762, 14532071, + ), + u32x8::new_const( + 34045696, 20351212, 31892898, 22564775, 42232113, 15210531, 27406293, 30693595, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 36447274, 2946121, 21285936, 8939725, 24505275, 66451394, 1923788, 7481505, + ), + u32x8::new_const( + 34181571, 37990878, 11301920, 6288700, 46182359, 24505232, 9424924, 6074720, + ), + u32x8::new_const( + 61175906, 28218027, 29763710, 21494951, 52546489, 65890060, 7754555, 20646718, + ), + u32x8::new_const( + 47755499, 49911769, 969801, 14998762, 57617218, 9872431, 19386424, 7502919, + ), + u32x8::new_const( + 23823345, 37710736, 353437, 837269, 20059850, 36660918, 5909148, 4042090, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 51470867, 48342424, 19844095, 773224, 26346536, 6529102, 20228223, 25701673, + ), + u32x8::new_const( + 37059302, 49714967, 13798761, 24840750, 18352099, 45959809, 18548956, 32391672, + ), + u32x8::new_const( + 33569256, 21738952, 17923265, 18618264, 19504640, 51279843, 23727570, 4279888, + ), + u32x8::new_const( + 55696366, 38845579, 22069653, 28586247, 49619343, 7355229, 9712149, 15347718, + ), + u32x8::new_const( + 48297532, 12020004, 15893950, 1733845, 6896622, 44889750, 18556572, 13312796, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 6490356, 33023974, 29104301, 18572662, 41649682, 7266370, 4815378, 13732647, + ), + u32x8::new_const( + 8702159, 22214007, 23289727, 5935891, 40875139, 40140791, 3008402, 20869501, + ), + u32x8::new_const( + 60661433, 47550641, 21958650, 31956329, 35584478, 9315792, 22453910, 12046027, + ), + u32x8::new_const( + 19762004, 21490912, 28975701, 20400139, 62957528, 36214948, 21789010, 4593612, + ), + u32x8::new_const( + 35698717, 33515594, 18721902, 12288462, 3455586, 24276529, 12477938, 3513932, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 13376996, 65306407, 8819762, 509836, 61979836, 29996824, 13728164, 1683577, + ), + u32x8::new_const( + 31754278, 41415297, 13907497, 5205944, 45844812, 46732506, 13966028, 25159819, + ), + u32x8::new_const( + 59439197, 64478722, 4835053, 18960918, 62436932, 8905029, 28596956, 5756766, + ), + u32x8::new_const( + 53224397, 6490738, 23756080, 15813398, 60653173, 52066349, 10281546, 25232857, + ), + u32x8::new_const( + 53318770, 21257373, 12826354, 15129547, 52456520, 53808437, 15158406, 4487957, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 41550835, 21914458, 28834230, 27635318, 15059059, 42296876, 15660040, 4037523, + ), + u32x8::new_const( + 47060225, 17570503, 11003606, 11312838, 35997511, 49275283, 29164177, 21774929, + ), + u32x8::new_const( + 11394838, 66550471, 31528400, 21464478, 28299924, 42329519, 22931929, 24076269, + ), + u32x8::new_const( + 62151355, 3473619, 19131297, 14959140, 49575228, 66257174, 20667402, 31713867, + ), + u32x8::new_const( + 47605434, 56106854, 9652000, 16341363, 20734550, 4974650, 8680004, 18520832, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 55014049, 56166958, 12325982, 29225780, 51408454, 66870445, 5773038, 27833505, + ), + u32x8::new_const( + 18140728, 50908918, 334462, 2284208, 39961432, 25082816, 5307496, 188363, + ), + u32x8::new_const( + 20676313, 14268341, 10026283, 23093022, 44203183, 37978274, 8438261, 2887752, + ), + u32x8::new_const( + 37261496, 57221442, 32601851, 4129478, 53445323, 21369981, 19234079, 2835438, + ), + u32x8::new_const( + 45787503, 17062316, 1884095, 25235460, 66422948, 55813009, 10666381, 32720377, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 7686657, 66224871, 22518516, 10843462, 25163913, 26354416, 8042017, 441838, + ), + u32x8::new_const( + 47708575, 3020178, 27840716, 4364999, 25383655, 29412724, 23348457, 9237315, + ), + u32x8::new_const( + 6272444, 54039282, 8899982, 27841888, 29505348, 36775319, 6336305, 22064771, + ), + u32x8::new_const( + 37152109, 32320311, 8670455, 23352630, 51365260, 1968036, 6936370, 32974423, + ), + u32x8::new_const( + 21951421, 30027530, 19458291, 12242090, 14997940, 52976661, 28054747, 5711378, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 17950668, 55075323, 31300190, 10183926, 4445653, 62306569, 33223381, 16532798, + ), + u32x8::new_const( + 54988195, 10175949, 30369750, 25328828, 59185551, 30491552, 8734833, 9613889, + ), + u32x8::new_const( + 5241018, 20913754, 31203311, 22979937, 45406816, 66448741, 18924706, 29339871, + ), + u32x8::new_const( + 5196490, 15479268, 27795721, 32631997, 9737545, 58569435, 15579604, 29875172, + ), + u32x8::new_const( + 14755460, 32572836, 3372474, 6668928, 65913585, 61065775, 18628649, 28587059, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 18165457, 4069393, 23155785, 2997879, 14730144, 3208555, 27442413, 11417510, + ), + u32x8::new_const( + 20704399, 58046354, 1069431, 16688733, 21546957, 33879183, 10569151, 9548738, + ), + u32x8::new_const( + 57089846, 20140780, 10307246, 6403032, 22404223, 36140665, 7891688, 11074026, + ), + u32x8::new_const( + 10920149, 29949354, 7738853, 1745449, 45470397, 5225234, 28546938, 15097478, + ), + u32x8::new_const( + 26430774, 24206708, 5069292, 14768207, 17595085, 353430, 1218821, 2818378, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 20910350, 52305504, 7697290, 25879030, 23352874, 14682583, 22079674, 22834543, + ), + u32x8::new_const( + 51049084, 44188336, 18335913, 14759686, 56752347, 38895866, 16587173, 19011044, + ), + u32x8::new_const( + 12938211, 43557833, 27973907, 33475864, 56594202, 25954472, 16573994, 29726963, + ), + u32x8::new_const( + 3898301, 10901036, 7602445, 1917915, 39760216, 9774843, 21779996, 15655542, + ), + u32x8::new_const( + 29388987, 6281239, 22073078, 15229204, 8421130, 39714378, 19561896, 8289657, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 21546549, 32946434, 19111394, 31996761, 29783677, 5566891, 13475221, 16288314, + ), + u32x8::new_const( + 54094563, 16464921, 16649349, 3058313, 37278150, 3886086, 28731864, 11796702, + ), + u32x8::new_const( + 53159833, 22229837, 3380283, 32228247, 62656858, 5184776, 20777034, 8836087, + ), + u32x8::new_const( + 23120182, 33361963, 8369041, 30410442, 30513474, 20892193, 25481199, 9331877, + ), + u32x8::new_const( + 47465728, 54130231, 8205722, 25616004, 30057551, 54576736, 14693268, 32348758, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 28660425, 44656599, 8748461, 27365619, 5521196, 63935665, 18065438, 22937662, + ), + u32x8::new_const( + 3120469, 34100952, 550431, 3730113, 42894630, 37828353, 11357199, 4806337, + ), + u32x8::new_const( + 12086214, 53548458, 3207690, 12334705, 7910881, 35504647, 19870599, 31344659, + ), + u32x8::new_const( + 62802349, 12517402, 32641989, 21624550, 57270930, 3549247, 6278113, 31550676, + ), + u32x8::new_const( + 14399443, 32323400, 15027259, 20767220, 60088307, 42789315, 11175117, 69847, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 65274066, 13751376, 12378765, 20048415, 11099021, 24661821, 5702786, 19473567, + ), + u32x8::new_const( + 57028688, 13426298, 8573512, 14809464, 22208058, 11535602, 18483718, 9214030, + ), + u32x8::new_const( + 46390518, 10803771, 22040353, 4729297, 35803291, 30660305, 5581949, 6865547, + ), + u32x8::new_const( + 38696365, 42508504, 15709824, 10569285, 35073707, 12754487, 17435220, 25380721, + ), + u32x8::new_const( + 34796390, 471612, 32849474, 11490029, 7579485, 5466203, 13965748, 9028171, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 46398293, 31763192, 11009463, 14514166, 9138837, 50031952, 20475358, 21925769, + ), + u32x8::new_const( + 14430903, 50083845, 19223649, 21472434, 609969, 52660479, 2639840, 9832885, + ), + u32x8::new_const( + 52344162, 5728060, 27238191, 10222394, 64973017, 49907322, 10108843, 521032, + ), + u32x8::new_const( + 47793090, 64765257, 29020380, 24524686, 52940614, 12262477, 33158351, 11498282, + ), + u32x8::new_const( + 56800279, 37034976, 3158344, 29019773, 54534150, 35772329, 8001282, 19330221, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 45925904, 56299077, 10759667, 9073241, 13702649, 27637149, 31621594, 21678227, + ), + u32x8::new_const( + 32670083, 34096737, 30218425, 5400421, 52204642, 59662423, 4781663, 31791466, + ), + u32x8::new_const( + 8197184, 17528365, 17586243, 25108374, 51219484, 42887435, 4140880, 13267174, + ), + u32x8::new_const( + 52644490, 29377262, 9350414, 17183906, 66195797, 3250976, 29901358, 17667319, + ), + u32x8::new_const( + 11653875, 3030019, 3778472, 28021431, 28134779, 56700686, 25614729, 8516583, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 49975689, 10179759, 12501939, 24670055, 62856726, 32391757, 27667528, 1847042, + ), + u32x8::new_const( + 53411362, 25947229, 4451531, 293599, 26835000, 20369835, 10800802, 11071763, + ), + u32x8::new_const( + 24484352, 17467581, 9370659, 5245157, 66918621, 21426707, 27911800, 14364451, + ), + u32x8::new_const( + 44979726, 38908236, 26336667, 9912388, 17498629, 37689374, 24956688, 4603513, + ), + u32x8::new_const( + 57580993, 1374673, 12321457, 8908217, 63554789, 14754667, 8987880, 27537203, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 38131533, 58677594, 14697078, 30884327, 24626850, 13059976, 22357714, 8909205, + ), + u32x8::new_const( + 52545298, 12825303, 3296902, 5157715, 9363783, 35187308, 3803720, 4439907, + ), + u32x8::new_const( + 17189305, 57308064, 27192477, 1347798, 14040416, 41456322, 23385136, 13885485, + ), + u32x8::new_const( + 57052845, 2406981, 32824514, 4655370, 30412409, 33595638, 19464320, 6076206, + ), + u32x8::new_const( + 13330079, 28047077, 17452985, 15860698, 5486545, 33164726, 3123559, 3382994, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 19425166, 15804094, 19246326, 3197553, 23817240, 52674714, 19795740, 9064177, + ), + u32x8::new_const( + 54177980, 66138378, 12194289, 32803965, 45879417, 48287620, 23403280, 5012597, + ), + u32x8::new_const( + 5316398, 28053150, 18173659, 7759388, 9250687, 66908279, 28735676, 10958853, + ), + u32x8::new_const( + 54410084, 15224920, 21235020, 4602263, 26595902, 18328240, 23498962, 1054891, + ), + u32x8::new_const( + 65892143, 61887867, 11204697, 1534216, 66553943, 53563175, 21934146, 11690109, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 47724275, 26014482, 30076460, 2958508, 5975771, 5671739, 28811193, 18031955, + ), + u32x8::new_const( + 32451132, 586856, 26543677, 3255215, 60483363, 14079099, 32234020, 19697705, + ), + u32x8::new_const( + 21472872, 46434446, 1510380, 10847828, 55269248, 44062694, 9751210, 7547163, + ), + u32x8::new_const( + 25165168, 63270285, 2042109, 12697884, 6656975, 7041577, 31045467, 2147149, + ), + u32x8::new_const( + 11991528, 63574666, 30380704, 9340412, 50393937, 2043147, 5390529, 352765, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 1550418, 52330110, 26409265, 28469159, 55535444, 32722371, 28573097, 16012159, + ), + u32x8::new_const( + 58389358, 53830560, 22221806, 30695591, 41386341, 26721300, 219038, 32709664, + ), + u32x8::new_const( + 19086032, 2102262, 23619165, 27407474, 15250356, 36899694, 28878414, 32540271, + ), + u32x8::new_const( + 42041517, 50254818, 32272558, 18440404, 16672938, 25374866, 19024707, 19441647, + ), + u32x8::new_const( + 17994558, 1051640, 18281712, 3248398, 11389789, 49577335, 8116500, 4760248, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 46532023, 16432714, 15478762, 6019862, 14771607, 15751909, 32770717, 11874709, + ), + u32x8::new_const( + 48541770, 20559615, 31325477, 19920210, 3614079, 58936725, 27322204, 9552530, + ), + u32x8::new_const( + 7748519, 14578706, 28979241, 21060952, 61044638, 53434623, 9380871, 23837872, + ), + u32x8::new_const( + 5400653, 43980232, 30090147, 17164849, 45279466, 5225645, 12555760, 30686374, + ), + u32x8::new_const( + 37573905, 40694048, 16546395, 30588996, 58757334, 64273317, 3068575, 16791851, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 610812, 14932813, 2692246, 32741850, 38943278, 16888531, 12032697, 7387068, + ), + u32x8::new_const( + 43872105, 65902799, 10044497, 21354699, 41263093, 52232769, 27291985, 8249610, + ), + u32x8::new_const( + 23675435, 62942269, 28632367, 31519948, 22378418, 39971978, 25936032, 31675091, + ), + u32x8::new_const( + 40066894, 39824391, 10932213, 10262528, 27874051, 175070, 22301606, 31043195, + ), + u32x8::new_const( + 18506964, 58680007, 18190848, 7676562, 32636640, 14475669, 3155181, 25257392, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 30089135, 35156482, 27291939, 8887133, 66564028, 41943147, 1235755, 14810811, + ), + u32x8::new_const( + 34382148, 17884113, 6369743, 24508223, 38844444, 13335595, 30384176, 3234026, + ), + u32x8::new_const( + 1905677, 27683665, 26472369, 15857050, 50179031, 61366061, 5089187, 23834790, + ), + u32x8::new_const( + 10190842, 59658946, 12202849, 17712353, 54662112, 59857136, 27934496, 23740673, + ), + u32x8::new_const( + 3437524, 14819683, 7417659, 178118, 18618648, 13991314, 21338144, 13799164, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 9719911, 40895071, 9525640, 17080099, 19574015, 55378945, 6843920, 5964456, + ), + u32x8::new_const( + 43171821, 53449385, 6081768, 1866894, 59786921, 51007931, 6037794, 468756, + ), + u32x8::new_const( + 21500587, 28947964, 13922474, 33044302, 17374625, 54213629, 18632861, 4585816, + ), + u32x8::new_const( + 8945137, 20174492, 27837869, 25683701, 61123110, 26363968, 30598122, 9919429, + ), + u32x8::new_const( + 51536299, 21626117, 14236480, 19331903, 16301580, 61050224, 25832297, 8263194, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 11140253, 11131045, 28436561, 25239360, 25588027, 65155270, 22774769, 17851222, + ), + u32x8::new_const( + 64491072, 43334882, 25301883, 31955672, 47937742, 1317318, 9514081, 13978627, + ), + u32x8::new_const( + 8802171, 28394591, 82234, 33282441, 8922236, 45708918, 2301010, 1983093, + ), + u32x8::new_const( + 30554504, 15757993, 23840417, 8904383, 47572746, 62002975, 8850888, 20862075, + ), + u32x8::new_const( + 43744357, 50385711, 15550423, 29553893, 66830206, 64498762, 20778012, 30169310, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 14867357, 45118563, 18845788, 15775520, 2564682, 60779919, 21186741, 7220438, + ), + u32x8::new_const( + 54750608, 43447861, 6375129, 26696317, 31357839, 53339889, 1463530, 4022891, + ), + u32x8::new_const( + 25646072, 17609956, 7250979, 15328587, 479642, 3036498, 28640473, 1299126, + ), + u32x8::new_const( + 55316871, 39622191, 22480985, 1129483, 38617910, 54978941, 24056066, 28807, + ), + u32x8::new_const( + 51065003, 44533782, 18862064, 14524700, 63954791, 39559613, 9962408, 23622043, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 63018303, 12102244, 28442965, 31721516, 35192130, 62556264, 26417276, 14801484, + ), + u32x8::new_const( + 45646841, 31701003, 14121931, 12565072, 18860229, 1626738, 1600424, 22221435, + ), + u32x8::new_const( + 55677777, 26519963, 17794806, 30172596, 65921087, 26176327, 2002122, 10469487, + ), + u32x8::new_const( + 1372377, 8601495, 20869454, 27843570, 8939226, 64119039, 31033207, 6583357, + ), + u32x8::new_const( + 1177016, 7337684, 28703520, 19987471, 5422532, 20613788, 27951523, 27660512, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 14849799, 5251051, 15176276, 7427477, 968823, 10761720, 26328278, 28794035, + ), + u32x8::new_const( + 23635321, 57695554, 4329650, 20820240, 27046054, 40932765, 24474527, 29678688, + ), + u32x8::new_const( + 53822522, 16047651, 6939643, 33408194, 60747694, 52509462, 18341470, 25825094, + ), + u32x8::new_const( + 30666373, 22991718, 25232775, 17781031, 11552830, 6539915, 18078409, 19736711, + ), + u32x8::new_const( + 64424600, 20457495, 20460564, 10898959, 30387056, 8629249, 18669915, 21156317, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 51734475, 51726057, 14546405, 7618397, 39077828, 28658885, 18447267, 31432119, + ), + u32x8::new_const( + 17600994, 54105246, 18906630, 22338062, 52010403, 4477001, 10537215, 22032946, + ), + u32x8::new_const( + 11647181, 2892760, 9269116, 17241937, 66823023, 42584556, 9857259, 374690, + ), + u32x8::new_const( + 36128798, 45209204, 31068849, 14392374, 310195, 13335655, 32991258, 13572240, + ), + u32x8::new_const( + 65637246, 55249894, 27270204, 5305925, 21588667, 1183611, 3029008, 16895807, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 36380894, 9061635, 14508199, 25443229, 55007427, 27939251, 21509559, 12982666, + ), + u32x8::new_const( + 8332601, 26781143, 24872396, 12863927, 45544107, 37580239, 11884691, 9603082, + ), + u32x8::new_const( + 18594829, 9425533, 23720155, 4971377, 44899242, 57417823, 16992758, 12150938, + ), + u32x8::new_const( + 33694783, 41614547, 25901130, 1947718, 38938262, 43270960, 650080, 10257916, + ), + u32x8::new_const( + 53732027, 65708249, 32575363, 1513912, 55053392, 10776633, 19027031, 23184862, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 36835361, 63488282, 30715955, 30985771, 45094590, 5848555, 29099290, 32297638, + ), + u32x8::new_const( + 7795059, 14667421, 29753451, 1679580, 34792983, 8385285, 24398041, 17441532, + ), + u32x8::new_const( + 48781922, 5669073, 7922166, 30178310, 59663017, 27489002, 3564688, 32034816, + ), + u32x8::new_const( + 65487042, 30209017, 17518282, 32673922, 61373726, 62519208, 28718857, 22349327, + ), + u32x8::new_const( + 54211650, 48270797, 6669863, 17882413, 29556940, 36343722, 23405936, 23191774, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 44959513, 62433874, 16306679, 20759552, 17162798, 51767301, 23294236, 32860705, + ), + u32x8::new_const( + 34425285, 51934952, 26434865, 12191198, 15366730, 51547559, 16856218, 28699780, + ), + u32x8::new_const( + 55835590, 41155775, 19391391, 22390960, 14993953, 35380174, 17549217, 31316496, + ), + u32x8::new_const( + 15397378, 15616376, 19876010, 22852367, 10769263, 14582037, 28646951, 13857305, + ), + u32x8::new_const( + 13191690, 25871801, 15832046, 1828651, 66787540, 840358, 17772454, 327910, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 32201641, 34077867, 23551899, 21162589, 20591353, 44534186, 14376015, 2279252, + ), + u32x8::new_const( + 12000097, 54344932, 19765316, 11708664, 44114030, 54637419, 11905990, 8976606, + ), + u32x8::new_const( + 7448881, 8971479, 32304719, 6257622, 36475381, 13425377, 30323619, 15746128, + ), + u32x8::new_const( + 3915175, 665188, 21424459, 16945325, 32493232, 65995460, 12911374, 14895303, + ), + u32x8::new_const( + 46435411, 43502337, 17525134, 29195139, 49967677, 450916, 5490855, 11584504, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 53674007, 13969216, 14226658, 5519852, 35313873, 45079216, 10513211, 2890110, + ), + u32x8::new_const( + 25686353, 47977105, 9500785, 27505391, 34016512, 34483198, 13443569, 1892979, + ), + u32x8::new_const( + 42698708, 39253907, 22925036, 33398085, 51184600, 64780843, 360494, 31549455, + ), + u32x8::new_const( + 615402, 65714769, 24419303, 1645340, 10365442, 33898376, 33222102, 19871601, + ), + u32x8::new_const( + 45764848, 288124, 31605752, 32401826, 34817675, 38790988, 5149247, 18041878, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 11573772, 32541211, 31168718, 33537923, 57518627, 32959984, 22162358, 13040928, + ), + u32x8::new_const( + 62978865, 17398894, 26909478, 4791599, 35163452, 53859171, 25566591, 23067631, + ), + u32x8::new_const( + 49954126, 8601799, 32319182, 33344822, 28102480, 46284017, 4607910, 30175840, + ), + u32x8::new_const( + 25086689, 50195079, 31610725, 6141310, 19702890, 57596397, 2078168, 3545279, + ), + u32x8::new_const( + 14337484, 31849999, 6912945, 33442857, 21518600, 30259358, 20817397, 24430362, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 14490779, 18335456, 1299884, 15797707, 20756153, 16099699, 16046198, 21851469, + ), + u32x8::new_const( + 36314351, 28969034, 32687438, 29446046, 27223508, 33011427, 14070434, 32774409, + ), + u32x8::new_const( + 63168772, 37265605, 31316709, 22477601, 52049283, 17431507, 9434313, 18428520, + ), + u32x8::new_const( + 11550216, 56597403, 17468121, 23760013, 5337005, 62589655, 30751736, 15317299, + ), + u32x8::new_const( + 45291893, 44001653, 3987717, 26614363, 14918062, 39119552, 1074690, 25714981, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 27361417, 17955508, 3953710, 13719695, 13407440, 33957856, 6036293, 30697122, + ), + u32x8::new_const( + 61216034, 12799215, 27233558, 4783597, 7310478, 32583116, 18915196, 608256, + ), + u32x8::new_const( + 716516, 45668202, 30203444, 14942952, 27523350, 41574893, 15283973, 9545348, + ), + u32x8::new_const( + 10221877, 43739008, 738665, 12262061, 54346212, 20143887, 5597121, 31629477, + ), + u32x8::new_const( + 66769453, 22354536, 7503157, 18121460, 25928609, 23899280, 23578075, 22284654, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 48074669, 22616656, 27618425, 11127229, 36261402, 66705467, 14536317, 8982883, + ), + u32x8::new_const( + 8214571, 39986942, 28511286, 14043477, 18127665, 22867686, 28878033, 7203821, + ), + u32x8::new_const( + 63817078, 6482031, 9982572, 33338991, 12977138, 33808629, 5882644, 16383415, + ), + u32x8::new_const( + 26427692, 6111744, 29346211, 12287319, 34256200, 47276801, 23449764, 3180143, + ), + u32x8::new_const( + 17739429, 34170903, 25948685, 29154215, 37220841, 57191917, 33419590, 28775010, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 16366076, 29210515, 28313711, 22167455, 23664778, 58342907, 18728142, 8446307, + ), + u32x8::new_const( + 49903000, 54128873, 4623896, 30141189, 40135970, 65674418, 2783519, 9438545, + ), + u32x8::new_const( + 12021518, 56284151, 18877120, 15463806, 36495734, 14597619, 25036169, 5461960, + ), + u32x8::new_const( + 40624409, 14778897, 29313785, 2830147, 53401689, 11270369, 15248365, 30861917, + ), + u32x8::new_const( + 53612420, 49563602, 4185689, 1487144, 45924263, 59538279, 13689393, 28374155, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 62448324, 39119503, 2376208, 26167494, 58743661, 30514077, 3817453, 28742402, + ), + u32x8::new_const( + 65775087, 64842964, 32275894, 31059646, 65677440, 9986651, 13574033, 6382212, + ), + u32x8::new_const( + 60750288, 38470939, 32436356, 18715250, 2066621, 60273500, 15642979, 14997670, + ), + u32x8::new_const( + 15259597, 31235310, 19183116, 1614281, 28349084, 41438403, 15563460, 15387361, + ), + u32x8::new_const( + 17216925, 56257102, 31244493, 24254300, 12043484, 66328694, 19420628, 14122181, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 31031970, 50333317, 15232840, 20700709, 6346793, 30015642, 9089552, 2403354, + ), + u32x8::new_const( + 54564023, 5135656, 31940048, 30048321, 26852583, 50315139, 17715573, 23013010, + ), + u32x8::new_const( + 50234405, 44293836, 22859610, 18630855, 65274547, 6388087, 17823332, 32306523, + ), + u32x8::new_const( + 20359317, 13891769, 33196972, 27359154, 54406328, 43910344, 12273016, 29104924, + ), + u32x8::new_const( + 2170631, 10685295, 3009948, 16125460, 24229555, 44132989, 10633107, 9375916, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 46177908, 64177297, 20054054, 18739919, 40452841, 46835774, 5979298, 20844203, + ), + u32x8::new_const( + 24866012, 3742502, 30714833, 25204779, 34087195, 31684005, 20449901, 24475068, + ), + u32x8::new_const( + 47384542, 11639593, 21135639, 24270003, 12052216, 15356000, 24953227, 18911658, + ), + u32x8::new_const( + 49847806, 56558436, 26231262, 27348855, 42331884, 13662544, 3400707, 9466693, + ), + u32x8::new_const( + 39205049, 31909263, 31354786, 4485767, 8805415, 63885825, 8049492, 11779978, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 35089776, 27682279, 26114285, 20005068, 7596626, 24313422, 24643671, 17131766, + ), + u32x8::new_const( + 32731612, 21290185, 32575030, 22234092, 66632947, 25741911, 24521617, 20163356, + ), + u32x8::new_const( + 32365930, 36414090, 17702236, 27082917, 44219961, 58910449, 27057285, 18463158, + ), + u32x8::new_const( + 12124126, 1246492, 25306168, 21593794, 48043189, 56422833, 8377174, 16706763, + ), + u32x8::new_const( + 12716036, 38242959, 1519491, 8806979, 48304186, 9037971, 28611171, 27678953, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 43178612, 42357131, 10947783, 12243834, 5820113, 59854163, 3740513, 14174602, + ), + u32x8::new_const( + 37493338, 7237024, 14100023, 27271727, 17094752, 56961986, 17157550, 12000793, + ), + u32x8::new_const( + 31589616, 16925009, 10301855, 4589578, 30691021, 51232394, 8723243, 11134272, + ), + u32x8::new_const( + 4127873, 36978916, 7476964, 25480065, 49420154, 9646381, 4091080, 27149296, + ), + u32x8::new_const( + 11370449, 32587558, 11660158, 689103, 64576292, 49150348, 17332982, 24148634, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 8215823, 35010905, 2265150, 15616079, 14548414, 50670002, 30985530, 23698899, + ), + u32x8::new_const( + 23143208, 14414565, 22807802, 32758455, 56560110, 43091380, 28093319, 4523774, + ), + u32x8::new_const( + 50134924, 12437546, 12482164, 23449038, 26685186, 28318222, 1402053, 20552656, + ), + u32x8::new_const( + 60475045, 62121346, 8494959, 3210600, 48141268, 60189060, 20274243, 1943088, + ), + u32x8::new_const( + 59633146, 7873761, 5812601, 2393630, 57178481, 15232474, 11134599, 29614656, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 18575874, 30966916, 6507773, 9410095, 17963883, 21651047, 19617086, 30963083, + ), + u32x8::new_const( + 25194909, 8159809, 17068823, 32567269, 24544837, 17674655, 31940599, 5467735, + ), + u32x8::new_const( + 23022905, 58216532, 31282502, 14180297, 55920693, 31608652, 29020943, 6506052, + ), + u32x8::new_const( + 13062607, 61505353, 26991921, 11677662, 27046035, 51241976, 7979443, 28659350, + ), + u32x8::new_const( + 55654801, 5114837, 6867471, 21872860, 53116827, 8035819, 8614438, 30566434, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 9194164, 23420706, 28243579, 1719836, 31944457, 44008545, 28672466, 26926101, + ), + u32x8::new_const( + 46465506, 16866169, 19453016, 25382848, 24367354, 54950546, 10327800, 28693900, + ), + u32x8::new_const( + 4590015, 22864448, 31407167, 32710212, 54303760, 2778674, 18805976, 32013809, + ), + u32x8::new_const( + 13351868, 65088357, 7991308, 9081572, 16894242, 13207822, 18869867, 12018827, + ), + u32x8::new_const( + 38072323, 51609717, 21462349, 31250927, 22071795, 36316106, 5235853, 2591106, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 65656108, 3537652, 1435901, 1824522, 15503979, 55640605, 28147423, 9343686, + ), + u32x8::new_const( + 58803520, 9050062, 27505857, 13906312, 2282651, 57431613, 3408660, 31820399, + ), + u32x8::new_const( + 23088213, 41591130, 8527643, 28654603, 11901663, 3404951, 16325299, 27241853, + ), + u32x8::new_const( + 43573240, 2938723, 29275339, 29000766, 53310491, 66980097, 32262498, 1366966, + ), + u32x8::new_const( + 31007835, 2784816, 7111616, 18327731, 14029485, 18673073, 18952374, 21356310, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 42307241, 31090601, 32982000, 29191468, 9838577, 49801417, 24292869, 32990508, + ), + u32x8::new_const( + 6621123, 39435439, 17602332, 13670725, 4296501, 23099295, 18451749, 27489405, + ), + u32x8::new_const( + 5921500, 22167300, 18500460, 22373158, 15222566, 53112177, 10373692, 14812976, + ), + u32x8::new_const( + 7658355, 41056552, 20038917, 10733391, 4408385, 27150315, 32358106, 30595689, + ), + u32x8::new_const( + 13956811, 22101056, 31531146, 31693312, 40123581, 62475542, 10091489, 13312166, + ), + ])), + CachedPoint(FieldElement2625x4([ + u32x8::new_const( + 659664, 16725749, 30742652, 21722795, 20146761, 31307163, 24304349, 4447037, + ), + u32x8::new_const( + 22632019, 60633890, 32085450, 13511934, 11330156, 9538370, 30123101, 2940245, + ), + u32x8::new_const( + 6652900, 22873830, 14648481, 10295335, 58813606, 40705536, 24178497, 17746785, + ), + u32x8::new_const( + 37021072, 32236407, 18596742, 25815309, 50827290, 60076902, 27456121, 566683, + ), + u32x8::new_const( + 54323783, 48458935, 6414417, 21358054, 17928047, 43792036, 27829187, 20471257, + ), + ])), +]); diff --git a/curve25519-dalek/src/backend/vector/ifma/constants.rs b/curve25519-dalek/src/backend/vector/ifma/constants.rs index 66ace964..8f3771d9 100644 --- a/curve25519-dalek/src/backend/vector/ifma/constants.rs +++ b/curve25519-dalek/src/backend/vector/ifma/constants.rs @@ -17,6 +17,11 @@ use crate::window::NafLookupTable8; use super::edwards::{CachedPoint, ExtendedPoint}; use super::field::{F51x4Reduced, F51x4Unreduced}; +#[cfg(feature = "precomputed-tables")] +mod b_shl_128_odd_lookup_table; +#[cfg(feature = "precomputed-tables")] +pub(crate) use b_shl_128_odd_lookup_table::B_SHL_128_ODD_LOOKUP_TABLE; + /// The identity element as an `ExtendedPoint`. pub(crate) static EXTENDEDPOINT_IDENTITY: ExtendedPoint = ExtendedPoint(F51x4Unreduced([ u64x4::new_const(0, 1, 1, 0), @@ -2062,3 +2067,59 @@ pub(crate) static BASEPOINT_ODD_LOOKUP_TABLE: NafLookupTable8 = Naf ), ])), ]); + +#[cfg(all(test, feature = "precomputed-tables", curve25519_dalek_generate_tables))] +mod table_generators { + use std::fs::File; + use std::io::Write; + + use crate::{ + backend::vector::ifma::edwards::CachedPoint, constants::ED25519_BASEPOINT_SHL_128, + window::NafLookupTable8, + }; + + #[test] + fn b_shl_128_odd_lookup_table() { + let table = NafLookupTable8::::from(&ED25519_BASEPOINT_SHL_128); + let mut table_file = File::create(format!( + "{}/src/backend/vector/ifma/constants/b_shl_128_odd_lookup_table.rs", + env!("CARGO_MANIFEST_DIR") + )) + .expect("can open file"); + + writeln!( + table_file, + "//! Generated file, do not alter! + + use crate::{{ + backend::vector::{{ + ifma::{{edwards::CachedPoint, field::F51x4Reduced}}, + packed_simd::u64x4, + }}, + window::NafLookupTable8, + }}; + + /// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. + pub(crate) static B_SHL_128_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([", + ) + .expect("can write file"); + + for row in table.0 { + writeln!(table_file, "CachedPoint(F51x4Reduced([").expect("can write file"); + for vector in row.0 .0 { + writeln!( + table_file, + "u64x4::new_const({}, {}, {}, {}),", + vector.extract::<0>(), + vector.extract::<1>(), + vector.extract::<2>(), + vector.extract::<3>(), + ) + .expect("can write file"); + } + writeln!(table_file, "])),").expect("can write file"); + } + + writeln!(table_file, "]);").expect("can write file"); + } +} diff --git a/curve25519-dalek/src/backend/vector/ifma/constants/b_shl_128_odd_lookup_table.rs b/curve25519-dalek/src/backend/vector/ifma/constants/b_shl_128_odd_lookup_table.rs new file mode 100644 index 00000000..837efcc5 --- /dev/null +++ b/curve25519-dalek/src/backend/vector/ifma/constants/b_shl_128_odd_lookup_table.rs @@ -0,0 +1,2036 @@ +//! Generated file, do not alter! + +use crate::{ + backend::vector::{ + ifma::{edwards::CachedPoint, field::F51x4Reduced}, + packed_simd::u64x4, + }, + window::NafLookupTable8, +}; + +/// Odd multiples of `[2^128]B`: `[[2^128]B, [3 2^128]B, [5 2^128]B, [7 2^128]B, ..., [127 2^128]B]`. +pub(crate) static B_SHL_128_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([ + CachedPoint(F51x4Reduced([ + u64x4::new_const(1277522120965857, 73557767439946, 243332, 1943719795065404), + u64x4::new_const(108375142003455, 341984820733594, 0, 2097709862669256), + u64x4::new_const(150073485536043, 750646439938056, 0, 581130035634455), + u64x4::new_const(2149983732744869, 1903255931888577, 0, 646644904824193), + u64x4::new_const(291045673509296, 1060034214701851, 0, 325245010451737), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1970681836121889, + 1660307753655178, + 1077207637163462, + 1436413309977108, + ), + u64x4::new_const( + 158785710838757, + 919645875412951, + 174577133496574, + 2213787394009350, + ), + u64x4::new_const( + 1017606396438281, + 1240932851489554, + 918203302506967, + 1239827708070863, + ), + u64x4::new_const( + 1748989883612327, + 1745367742532782, + 1168385548387, + 1211387683826673, + ), + u64x4::new_const( + 799349980018733, + 1471088235739693, + 1505351346057417, + 2104975925096407, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 171437462972293, + 36016853025886, + 1184164975342640, + 1633525003912147, + ), + u64x4::new_const( + 2113383632509037, + 1946216474924125, + 1884174984466256, + 1373317790955847, + ), + u64x4::new_const( + 791293623466401, + 1796466048084189, + 444977763198796, + 629823271230872, + ), + u64x4::new_const( + 1093217720067380, + 2157024270666135, + 238122980108466, + 806820763806847, + ), + u64x4::new_const( + 793658959468458, + 368578641413741, + 11592529764159, + 2144017075993471, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1538027396670268, + 1588896993892061, + 675619548648376, + 788373514423313, + ), + u64x4::new_const( + 1987517656073805, + 1940987929951188, + 666993851697339, + 2040540928108427, + ), + u64x4::new_const( + 375514548584082, + 1726008037083790, + 1070069155000872, + 570111103756303, + ), + u64x4::new_const( + 772223645372213, + 2123395244967674, + 868238486911408, + 1846639042240362, + ), + u64x4::new_const( + 872865734460736, + 32277956842850, + 1701451131455402, + 773883376061880, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1845177363882902, + 275858237213625, + 1052127336883600, + 171072805852218, + ), + u64x4::new_const( + 139016783952609, + 462699304987089, + 430046471494974, + 410922720999257, + ), + u64x4::new_const( + 846403935976337, + 243817706931454, + 971825428236901, + 571800039596794, + ), + u64x4::new_const( + 807642685434918, + 1933536976438782, + 812324278898440, + 688391556487313, + ), + u64x4::new_const( + 76239450396192, + 629532732688863, + 1833302026979779, + 650067934544499, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1373931604989264, + 331159264656614, + 364391529321767, + 874765630865409, + ), + u64x4::new_const( + 2109908262150241, + 473400816504190, + 91544045127333, + 976307977609515, + ), + u64x4::new_const( + 330175435673491, + 2126511895885904, + 1022944071588421, + 2158480209801463, + ), + u64x4::new_const( + 1305666795527971, + 162063591028664, + 2193154870675382, + 1789166662611800, + ), + u64x4::new_const( + 817858592500508, + 1672743239440202, + 859976879916778, + 1167423340862516, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 274334925170164, + 565841102587251, + 603083835949120, + 607539210240861, + ), + u64x4::new_const( + 196754662972649, + 1339063476699167, + 1406077076979491, + 896902435668469, + ), + u64x4::new_const( + 397962210956733, + 174839587476217, + 1381082665748936, + 175195877334136, + ), + u64x4::new_const( + 717429432748391, + 1635309821746318, + 363374010274647, + 882908746261699, + ), + u64x4::new_const( + 600946602802781, + 1946596133370711, + 1532135183320341, + 690530671668253, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2074443704000945, + 2163534804938345, + 425423840926528, + 1100826171404853, + ), + u64x4::new_const( + 111700142796101, + 1456893872751964, + 1186145518682968, + 2192182627706116, + ), + u64x4::new_const( + 1848722121856066, + 2123239575044749, + 1323870754599272, + 883211262889775, + ), + u64x4::new_const( + 938263017712916, + 689670293631396, + 183944529557576, + 501908638166580, + ), + u64x4::new_const( + 2170571907220631, + 36636756989655, + 1875035480138608, + 803703278398018, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1053429956874064, + 1636640618139765, + 1556890827801070, + 2142720579528828, + ), + u64x4::new_const( + 1814240918422814, + 692326274601777, + 1054896561802157, + 2025454041705534, + ), + u64x4::new_const( + 2109495823888757, + 1287497869997176, + 194170063200096, + 621116840113213, + ), + u64x4::new_const( + 2156505873679998, + 2197064359737385, + 1312887672223536, + 369862818895912, + ), + u64x4::new_const( + 977381163563657, + 1878897311974033, + 2144566861359744, + 1832960882773351, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1266492498289486, + 1301524759372145, + 324789537938521, + 442710471023019, + ), + u64x4::new_const( + 1232722320001345, + 1191193089162455, + 176474006074813, + 2158950213252857, + ), + u64x4::new_const( + 1901782191467749, + 494791441598902, + 1820415815322129, + 854954583485223, + ), + u64x4::new_const( + 1511383667649702, + 792536415032464, + 2027741263854728, + 1727944381044738, + ), + u64x4::new_const( + 606355788891204, + 1670687521471220, + 582824350365415, + 1509135066079912, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1079942762813598, + 2015830004785901, + 479916361323351, + 1907956590950158, + ), + u64x4::new_const( + 2053400302939156, + 1319799126867070, + 19493088767391, + 1908755581402373, + ), + u64x4::new_const( + 2235858054780980, + 885832711204321, + 810332865560178, + 103174191215441, + ), + u64x4::new_const( + 1843466881032833, + 355511728384038, + 693846715794114, + 186545012724117, + ), + u64x4::new_const( + 1661758432892509, + 1491022339899281, + 698941123765263, + 174945407208560, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1075933251927831, + 400263885306647, + 1308157532880528, + 347933379126665, + ), + u64x4::new_const( + 673811632329433, + 1584860147186478, + 271778891257244, + 498194055154207, + ), + u64x4::new_const( + 703783427747558, + 1051624728592032, + 1371463103351544, + 230351033002960, + ), + u64x4::new_const( + 860729466483372, + 421647596766583, + 1520613871336707, + 635298775280054, + ), + u64x4::new_const( + 1168352891728845, + 1691216293752089, + 1799491997061519, + 399728882318504, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 420156727446514, + 1483649215777128, + 165508610199900, + 1918121104840431, + ), + u64x4::new_const( + 2129902293682427, + 730952770435213, + 2184527544565390, + 1939880362232986, + ), + u64x4::new_const( + 1771978364905086, + 510975579746524, + 927564335219142, + 177574146260558, + ), + u64x4::new_const( + 2164104536437514, + 1532598873799015, + 406875369182421, + 1367005937406517, + ), + u64x4::new_const( + 35073200082587, + 1981124717036219, + 1854087014063833, + 122419694385217, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1963785875777739, + 411497142699119, + 1974557512687408, + 1268304422747183, + ), + u64x4::new_const( + 762752575978150, + 1443822019541748, + 1331556159904338, + 377726798263780, + ), + u64x4::new_const( + 825953972847841, + 353487068141356, + 1955697322427207, + 2048226560172078, + ), + u64x4::new_const( + 1482378558684434, + 657691905625918, + 923870001994493, + 1694132799397736, + ), + u64x4::new_const( + 1643904759603122, + 170495566698285, + 1218312703413378, + 784318735038131, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 939230507241903, + 2238763473105245, + 1827325199528162, + 1153939339775538, + ), + u64x4::new_const( + 38544505283339, + 258889431497015, + 351721979677947, + 1357907379592829, + ), + u64x4::new_const( + 1393974676373341, + 1131355528938676, + 473104915298872, + 978783482501776, + ), + u64x4::new_const( + 2131516168980501, + 2113911780991092, + 1477027502354261, + 542884524860340, + ), + u64x4::new_const( + 1029606261349423, + 64226378557628, + 1669131167474348, + 2212808057234874, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1423176501543193, + 163313632579593, + 2220495688893001, + 2220041045291870, + ), + u64x4::new_const( + 1111834224023697, + 1026815658023689, + 1404605100939775, + 1412149108248227, + ), + u64x4::new_const( + 1542537854906076, + 1270288391129127, + 991419278941933, + 1824939809581980, + ), + u64x4::new_const( + 1142003215657891, + 525980550896367, + 1508270666157963, + 917719462309053, + ), + u64x4::new_const( + 400851268057105, + 1620818232405188, + 1251478578139510, + 2162841805361886, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2125383272208441, + 1368790097335984, + 11813369275978, + 639513785921674, + ), + u64x4::new_const( + 2200806265616284, + 1041996387620216, + 1275149397833084, + 1723371028064068, + ), + u64x4::new_const( + 603720163891275, + 2135593511176153, + 2049641644431548, + 1198460677818310, + ), + u64x4::new_const( + 1862491879401621, + 2008116580769441, + 626566325260235, + 1058308304975798, + ), + u64x4::new_const( + 628557314314858, + 1075323332046522, + 1631772244117095, + 1812174547405683, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1222773123817104, + 363276129291452, + 796237592807883, + 1914425291893078, + ), + u64x4::new_const( + 1721259057429088, + 734941709009373, + 1553365830564638, + 1492120931079419, + ), + u64x4::new_const( + 1009354843273686, + 293884504384873, + 1050281954944357, + 134132942667344, + ), + u64x4::new_const( + 23119363298711, + 1694754778833445, + 1725925193393496, + 1738396998222001, + ), + u64x4::new_const( + 1753692057254667, + 118428526447110, + 840961387840295, + 1227619055408558, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1004186117579547, + 508771992330056, + 1426571663072421, + 2238524171903259, + ), + u64x4::new_const( + 744764613007812, + 398885442368825, + 2047459490294949, + 2141797621077959, + ), + u64x4::new_const( + 4556204156489, + 1708213022802363, + 1071381560923933, + 393474529142567, + ), + u64x4::new_const( + 350116198213005, + 945907227204695, + 168267474358731, + 1801504420122711, + ), + u64x4::new_const( + 728788674520360, + 1262722049156121, + 455259596607008, + 1159442365834489, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2226818917892677, + 185673745808179, + 2240952219732549, + 324137961621908, + ), + u64x4::new_const( + 1659527641857410, + 973964060249383, + 1349692151487730, + 1172743533370593, + ), + u64x4::new_const( + 310591478467746, + 2123977244137170, + 774562885265820, + 430035546191685, + ), + u64x4::new_const( + 2150863173197992, + 2101978317708856, + 193592648406011, + 1375328504508580, + ), + u64x4::new_const( + 1946235834250479, + 121741431658675, + 1004342690620100, + 2063466488599450, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 463079632200153, + 40415275714025, + 545935352782679, + 1458043501600908, + ), + u64x4::new_const( + 783771976559993, + 880839641726471, + 1782028201271831, + 41664413404590, + ), + u64x4::new_const( + 985129151724159, + 187728621410000, + 16620051933318, + 378011085567733, + ), + u64x4::new_const( + 1820372198168638, + 905710046480679, + 1912961774249737, + 1868135861067161, + ), + u64x4::new_const( + 474460473983187, + 1455684425673661, + 652771171116843, + 733511920760779, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1088886980746809, + 1660218575261626, + 527921875040240, + 915086639857889, + ), + u64x4::new_const( + 1814735788528175, + 1586698876186367, + 2040856637532862, + 405684812785624, + ), + u64x4::new_const( + 658578559700999, + 1751442070931114, + 1293623371490094, + 715026719042518, + ), + u64x4::new_const( + 382156225644820, + 897982285504960, + 577673183555858, + 1158728558309719, + ), + u64x4::new_const( + 1865791902475663, + 124491617513788, + 758484125168765, + 734065580770143, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 330985690350617, + 2214424721795630, + 973374650780848, + 1507267060932964, + ), + u64x4::new_const( + 1733823971011290, + 1730742552292995, + 669018866977489, + 604527664126146, + ), + u64x4::new_const( + 1082092498645474, + 1029182053935309, + 756799947765834, + 1764720030308351, + ), + u64x4::new_const( + 969912105693756, + 38116887248276, + 2148030115687613, + 995140534653865, + ), + u64x4::new_const( + 2154373397460354, + 298128883464656, + 479587543632539, + 1061127201140779, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 843064865526549, + 2019481782959016, + 1873125524281672, + 2013330239022371, + ), + u64x4::new_const( + 1192932403815186, + 1818108671859220, + 1247005102016258, + 1210577394628058, + ), + u64x4::new_const( + 132359273326717, + 795492788299178, + 1235924489372816, + 891705064411550, + ), + u64x4::new_const( + 1425833709104858, + 152114045731085, + 991347902581315, + 1387773338707683, + ), + u64x4::new_const( + 48024203807922, + 157005564892977, + 1474053161953744, + 727448023498345, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1076621484026788, + 1309917234320927, + 1786998180233659, + 1595497085944737, + ), + u64x4::new_const( + 1737334672694726, + 2038133716999447, + 1929061192400917, + 620544235219084, + ), + u64x4::new_const( + 1550527313469747, + 329096759623509, + 1585214659209474, + 693419841748324, + ), + u64x4::new_const( + 1450010875912315, + 2085047082180569, + 757421110771886, + 389367139787400, + ), + u64x4::new_const( + 781339490566117, + 132941783448971, + 258650459725225, + 2042274962585613, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 859638991542650, + 2249840007426442, + 1138753070862357, + 793751342318913, + ), + u64x4::new_const( + 2133476133447306, + 1027010646129239, + 436851910892865, + 866949948830344, + ), + u64x4::new_const( + 1936003572431223, + 531513680252193, + 1929877059408416, + 830585477662503, + ), + u64x4::new_const( + 1460760405777960, + 686673748420916, + 275475330051554, + 1581792376993692, + ), + u64x4::new_const( + 894482039456784, + 1801274480988632, + 16407898635278, + 1668497039215206, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 258585746227669, + 936490904651492, + 1826793887434108, + 1201219990633823, + ), + u64x4::new_const( + 979462791643635, + 461762372210187, + 218708929991480, + 1378150755760178, + ), + u64x4::new_const( + 642542170229970, + 787135445552820, + 371168855880557, + 182642566486693, + ), + u64x4::new_const( + 1152277399721904, + 1726910452705576, + 1452393215705343, + 2117799581546845, + ), + u64x4::new_const( + 1211265143925330, + 14373046151823, + 1745528818271507, + 1842106288572078, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 635154614562157, + 1956763034454109, + 509123035953043, + 445727657534780, + ), + u64x4::new_const( + 2072765509783252, + 1282639891593570, + 1075086397362049, + 722996110178195, + ), + u64x4::new_const( + 1385572918825603, + 1190035835509576, + 218317841176013, + 1047865370756924, + ), + u64x4::new_const( + 473991569426488, + 1910588123704592, + 1338270051770806, + 401676861680875, + ), + u64x4::new_const( + 992455353618436, + 126422733426929, + 1955248037756399, + 119233843022643, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1555272991526078, + 2214378187116349, + 366893798097444, + 1401502118355702, + ), + u64x4::new_const( + 1157229521930713, + 2144787187506262, + 1681597469697840, + 847499096518697, + ), + u64x4::new_const( + 1872802655800758, + 1027119609820793, + 1137278714788290, + 1664750301179485, + ), + u64x4::new_const( + 1091289858897030, + 910126419483563, + 1101920147235731, + 597083075893952, + ), + u64x4::new_const( + 1711011533670315, + 185206680336278, + 1620960612579784, + 1968598849170880, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 73077300235958, + 257216723095630, + 466947267713785, + 847105214181598, + ), + u64x4::new_const( + 1322905631406309, + 407458059314731, + 230045063190376, + 923800751267786, + ), + u64x4::new_const( + 1146027205000415, + 1541328763727623, + 768510249199119, + 1630223587589059, + ), + u64x4::new_const( + 1930368769879433, + 1376145403022159, + 1898149855343131, + 1709421930518180, + ), + u64x4::new_const( + 633944191571764, + 58314960742839, + 2050971151574988, + 757799756090059, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 361576929158539, + 1035682890165818, + 160945739362874, + 266975208626222, + ), + u64x4::new_const( + 1635371797076046, + 2106722851965197, + 451585919077206, + 6692426667180, + ), + u64x4::new_const( + 175820543533852, + 2057511393764025, + 1531846543720469, + 1648320903946519, + ), + u64x4::new_const( + 947461770620940, + 1107335044817620, + 1725565474111216, + 2182263619949220, + ), + u64x4::new_const( + 726444888601221, + 1379664085279206, + 1517215633290417, + 1763968936542507, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 686545355846512, + 1712283265573167, + 1743509592736302, + 1653906616429153, + ), + u64x4::new_const( + 985108805667149, + 2244347650874753, + 1304749057936860, + 321846134330589, + ), + u64x4::new_const( + 296321076156886, + 1717929256240029, + 450933772486425, + 2015536856431605, + ), + u64x4::new_const( + 1690393512821866, + 646913049470189, + 2198650647576397, + 1230646705710442, + ), + u64x4::new_const( + 601961913448442, + 878806578800541, + 620497587492381, + 330716414244629, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 631510982676132, + 1755753187697174, + 1596201246674299, + 2197888384902121, + ), + u64x4::new_const( + 626957678275745, + 1447583371478595, + 1375375216702128, + 1443613232818823, + ), + u64x4::new_const( + 1962997804660501, + 1051744123184519, + 1002558639300437, + 1237313314603385, + ), + u64x4::new_const( + 2118828335274995, + 226398203764759, + 889099617161107, + 1620967117678504, + ), + u64x4::new_const( + 227261019362935, + 2046897556746842, + 591524060355369, + 2178552047369691, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1375403119051662, + 222313965014452, + 539873444241395, + 213198095917915, + ), + u64x4::new_const( + 1436952871599114, + 1229749762725246, + 1174441562267670, + 265367077740349, + ), + u64x4::new_const( + 11107426165917, + 985954476039181, + 1147329112365579, + 1133931640328107, + ), + u64x4::new_const( + 585235055006843, + 699515259687482, + 299559608721134, + 2134819767146767, + ), + u64x4::new_const( + 1376401105588528, + 391412107507860, + 302743651807545, + 1362834426455518, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1802940904616205, + 1615132760193234, + 869321663313735, + 666494072545310, + ), + u64x4::new_const( + 1452849320020701, + 1472716813676364, + 472862999490802, + 359937983286145, + ), + u64x4::new_const( + 1221198323133843, + 491718521756528, + 1387135774113906, + 793779904904008, + ), + u64x4::new_const( + 1032129287829151, + 30730741946697, + 217603185195068, + 2118169309744162, + ), + u64x4::new_const( + 225899335574721, + 1767553399797342, + 881082465669982, + 1435383196392870, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1127093564374276, + 2245188499702906, + 1250041622887441, + 2179324911668149, + ), + u64x4::new_const( + 908019210866875, + 1879900391060964, + 1355047706206597, + 647218945377302, + ), + u64x4::new_const( + 1616265604422592, + 2134336781521657, + 1157711219915601, + 1227494173135033, + ), + u64x4::new_const( + 136450294813355, + 1984543542455033, + 1199486053011083, + 33687889941331, + ), + u64x4::new_const( + 1053447012707371, + 68239344331930, + 537448158443925, + 1829189783369646, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 996806463322563, + 2043104667851348, + 1110361398300309, + 1218740346887957, + ), + u64x4::new_const( + 399141907016839, + 1307691109658227, + 532535384961264, + 896201194398872, + ), + u64x4::new_const( + 111705272106160, + 1790972382466021, + 1159338112559144, + 303544352897203, + ), + u64x4::new_const( + 1036600573322969, + 1457119922663674, + 334117653665514, + 460023361701263, + ), + u64x4::new_const( + 1363773215189933, + 1915594049343802, + 1661249423378694, + 1744945551969247, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 3093919631215, + 574886478077610, + 1704446919728971, + 250093147254210, + ), + u64x4::new_const( + 1387413348737796, + 360142717826981, + 2116185073015983, + 474541388374100, + ), + u64x4::new_const( + 1632539630892580, + 1332404016215719, + 2145297637794728, + 1289783723173504, + ), + u64x4::new_const( + 1030244179060173, + 579782698595797, + 1062365251139982, + 677149839815546, + ), + u64x4::new_const( + 6671539419876, + 1426937459653775, + 406942403696343, + 675479224223817, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 271984148441782, + 1708099625818957, + 1499011822959235, + 516808451044836, + ), + u64x4::new_const( + 1124847751346323, + 2038336022958449, + 1721698491022600, + 705944403212572, + ), + u64x4::new_const( + 85459783780275, + 1715213099986669, + 1728445509034791, + 730657630359717, + ), + u64x4::new_const( + 1185034652652387, + 755472578204310, + 476118360897817, + 1800434542785310, + ), + u64x4::new_const( + 1815589628676941, + 491778500674079, + 1547664984392513, + 279891608681267, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2036337168672113, + 1730787524684269, + 639134121311693, + 698060925015524, + ), + u64x4::new_const( + 315211075189491, + 1329055848835358, + 688621136402134, + 1271193060119448, + ), + u64x4::new_const( + 1697984374314012, + 459330773536457, + 305481314707918, + 61676911066002, + ), + u64x4::new_const( + 2166631826859191, + 2105217187401781, + 937587962768434, + 357397435365683, + ), + u64x4::new_const( + 1206757093145471, + 1287847622009294, + 1951336140421622, + 2233789834777410, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 82144190081093, + 1568417433687791, + 907555979158442, + 2037855062523867, + ), + u64x4::new_const( + 1225315484058853, + 315317868015613, + 1765025920288384, + 175223259828436, + ), + u64x4::new_const( + 1215010304871271, + 662713408454950, + 429517658575616, + 991062684008811, + ), + u64x4::new_const( + 993837615254894, + 1485561584889450, + 2001836754226476, + 1915943063896801, + ), + u64x4::new_const( + 818895101625673, + 1342479472068804, + 1380235330010671, + 23315169761453, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1500726307559118, + 956166860173424, + 512663951564436, + 1940180717699824, + ), + u64x4::new_const( + 1789521472720825, + 779456898652427, + 2035063615853504, + 863582140589407, + ), + u64x4::new_const( + 634508890793787, + 1748041666732214, + 259642099961634, + 1294936839797812, + ), + u64x4::new_const( + 2183334898697038, + 2197242820694806, + 2217225409073703, + 992633998226449, + ), + u64x4::new_const( + 2197077498155916, + 1562008797791883, + 1395088759904208, + 331715244679294, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 186854731652320, + 284389440026580, + 1252175415119400, + 1025377410100223, + ), + u64x4::new_const( + 1578732129417607, + 898645497852382, + 2237766074482974, + 1939197790303592, + ), + u64x4::new_const( + 1438830390640145, + 1682452015845597, + 1108441197232223, + 1984134492898664, + ), + u64x4::new_const( + 282668727301669, + 1609018289552856, + 390363439795705, + 1138459124667912, + ), + u64x4::new_const( + 18889015928490, + 532489638086725, + 324621535996080, + 2210046082697453, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2041327051605378, + 2244037852176483, + 2116336876147147, + 9616672544864, + ), + u64x4::new_const( + 969847387559191, + 1059119127679639, + 1764630094670633, + 364568045311834, + ), + u64x4::new_const( + 505938893153679, + 2075421412172902, + 326984153045666, + 1959549727324704, + ), + u64x4::new_const( + 1088715617911260, + 13917085151028, + 950568481355929, + 23687195265771, + ), + u64x4::new_const( + 1798284568673198, + 808382292203333, + 2214698741961545, + 610817203275867, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1731488929623777, + 1158815615106413, + 1491090861948525, + 1428384712900962, + ), + u64x4::new_const( + 722237139522457, + 1514290328911535, + 1366197913116230, + 1519472657321210, + ), + u64x4::new_const( + 246028966932273, + 1888239319448405, + 423720022211163, + 455243905681470, + ), + u64x4::new_const( + 738323403716001, + 1758018973481179, + 1180718299482318, + 1008495946606708, + ), + u64x4::new_const( + 334959381596119, + 1704599537529481, + 2172191232106896, + 13502508918495, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 273393076768079, + 427388720298603, + 1071733376018227, + 1715429388968611, + ), + u64x4::new_const( + 751776629892313, + 1965239102856011, + 541955408230119, + 831043488876080, + ), + u64x4::new_const( + 643718536393104, + 390543998404644, + 2176730661486279, + 499459234889079, + ), + u64x4::new_const( + 1482404333915009, + 865527293526285, + 507957951411713, + 216456252558825, + ), + u64x4::new_const( + 2210281256300231, + 1519357818277551, + 1257866936775246, + 1689605217672864, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2135395168187905, + 2214400157568614, + 2032983817870823, + 1124945109072647, + ), + u64x4::new_const( + 1602820011758145, + 906675633903289, + 782700735390986, + 2067218823525601, + ), + u64x4::new_const( + 786785748926382, + 1433583123655616, + 905839404290873, + 2249680349963778, + ), + u64x4::new_const( + 1940824582370584, + 1610961256326291, + 285307858781375, + 1755588655461194, + ), + u64x4::new_const( + 233682812055333, + 2146114223476434, + 41132209533476, + 535292431776371, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 600257696476418, + 18449221564824, + 1422209458591138, + 239571584769716, + ), + u64x4::new_const( + 2056372917056980, + 1155290566623531, + 1252473955568148, + 1276690716882081, + ), + u64x4::new_const( + 246974369025311, + 658117221519903, + 2000380937898441, + 1351183273924850, + ), + u64x4::new_const( + 1803747363753112, + 1736801515030186, + 2025633577199091, + 603378480769167, + ), + u64x4::new_const( + 57348749438551, + 1893551220299655, + 657926732731806, + 1522499384853705, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 591809128842736, + 284860517232591, + 27436696863545, + 886306697195798, + ), + u64x4::new_const( + 2113192175751749, + 1405882509906423, + 561316282804847, + 835573846576266, + ), + u64x4::new_const( + 94407289485409, + 1781534171669004, + 2098782516531528, + 598529921520053, + ), + u64x4::new_const( + 1860137004504786, + 2197323407480349, + 1516772733981532, + 961740253777086, + ), + u64x4::new_const( + 1484139612868217, + 1593557644636881, + 838834937143441, + 36382198263380, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1165898865828562, + 1153420815042389, + 1068625028915785, + 1945927229911090, + ), + u64x4::new_const( + 843454394017146, + 571029655293754, + 386282254545998, + 1804608237584150, + ), + u64x4::new_const( + 370552451091100, + 1279105656351124, + 1864742949668631, + 2093071521726981, + ), + u64x4::new_const( + 1872542389052198, + 1679083953574330, + 349872262454465, + 1470311090717925, + ), + u64x4::new_const( + 685345654160323, + 319718985807814, + 1359932285384164, + 1410900103316331, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 2083666668832889, + 314624387816655, + 1496694646480345, + 1946728950459189, + ), + u64x4::new_const( + 1579153761571203, + 508771185291380, + 1002249659402007, + 551517831173801, + ), + u64x4::new_const( + 2132371471626150, + 1988122278556533, + 1552195130653890, + 1327637750292755, + ), + u64x4::new_const( + 118937099181527, + 382610380973142, + 634951529106471, + 382740054041699, + ), + u64x4::new_const( + 801287519643470, + 87822941589258, + 1908825350108451, + 1404208826499115, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 330347226380261, + 672119116965146, + 1761510370768005, + 1959200302484704, + ), + u64x4::new_const( + 1631876583009250, + 1684917718484264, + 1027256947805920, + 2174612545251129, + ), + u64x4::new_const( + 636668855699872, + 625187713984839, + 265886954766790, + 167898557908504, + ), + u64x4::new_const( + 1210974548180860, + 2051308710365526, + 907620584086428, + 1081788677970850, + ), + u64x4::new_const( + 621792955460854, + 1450945504745382, + 1666728650687828, + 977937146451674, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 24725936182267, + 2226765032752574, + 2036560083102883, + 2002351185719584, + ), + u64x4::new_const( + 1620080779405308, + 1493220053370419, + 2245691691038916, + 1152182628629603, + ), + u64x4::new_const( + 317928527147500, + 1855194218440212, + 979380281964169, + 861442286685289, + ), + u64x4::new_const( + 393308472784625, + 486143087279967, + 1234071346236405, + 777748237119399, + ), + u64x4::new_const( + 43850412814718, + 1497656407486446, + 744128331046695, + 1618035787321792, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1670169946550211, + 1230951698726438, + 806586940221293, + 23159779184607, + ), + u64x4::new_const( + 634011340979302, + 764182085034744, + 731065727766955, + 1737985776442180, + ), + u64x4::new_const( + 240492712141842, + 73976435954441, + 162810587166835, + 697230894340912, + ), + u64x4::new_const( + 1299745598348388, + 1359436039694544, + 1856609816731554, + 25228008461513, + ), + u64x4::new_const( + 2180690501932381, + 2161211192848458, + 87069466793408, + 2003456332883860, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1106932458043379, + 1675181364231371, + 1681785724775243, + 131824742557210, + ), + u64x4::new_const( + 1671649414647169, + 1827849994880670, + 1097958057111899, + 701956891169434, + ), + u64x4::new_const( + 2095539283710881, + 591029812888096, + 1699571518315654, + 1297589045812566, + ), + u64x4::new_const( + 1345612272298537, + 2166754730876055, + 2047982622154948, + 1785222806258129, + ), + u64x4::new_const( + 2181915268829890, + 1895697064378670, + 1288412327355885, + 1561075738281368, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 741330264098392, + 357073519729966, + 1603572339180975, + 433572083688575, + ), + u64x4::new_const( + 699685108971208, + 1719650727634959, + 1941668009419214, + 870374958347891, + ), + u64x4::new_const( + 385971389331537, + 11655507719711, + 94814615497633, + 515572102810609, + ), + u64x4::new_const( + 1396688200590426, + 1518748475144123, + 162386454324368, + 2083303971579002, + ), + u64x4::new_const( + 1511688632419263, + 251584258592336, + 545345887993880, + 1229840230314160, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1298668855706029, + 2017860934939344, + 2224150456036391, + 1925926576297971, + ), + u64x4::new_const( + 259522963883544, + 1312469129541229, + 1647530465049600, + 1113737129047154, + ), + u64x4::new_const( + 733193298663145, + 2115712816303403, + 897628702762311, + 116440277571901, + ), + u64x4::new_const( + 1998719395229750, + 1662774553684237, + 194395608126452, + 98796702872301, + ), + u64x4::new_const( + 2226158244229144, + 91961728239158, + 526869903032152, + 849263805316773, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 472779569333556, + 854477760843410, + 2070906720349401, + 734613359834689, + ), + u64x4::new_const( + 1771897100487404, + 1604024196006064, + 319699348925383, + 437152129592623, + ), + u64x4::new_const( + 627618365135361, + 1768642666037955, + 588564169143939, + 35295037750744, + ), + u64x4::new_const( + 220241884231278, + 319104161410840, + 1048165719448798, + 1583931089774347, + ), + u64x4::new_const( + 166479451884333, + 1623611819962804, + 59990366193679, + 900727256046987, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 1944687327687331, + 1328410791053991, + 2083980670913902, + 609396833380574, + ), + u64x4::new_const( + 1907563845734496, + 1385619047697883, + 869817384774457, + 106642388505109, + ), + u64x4::new_const( + 1006516581737154, + 1561918369633937, + 1921172883211450, + 2216650451558824, + ), + u64x4::new_const( + 1780506017391778, + 233064930371847, + 1332962603425752, + 1380075261612354, + ), + u64x4::new_const( + 1907624789747741, + 1310065402098523, + 1838275780706825, + 884225500782782, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 198729830692545, + 100156148743413, + 2140568641558859, + 2220606475942394, + ), + u64x4::new_const( + 1108788217903741, + 1706330932366163, + 2050449866410661, + 684907598542847, + ), + u64x4::new_const( + 1101958322366646, + 659427843062405, + 253899933868173, + 896574852821269, + ), + u64x4::new_const( + 1157052140740658, + 440541103447032, + 2173354981480949, + 604768603561932, + ), + u64x4::new_const( + 961238337866054, + 830849154351308, + 1643852412409441, + 1436749321770368, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 784870637473285, + 1180234052037572, + 2086951602998715, + 419328169540373, + ), + u64x4::new_const( + 1966862397394559, + 788036164772123, + 2024355635709481, + 1471696676696146, + ), + u64x4::new_const( + 1468884300957205, + 1408016588131185, + 2229595828577885, + 240413942963547, + ), + u64x4::new_const( + 1481791691942441, + 970648959691160, + 1635500996148197, + 2236917233261585, + ), + u64x4::new_const( + 31660820731028, + 801794768903647, + 1069092619607344, + 282652554845923, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 911659428682786, + 762502588057038, + 1311399152500807, + 1966922911783311, + ), + u64x4::new_const( + 1229849228728540, + 258161307933217, + 2140796867375541, + 1569345075547911, + ), + u64x4::new_const( + 1487354676143742, + 1818317546165791, + 811033554173350, + 1768788663337616, + ), + u64x4::new_const( + 450017165913234, + 962535873747168, + 2099104262993585, + 503030952485785, + ), + u64x4::new_const( + 1259958681304518, + 479589250923541, + 1503904042161640, + 706283657294305, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 794562643024291, + 198670993088241, + 1678984629358943, + 273399517554618, + ), + u64x4::new_const( + 188458991574433, + 1389872130156447, + 1461868931574746, + 795140878721432, + ), + u64x4::new_const( + 624046647169653, + 630363741191019, + 911018499983500, + 1410140563046579, + ), + u64x4::new_const( + 1675056174405076, + 632544713589250, + 795454163559811, + 1535271563341780, + ), + u64x4::new_const( + 25504547444781, + 812510098987855, + 51290042016232, + 1992260991700127, + ), + ])), + CachedPoint(F51x4Reduced([ + u64x4::new_const( + 269968325452358, + 470932785179706, + 1684444304834150, + 1027482126748243, + ), + u64x4::new_const( + 457941065342419, + 2117377568137882, + 1209423706730905, + 2192403099717071, + ), + u64x4::new_const( + 1899046404863678, + 1359500336071762, + 1492389156724726, + 1455627081827750, + ), + u64x4::new_const( + 2016101061876546, + 1967000012916571, + 582539481696050, + 1197538178790094, + ), + u64x4::new_const( + 639684852217504, + 1799941252757449, + 1470016556327743, + 846111828965901, + ), + ])), +]); diff --git a/curve25519-dalek/src/backend/vector/ifma/edwards.rs b/curve25519-dalek/src/backend/vector/ifma/edwards.rs index f8605fe5..a53c5fe4 100644 --- a/curve25519-dalek/src/backend/vector/ifma/edwards.rs +++ b/curve25519-dalek/src/backend/vector/ifma/edwards.rs @@ -334,4 +334,25 @@ mod test { let P = constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); doubling_test_helper(P); } + + #[test] + fn basepoint_odd_lookup_table_verify() { + use crate::backend::vector::ifma::constants::BASEPOINT_ODD_LOOKUP_TABLE; + use crate::constants; + + let basepoint_odd_table = + NafLookupTable8::::from(&constants::ED25519_BASEPOINT_POINT); + println!("basepoint_odd_lookup_table = {:?}", basepoint_odd_table); + + let table_B = &BASEPOINT_ODD_LOOKUP_TABLE; + for (b_vec, base_vec) in table_B.0.iter().zip(basepoint_odd_table.0.iter()) { + let b_splits = b_vec.0.split(); + let base_splits = base_vec.0.split(); + + assert_eq!(base_splits[0], b_splits[0]); + assert_eq!(base_splits[1], b_splits[1]); + assert_eq!(base_splits[2], b_splits[2]); + assert_eq!(base_splits[3], b_splits[3]); + } + } } diff --git a/curve25519-dalek/src/backend/vector/scalar_mul/abglsv_pornin.rs b/curve25519-dalek/src/backend/vector/scalar_mul/abglsv_pornin.rs new file mode 100644 index 00000000..17bd1f1a --- /dev/null +++ b/curve25519-dalek/src/backend/vector/scalar_mul/abglsv_pornin.rs @@ -0,0 +1,213 @@ +// -*- mode: rust; -*- +// +// This file is part of curve25519-dalek. +// Copyright (c) 2020-2024 Jack Grigg +// See LICENSE for licensing information. +// +// Author: +// Jack Grigg +#![allow(non_snake_case)] + +#[curve25519_dalek_derive::unsafe_target_feature_specialize( + "avx2", + conditional("avx512ifma,avx512vl", nightly) +)] +pub mod spec { + #[for_target_feature("avx2")] + use crate::backend::vector::avx2::{CachedPoint, ExtendedPoint}; + + #[for_target_feature("avx512ifma")] + use crate::backend::vector::ifma::{CachedPoint, ExtendedPoint}; + + #[cfg(feature = "precomputed-tables")] + #[for_target_feature("avx2")] + use crate::backend::vector::avx2::constants::{ + BASEPOINT_ODD_LOOKUP_TABLE, B_SHL_128_ODD_LOOKUP_TABLE, + }; + + #[cfg(feature = "precomputed-tables")] + #[for_target_feature("avx512ifma")] + use crate::backend::vector::ifma::constants::{ + BASEPOINT_ODD_LOOKUP_TABLE, B_SHL_128_ODD_LOOKUP_TABLE, + }; + + use core::cmp::Ordering; + + use crate::{ + edwards::EdwardsPoint, + scalar::{lattice_reduction::find_short_vector, Scalar}, + traits::Identity, + window::NafLookupTable5, + }; + + /// Computes \\([δa]A + [δb]B - [δ]C\\) in variable time. + /// + /// - \\(B\\) is the Ed25519 basepoint. + /// - \\(δ\\) is a value invertible \\( \mod \ell \\), which is selected internally to + /// this function. + /// + /// This corresponds to the signature verification optimisation presented in + /// [Antipa et al 2005](http://cacr.uwaterloo.ca/techreports/2005/cacr2005-28.pdf). + pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar, C: &EdwardsPoint) -> EdwardsPoint { + // Starting with the target equation: + // + // [(δa mod l)]A + [(δb mod l)]B - [δ]C + // + // We can split δb mod l into two halves e_0 (128 bits) and e_1 (125 bits), and + // rewrite the equation as: + // + // [(δa mod l)]A + [e_0]B + [e_1 2^128]B - [δ]C + // + // B and [2^128]B are precomputed, and their resulting scalar multiplications each + // have half as many doublings. We therefore want to find a pair of signed integers + // + // (d_0, d_1) = (δa mod l, δ) + // + // that both have as few bits as possible, similarly reducing the number of doublings + // in the scalar multiplications [d_0]A and [d_1]C. This is equivalent to finding a + // short vector in a lattice of dimension 2. + + // Find a short vector. + let (d_0, d_1) = find_short_vector(a); + + // Move the signs of d_0 and d_1 into their corresponding bases and scalars. + let A = if d_0.is_negative() { -A } else { *A }; + let (b, negC) = if d_1.is_negative() { + (-b, *C) + } else { + (*b, -C) + }; + let d_0 = Scalar::from(d_0.unsigned_abs()); + let d_1 = Scalar::from(d_1.unsigned_abs()); + + // Calculate the remaining scalars. + let (e_0, e_1) = { + let db = b * d_1; + let mut e_0 = [0; 32]; + let mut e_1 = [0; 32]; + e_0[..16].copy_from_slice(&db.as_bytes()[..16]); + e_1[..16].copy_from_slice(&db.as_bytes()[16..]); + (Scalar { bytes: e_0 }, Scalar { bytes: e_1 }) + }; + + // Now we can compute the following using Straus's method: + // [d_0]A + [e_0]B + [e_1][2^128]B + [d_1][-C] + // + // We inline it here so we can use precomputed multiples of [2^128]B. + + let d_0_naf = d_0.non_adjacent_form(5); + + #[cfg(feature = "precomputed-tables")] + let e_0_naf = e_0.non_adjacent_form(8); + #[cfg(not(feature = "precomputed-tables"))] + let e_0_naf = e_0.non_adjacent_form(5); + + #[cfg(feature = "precomputed-tables")] + let e_1_naf = e_1.non_adjacent_form(8); + #[cfg(not(feature = "precomputed-tables"))] + let e_1_naf = e_1.non_adjacent_form(5); + + let d_1_naf = d_1.non_adjacent_form(5); + + // Find starting index + let mut i: usize = 255; + for j in (0..256).rev() { + i = j; + if d_0_naf[i] != 0 || e_0_naf[i] != 0 || e_1_naf[i] != 0 || d_1_naf[i] != 0 { + break; + } + } + + let table_A = NafLookupTable5::::from(&A); + + #[cfg(feature = "precomputed-tables")] + let table_B = &BASEPOINT_ODD_LOOKUP_TABLE; + #[cfg(not(feature = "precomputed-tables"))] + let table_B = + &NafLookupTable5::::from(&crate::constants::ED25519_BASEPOINT_POINT); + + #[cfg(feature = "precomputed-tables")] + let table_B_SHL_128 = &B_SHL_128_ODD_LOOKUP_TABLE; + #[cfg(not(feature = "precomputed-tables"))] + let table_B_SHL_128 = + &NafLookupTable5::::from(&crate::constants::ED25519_BASEPOINT_SHL_128); + + let table_negC = NafLookupTable5::::from(&negC); + + let mut Q = ExtendedPoint::identity(); + + loop { + Q = Q.double(); + + match d_0_naf[i].cmp(&0) { + Ordering::Greater => Q = &Q + &table_A.select(d_0_naf[i] as usize), + Ordering::Less => Q = &Q - &table_A.select(-d_0_naf[i] as usize), + Ordering::Equal => {} + } + + match e_0_naf[i].cmp(&0) { + Ordering::Greater => Q = &Q + &table_B.select(e_0_naf[i] as usize), + Ordering::Less => Q = &Q - &table_B.select(-e_0_naf[i] as usize), + Ordering::Equal => {} + } + + match e_1_naf[i].cmp(&0) { + Ordering::Greater => Q = &Q + &table_B_SHL_128.select(e_1_naf[i] as usize), + Ordering::Less => Q = &Q - &table_B_SHL_128.select(-e_1_naf[i] as usize), + Ordering::Equal => {} + } + + match d_1_naf[i].cmp(&0) { + Ordering::Greater => Q = &Q + &table_negC.select(d_1_naf[i] as usize), + Ordering::Less => Q = &Q - &table_negC.select(-d_1_naf[i] as usize), + Ordering::Equal => {} + } + + if i == 0 { + break; + } + i -= 1; + } + + Q.into() + } +} + +#[cfg(test)] +mod tests { + use crate::{ + backend::scalar_mul_abglsv_pornin as mul, constants::ED25519_BASEPOINT_POINT, + scalar::Scalar, traits::IsIdentity, + }; + + #[test] + fn test_mul() { + let a = Scalar::from(2u8); + let A = ED25519_BASEPOINT_POINT.double(); // [2]B + let b = Scalar::from(4u8); + let C = A.double().double(); // [8]B + + // The equation evaluates to the identity, so will be unaffected by δ. + assert_eq!( + mul(&a, &A, &b, &C), + (a * A) + (b * ED25519_BASEPOINT_POINT) - C + ); + + // Now test some random values. + let mut rng = rand::thread_rng(); + + for _ in 0..100 { + let a = Scalar::random(&mut rng); + let A = &Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT; + let b = Scalar::random(&mut rng); + + // With a correctly-constructed C, we get the identity. + let C = (a * A) + (b * ED25519_BASEPOINT_POINT); + assert!(mul(&a, &A, &b, &C).is_identity()); + + // With a random C, with high probability we do not get the identity. + let C = &Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT; + assert!(!mul(&a, &A, &b, &C).is_identity()); + } + } +} diff --git a/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs b/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs index fed3470e..e33b5961 100644 --- a/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs +++ b/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs @@ -11,6 +11,8 @@ //! Implementations of various multiplication algorithms for the SIMD backends. +pub mod abglsv_pornin; + #[allow(missing_docs)] pub mod variable_base;