From f8139da0b62c7c7ccff0b47e52a5b98e28576844 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Wed, 22 Feb 2017 22:47:55 +0000 Subject: [PATCH 001/101] We're not so yolo that we're not gonna test. Test yolocrypto by default. --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 14f00de..da90912 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ lto = false debug-assertions = true codegen-units = 1 panic = 'unwind' +required-features = ['yolocrypto'] # The benchmarking profile, used for `cargo bench`. [profile.bench] From a202f369164a6092694c8f6db43889209a445e55 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 22 Feb 2017 16:24:11 -0800 Subject: [PATCH 002/101] Rewrite invsqrt to avoid using an Option type. --- src/constants.rs | 3 ++- src/decaf.rs | 14 ++++++++------ src/field.rs | 50 ++++++++++++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 2f57e0e..a43677d 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1634,7 +1634,8 @@ mod test { fn test_sqrt_constants_sign() { let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); - let invsqrt_m1 = minus_one.invsqrt().unwrap(); + let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt(); + assert_eq!(was_nonzero_square, 1u8); let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1; let sign_test_msqrt = &invsqrt_m1 * &constants::MSQRT_M1; // XXX it seems we have flipped the sign relative to diff --git a/src/decaf.rs b/src/decaf.rs index 715190e..1b777c9 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -71,10 +71,12 @@ impl CompressedDecaf { let Z = &FieldElement::one() - &ss; // Z = 1+as^2 let u = &(&Z * &Z) - &(&constants::d4 * &ss); // u = Z^2 - 4ds^2 let uss = &u * &ss; - let mut v = match uss.invsqrt() { - Some(v) => v, - None => return None, - }; + + let (uss_is_nonzero_square, mut v) = uss.invsqrt(); + if (uss_is_nonzero_square | uss.is_zero()) == 0u8 { + return None; // us^2 is nonzero nonsquare + } + // Now v = 1/sqrt(us^2) if us^2 is a nonzero square, 0 if us^2 is zero. let uv = &v * &u; if uv.is_negative_decaf() == 1u8 { @@ -158,9 +160,9 @@ impl DecafPoint { let Z_plus_Y = &self.0.Z + &Y; let Z_minus_Y = &self.0.Z - &Y; let t = &constants::a_minus_d * &(&Z_plus_Y * &Z_minus_Y); + let (t_is_nonzero_square, mut r) = t.invsqrt(); // t should always be square (why?) - // XXX is it safe to use option types here? - let mut r = t.invsqrt().unwrap(); + debug_assert_eq!( t_is_nonzero_square | t.is_zero(), 1u8 ); // Step 2: Compute u = (a-d)r let u = &constants::a_minus_d * &r; diff --git a/src/field.rs b/src/field.rs index e0a1203..99bc104 100644 --- a/src/field.rs +++ b/src/field.rs @@ -215,6 +215,11 @@ impl FieldElement { FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + /// Construct -1. + pub fn minus_one() -> FieldElement { + FieldElement([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) + } + fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine let mut c = [0i64;10]; let mut h = input.clone(); @@ -817,18 +822,20 @@ impl FieldElement { t21 } - /// Try to compute 1/sqrt(self). + /// For `self` a nonzero square, compute 1/sqrt(self) in + /// constant time. + /// + /// It would be much better to use an `Option` type here, but + /// doing so forces the caller to branch, which we don't want to + /// do. This seems like the least bad solution. /// /// # Return /// - /// * If `self` is zero, returns zero. - /// * If `self` is square, returns 1/sqrt(self). - /// * If `self` is nonsquare, returns `None`. - pub fn invsqrt(&self) -> Option { - // We are to compute v as: - // / 1/sqrt(self) if self is square, nonzero; - // v = | 0 if self is zero; - // \ [reject] if self is nonsquare. + /// - `(1u8, 1/sqrt(self))` if `self` is a nonzero square; + /// - `(0u8, zero)` if `self` is zero; + /// - `(0u8, garbage)` if `self` is nonsquare. + /// + pub fn invsqrt(&self) -> (u8, FieldElement) { // // Using the same trick as in ed25519 decoding, we merge the // inversion, the square root, and the square test as follows. @@ -841,22 +848,23 @@ impl FieldElement { // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8) // = α^3 * (α^7)^((p-5)/8). // - // If α is square, then (1/β)^2 = ±(1/α), so that (1/β)^2 α = ±1. + // If α is nonzero square, then (1/β)^2 = ±(1/α), + // so that (1/β)^2 α = ±1. let a3 = &self.square() * self; // α^3 let a7 = &a3.square() * self; // α^7 let mut v = &a3 * &a7.pow_p58(); // α^(p-1-(p+3)/8) - let check = self * &v.square(); // ±1 if α is square + let check = self * &v.square(); // ±1 if α is nz square - if v.is_zero() == 1u8 { - return Some(v); // α was zero all along - } else if check == FieldElement::one() { - return Some(v); // computed the correct sqrt - } else if check == -&FieldElement::one() { - // wrong sign, multiply by sqrt(-1) - return Some(&v * &constants::SQRT_M1); - } else { - return None; // input was nonsquare - } + let correct_sign_sqrt = check.ct_eq(&FieldElement::one()); + let flipped_sign_sqrt = check.ct_eq(&FieldElement::minus_one()); + + // If check = -1, we're off by a factor of sqrt(-1). + let v_prime = &constants::SQRT_M1 * &v; + v.conditional_assign(&v_prime, flipped_sign_sqrt); + + let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; + + (was_nonzero_square, v) } /// chi calculates `self^((p-1)/2)`. From 1febf3f75331576c962c24f9a1fce077977bec34 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 22 Feb 2017 17:33:08 -0800 Subject: [PATCH 003/101] Add an invsqrt_ratio function. --- src/field.rs | 85 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/src/field.rs b/src/field.rs index 99bc104..08e2990 100644 --- a/src/field.rs +++ b/src/field.rs @@ -822,6 +822,61 @@ impl FieldElement { t21 } + /// Given `FieldElements` `u` and `v`, attempt to compute + /// `sqrt(u/v)` in constant time. + /// + /// It would be much better to use an `Option` type here, but + /// doing so forces the caller to branch, which we don't want to + /// do. This seems like the least bad solution. + /// + /// # Return + /// + /// - `(1u8, sqrt(u/v))` if `v` is nonzero and `u/v` is square; + /// - `(0u8, zero)` if `v` is zero; + /// - `(0u8, garbage)` if `u/v` is nonsquare. + /// + pub fn sqrt_ratio(u: &FieldElement, v: &FieldElement) + -> (u8, FieldElement) { + // Using the same trick as in ed25519 decoding, we merge the + // inversion, the square root, and the square test as follows. + // + // To compute sqrt(α), we can compute β = α^((p+3)/8). + // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary + // gives sqrt(α). + // + // To compute 1/sqrt(α), we observe that + // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8) + // = α^3 * (α^7)^((p-5)/8). + // + // We can therefore compute sqrt(u/v) = sqrt(u)/sqrt(v) + // by first computing + // r = u^((p+3)/8) v^(p-1-(p+3)/8) + // = u u^((p-5)/8) v^3 (v^7)^((p-5)/8) + // = (uv^3) (uv^7)^((p-5)/8). + // + // If v is nonzero and u/v is square, then r^2 = ±u/v, + // so vr^2 = ±u. + // If vr^2 = u, then sqrt(u/v) = r. + // If vr^2 = -u, then sqrt(u/v) = r*sqrt(-1). + // + // If v is zero, r is also zero. + + let v3 = &v.square() * v; + let v7 = &v3.square() * v; + let mut r = &(u * &v3) * &(u * &v7).pow_p58(); + let check = v * &r.square(); + + let correct_sign_sqrt = check.ct_eq( u); + let flipped_sign_sqrt = check.ct_eq(&(-u)); + + let r_prime = &constants::SQRT_M1 * &r; + r.conditional_assign(&r_prime, flipped_sign_sqrt); + + let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; + + (was_nonzero_square, r) + } + /// For `self` a nonzero square, compute 1/sqrt(self) in /// constant time. /// @@ -836,35 +891,7 @@ impl FieldElement { /// - `(0u8, garbage)` if `self` is nonsquare. /// pub fn invsqrt(&self) -> (u8, FieldElement) { - // - // Using the same trick as in ed25519 decoding, we merge the - // inversion, the square root, and the square test as follows. - // - // To compute sqrt(α), we can compute β = α^((p+3)/8). - // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary - // gives sqrt(α). - // - // To compute 1/sqrt(α), we observe that - // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8) - // = α^3 * (α^7)^((p-5)/8). - // - // If α is nonzero square, then (1/β)^2 = ±(1/α), - // so that (1/β)^2 α = ±1. - let a3 = &self.square() * self; // α^3 - let a7 = &a3.square() * self; // α^7 - let mut v = &a3 * &a7.pow_p58(); // α^(p-1-(p+3)/8) - let check = self * &v.square(); // ±1 if α is nz square - - let correct_sign_sqrt = check.ct_eq(&FieldElement::one()); - let flipped_sign_sqrt = check.ct_eq(&FieldElement::minus_one()); - - // If check = -1, we're off by a factor of sqrt(-1). - let v_prime = &constants::SQRT_M1 * &v; - v.conditional_assign(&v_prime, flipped_sign_sqrt); - - let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; - - (was_nonzero_square, v) + FieldElement::sqrt_ratio(&FieldElement::one(), self) } /// chi calculates `self^((p-1)/2)`. From d450659b7fb9995763b5cf1a6eb934400f317daa Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 22 Feb 2017 20:51:44 -0800 Subject: [PATCH 004/101] Rewrite `CompressedEdwardsY::decompress()` to use `FieldElement::sqrt_ratio` --- src/curve.rs | 49 ++++++++++++++----------------------------------- src/field.rs | 12 ++++++------ 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 5d770d1..ba6416f 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -127,45 +127,24 @@ impl CompressedEdwardsY { /// Attempt to decompress to an `ExtendedPoint`. /// - /// # Warning - /// - /// This function will fail and return None if both vx²-u=0 and vx²+u=0. + /// Returns `None` if the input is not the `y`-coordinate of a + /// curve point. pub fn decompress(&self) -> Option { // FromBytes() - let mut u: FieldElement; - let mut v: FieldElement; - let v3: FieldElement; - let vxx: FieldElement; + let Y = FieldElement::from_bytes(&self.0); + let Z = FieldElement::one(); + let YY = Y.square(); + let u = &YY - &Z; // u = y²-1 + let v = &(&YY * &constants::d) + &Z; // v = dy²+1 + let (is_nonzero_square, mut X) = FieldElement::sqrt_ratio(&u, &v); - let mut X: FieldElement; - let Y: FieldElement; - let Z: FieldElement; - let T: FieldElement; + if is_nonzero_square != 1u8 { return None; } - Y = FieldElement::from_bytes(&self.0); - Z = FieldElement::one(); + // Flip the sign of X if it's not correct + let compressed_sign_bit = self[31] >> 7; + let current_sign_bit = X.is_negative_ed25519(); + X.conditional_negate(current_sign_bit ^ compressed_sign_bit); - u = Y.square(); - v = &u * &constants::d; - u -= &Z; // u = y²-1 - v += &Z; // v = dy²+1 - v3 = &v.square() * &v; // v3 = v³ - X = (&v3.square() * &(&v * &u)).pow_p58(); // x = (uv⁷)^((q-5)/8) - X *= &(&u * &v3); // x = (uv³)(uv⁷)^((q-5)/8) - - vxx = &v * &X.square(); - if (&vxx - &u).is_nonzero() == 1 { // vx²-u - if (&vxx + &u).is_nonzero() == 1 { // vx²+u - return None; - } - X *= &constants::SQRT_M1; - } - - if X.is_negative_ed25519() != (self[31] >> 7) as i32 { - X = X.neg(); - } - T = &X * &Y; - - Some(ExtendedPoint{ X: X, Y: Y, Z: Z, T: T }) + Some(ExtendedPoint{ X: X, Y: Y, Z: Z, T: &X * &Y }) } } diff --git a/src/field.rs b/src/field.rs index 08e2990..926804e 100644 --- a/src/field.rs +++ b/src/field.rs @@ -517,16 +517,16 @@ impl FieldElement { (!equal_so_far & 1 & greater) as u8 } - /// Determine if this `FieldElement` is negative, in the - /// sense used in the ed25519 paper. + /// Determine if this `FieldElement` is negative, in the sense + /// used in the ed25519 paper: `x` is negative if the low bit is + /// set. /// /// # Return /// - /// If negative, return `1i32`. Otherwise, return `0i32`. - // XXX should return u8 - pub fn is_negative_ed25519(&self) -> i32 { //FeIsNegative + /// If negative, return `1u8`. Otherwise, return `0u8`. + pub fn is_negative_ed25519(&self) -> u8 { //FeIsNegative let bytes = self.to_bytes(); - (bytes[0] & 1) as i32 + (bytes[0] & 1) as u8 } /// Determine if this `FieldElement` is negative, in the From a649ea38eeba1d2d5d5b841699a28fce84313524 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 25 Feb 2017 00:47:06 +0000 Subject: [PATCH 005/101] =?UTF-8?q?Rename=20{PreComputed,Cached}Point=20?= =?UTF-8?q?=E2=86=92=20{Affine,Projective}NielsPoint.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FIXES Issue #28: https://github.com/isislovecruft/curve25519-dalek/issues/28 --- src/constants.rs | 536 +++++++++++++++++++++++------------------------ src/curve.rs | 116 +++++----- 2 files changed, 327 insertions(+), 325 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 2f57e0e..3483b95 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -21,7 +21,7 @@ use field::FieldElement; use curve::ExtendedPoint; -use curve::PreComputedPoint; +use curve::AffineNielsPoint; use curve::CompressedEdwardsY; use scalar::Scalar; @@ -173,43 +173,43 @@ pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ }, ]; -pub const bi: [PreComputedPoint; 8] = [ - PreComputedPoint{ +pub const bi: [AffineNielsPoint; 8] = [ + AffineNielsPoint{ y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), y_minus_x: FieldElement([-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378]), xy2d: FieldElement([-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024]), y_minus_x: FieldElement([16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574]), xy2d: FieldElement([30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380]), y_minus_x: FieldElement([4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306]), xy2d: FieldElement([19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766]), y_minus_x: FieldElement([-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701]), xy2d: FieldElement([28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877]), y_minus_x: FieldElement([-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951]), xy2d: FieldElement([4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436]), y_minus_x: FieldElement([25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918]), xy2d: FieldElement([23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800]), y_minus_x: FieldElement([-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305]), xy2d: FieldElement([-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876]), y_minus_x: FieldElement([-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619]), xy2d: FieldElement([-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683]), @@ -220,1346 +220,1346 @@ pub const bi: [PreComputedPoint; 8] = [ /// /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`, /// for `0 ≤ i < 32`, `1 ≤ j < 9`. -pub const base: [[PreComputedPoint; 8]; 32] = [ +pub const base: [[AffineNielsPoint; 8]; 32] = [ [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), y_minus_x: FieldElement([-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378]), xy2d: FieldElement([-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303]), y_minus_x: FieldElement([-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081]), xy2d: FieldElement([26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024]), y_minus_x: FieldElement([16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574]), xy2d: FieldElement([30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540]), y_minus_x: FieldElement([23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397]), xy2d: FieldElement([7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380]), y_minus_x: FieldElement([4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306]), xy2d: FieldElement([19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777]), y_minus_x: FieldElement([-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737]), xy2d: FieldElement([-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766]), y_minus_x: FieldElement([-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701]), xy2d: FieldElement([28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726]), y_minus_x: FieldElement([-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955]), xy2d: FieldElement([27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171]), y_minus_x: FieldElement([27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510]), xy2d: FieldElement([17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639]), y_minus_x: FieldElement([29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963]), xy2d: FieldElement([5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568]), y_minus_x: FieldElement([12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335]), xy2d: FieldElement([25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007]), y_minus_x: FieldElement([-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772]), xy2d: FieldElement([-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567]), y_minus_x: FieldElement([13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686]), xy2d: FieldElement([21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887]), y_minus_x: FieldElement([-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954]), xy2d: FieldElement([-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833]), y_minus_x: FieldElement([-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532]), xy2d: FieldElement([-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268]), y_minus_x: FieldElement([33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214]), xy2d: FieldElement([1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800]), y_minus_x: FieldElement([4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645]), xy2d: FieldElement([-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933]), y_minus_x: FieldElement([-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182]), xy2d: FieldElement([-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991]), y_minus_x: FieldElement([20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880]), xy2d: FieldElement([9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295]), y_minus_x: FieldElement([19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788]), xy2d: FieldElement([8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026]), y_minus_x: FieldElement([11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347]), xy2d: FieldElement([-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395]), y_minus_x: FieldElement([-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278]), xy2d: FieldElement([1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995]), y_minus_x: FieldElement([-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596]), xy2d: FieldElement([-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060]), y_minus_x: FieldElement([11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608]), xy2d: FieldElement([-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389]), y_minus_x: FieldElement([-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016]), xy2d: FieldElement([-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505]), y_minus_x: FieldElement([14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553]), xy2d: FieldElement([-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220]), y_minus_x: FieldElement([12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631]), xy2d: FieldElement([-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556]), y_minus_x: FieldElement([14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749]), xy2d: FieldElement([236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391]), y_minus_x: FieldElement([5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253]), xy2d: FieldElement([20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958]), y_minus_x: FieldElement([-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082]), xy2d: FieldElement([-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521]), y_minus_x: FieldElement([-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807]), xy2d: FieldElement([23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134]), y_minus_x: FieldElement([-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455]), xy2d: FieldElement([27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069]), y_minus_x: FieldElement([-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746]), xy2d: FieldElement([24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837]), y_minus_x: FieldElement([8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906]), xy2d: FieldElement([-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817]), y_minus_x: FieldElement([10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098]), xy2d: FieldElement([10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504]), y_minus_x: FieldElement([-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727]), xy2d: FieldElement([28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003]), y_minus_x: FieldElement([-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605]), xy2d: FieldElement([-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701]), y_minus_x: FieldElement([-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683]), xy2d: FieldElement([29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563]), y_minus_x: FieldElement([-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260]), xy2d: FieldElement([-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672]), y_minus_x: FieldElement([23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686]), xy2d: FieldElement([-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182]), y_minus_x: FieldElement([-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277]), xy2d: FieldElement([14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474]), y_minus_x: FieldElement([-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539]), xy2d: FieldElement([-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970]), y_minus_x: FieldElement([19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756]), xy2d: FieldElement([-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683]), y_minus_x: FieldElement([-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655]), xy2d: FieldElement([-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125]), y_minus_x: FieldElement([-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839]), xy2d: FieldElement([-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294]), y_minus_x: FieldElement([-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899]), xy2d: FieldElement([-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294]), y_minus_x: FieldElement([-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949]), xy2d: FieldElement([-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420]), y_minus_x: FieldElement([-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940]), xy2d: FieldElement([29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567]), y_minus_x: FieldElement([20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127]), xy2d: FieldElement([-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887]), y_minus_x: FieldElement([22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964]), xy2d: FieldElement([16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244]), y_minus_x: FieldElement([24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999]), xy2d: FieldElement([-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274]), y_minus_x: FieldElement([-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236]), xy2d: FieldElement([-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761]), y_minus_x: FieldElement([-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884]), xy2d: FieldElement([-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638]), y_minus_x: FieldElement([-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490]), xy2d: FieldElement([-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736]), y_minus_x: FieldElement([10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124]), xy2d: FieldElement([-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029]), y_minus_x: FieldElement([6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048]), xy2d: FieldElement([28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593]), y_minus_x: FieldElement([26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071]), xy2d: FieldElement([-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687]), y_minus_x: FieldElement([-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441]), xy2d: FieldElement([-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460]), y_minus_x: FieldElement([-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007]), xy2d: FieldElement([-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005]), y_minus_x: FieldElement([-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674]), xy2d: FieldElement([4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590]), y_minus_x: FieldElement([-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957]), xy2d: FieldElement([-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740]), y_minus_x: FieldElement([-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122]), xy2d: FieldElement([-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885]), y_minus_x: FieldElement([26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140]), xy2d: FieldElement([19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155]), y_minus_x: FieldElement([19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260]), xy2d: FieldElement([19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677]), y_minus_x: FieldElement([32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815]), xy2d: FieldElement([22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203]), y_minus_x: FieldElement([-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208]), xy2d: FieldElement([1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850]), y_minus_x: FieldElement([-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389]), xy2d: FieldElement([-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689]), y_minus_x: FieldElement([14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880]), xy2d: FieldElement([5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632]), y_minus_x: FieldElement([-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412]), xy2d: FieldElement([20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038]), y_minus_x: FieldElement([-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232]), xy2d: FieldElement([-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856]), y_minus_x: FieldElement([23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738]), xy2d: FieldElement([15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718]), y_minus_x: FieldElement([-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697]), xy2d: FieldElement([-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912]), y_minus_x: FieldElement([-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358]), xy2d: FieldElement([3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307]), y_minus_x: FieldElement([-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977]), xy2d: FieldElement([-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644]), y_minus_x: FieldElement([-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616]), xy2d: FieldElement([-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099]), y_minus_x: FieldElement([29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341]), xy2d: FieldElement([-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646]), y_minus_x: FieldElement([31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425]), xy2d: FieldElement([-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743]), y_minus_x: FieldElement([-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822]), xy2d: FieldElement([-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985]), y_minus_x: FieldElement([9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702]), xy2d: FieldElement([-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293]), y_minus_x: FieldElement([27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100]), xy2d: FieldElement([19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186]), y_minus_x: FieldElement([2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610]), xy2d: FieldElement([-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220]), y_minus_x: FieldElement([915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025]), xy2d: FieldElement([32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992]), y_minus_x: FieldElement([-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027]), xy2d: FieldElement([21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901]), y_minus_x: FieldElement([31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952]), xy2d: FieldElement([19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390]), y_minus_x: FieldElement([32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730]), xy2d: FieldElement([2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180]), y_minus_x: FieldElement([-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272]), xy2d: FieldElement([-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970]), y_minus_x: FieldElement([-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772]), xy2d: FieldElement([-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750]), y_minus_x: FieldElement([20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373]), xy2d: FieldElement([32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144]), y_minus_x: FieldElement([-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195]), xy2d: FieldElement([5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684]), y_minus_x: FieldElement([-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518]), xy2d: FieldElement([-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793]), y_minus_x: FieldElement([-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794]), xy2d: FieldElement([580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921]), y_minus_x: FieldElement([13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518]), xy2d: FieldElement([2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278]), y_minus_x: FieldElement([-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024]), xy2d: FieldElement([4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783]), y_minus_x: FieldElement([27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717]), xy2d: FieldElement([6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333]), y_minus_x: FieldElement([16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048]), xy2d: FieldElement([22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760]), y_minus_x: FieldElement([-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757]), xy2d: FieldElement([-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468]), y_minus_x: FieldElement([3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184]), xy2d: FieldElement([10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066]), y_minus_x: FieldElement([24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882]), xy2d: FieldElement([13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101]), y_minus_x: FieldElement([29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279]), xy2d: FieldElement([-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709]), y_minus_x: FieldElement([20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714]), xy2d: FieldElement([-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464]), y_minus_x: FieldElement([12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847]), xy2d: FieldElement([13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414]), y_minus_x: FieldElement([-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158]), xy2d: FieldElement([17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415]), y_minus_x: FieldElement([-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459]), xy2d: FieldElement([-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412]), y_minus_x: FieldElement([-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743]), xy2d: FieldElement([-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022]), y_minus_x: FieldElement([18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429]), xy2d: FieldElement([-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861]), y_minus_x: FieldElement([10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000]), xy2d: FieldElement([-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815]), y_minus_x: FieldElement([29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642]), xy2d: FieldElement([10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574]), y_minus_x: FieldElement([-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742]), xy2d: FieldElement([-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020]), y_minus_x: FieldElement([-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772]), xy2d: FieldElement([3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953]), y_minus_x: FieldElement([-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218]), xy2d: FieldElement([-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073]), y_minus_x: FieldElement([-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325]), xy2d: FieldElement([-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870]), y_minus_x: FieldElement([-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863]), xy2d: FieldElement([-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267]), y_minus_x: FieldElement([-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663]), xy2d: FieldElement([22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673]), y_minus_x: FieldElement([15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943]), xy2d: FieldElement([15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238]), y_minus_x: FieldElement([11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064]), xy2d: FieldElement([14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052]), y_minus_x: FieldElement([-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904]), xy2d: FieldElement([29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979]), y_minus_x: FieldElement([-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841]), xy2d: FieldElement([10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324]), y_minus_x: FieldElement([-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940]), xy2d: FieldElement([10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184]), y_minus_x: FieldElement([14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114]), xy2d: FieldElement([30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784]), y_minus_x: FieldElement([-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091]), xy2d: FieldElement([-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208]), y_minus_x: FieldElement([10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864]), xy2d: FieldElement([17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233]), y_minus_x: FieldElement([26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212]), xy2d: FieldElement([-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068]), y_minus_x: FieldElement([9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397]), xy2d: FieldElement([-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889]), y_minus_x: FieldElement([32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038]), xy2d: FieldElement([14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875]), y_minus_x: FieldElement([-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905]), xy2d: FieldElement([-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818]), y_minus_x: FieldElement([27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714]), xy2d: FieldElement([10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931]), y_minus_x: FieldElement([-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024]), xy2d: FieldElement([-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204]), y_minus_x: FieldElement([20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817]), xy2d: FieldElement([27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504]), y_minus_x: FieldElement([-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768]), xy2d: FieldElement([-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790]), y_minus_x: FieldElement([1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438]), xy2d: FieldElement([-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971]), y_minus_x: FieldElement([31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905]), xy2d: FieldElement([29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409]), y_minus_x: FieldElement([6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499]), xy2d: FieldElement([-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664]), y_minus_x: FieldElement([-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324]), xy2d: FieldElement([-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990]), y_minus_x: FieldElement([-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914]), xy2d: FieldElement([-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257]), y_minus_x: FieldElement([-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433]), xy2d: FieldElement([-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045]), y_minus_x: FieldElement([11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093]), xy2d: FieldElement([-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191]), y_minus_x: FieldElement([-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507]), xy2d: FieldElement([-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018]), y_minus_x: FieldElement([-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109]), xy2d: FieldElement([-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528]), y_minus_x: FieldElement([8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625]), xy2d: FieldElement([-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033]), y_minus_x: FieldElement([27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866]), xy2d: FieldElement([21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075]), y_minus_x: FieldElement([26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347]), xy2d: FieldElement([-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165]), y_minus_x: FieldElement([-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588]), xy2d: FieldElement([-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017]), y_minus_x: FieldElement([-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883]), xy2d: FieldElement([21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043]), y_minus_x: FieldElement([29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663]), xy2d: FieldElement([-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860]), y_minus_x: FieldElement([2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466]), xy2d: FieldElement([-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997]), y_minus_x: FieldElement([-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295]), xy2d: FieldElement([-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385]), y_minus_x: FieldElement([18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109]), xy2d: FieldElement([2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424]), y_minus_x: FieldElement([-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185]), xy2d: FieldElement([7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325]), y_minus_x: FieldElement([10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593]), xy2d: FieldElement([696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644]), y_minus_x: FieldElement([17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801]), xy2d: FieldElement([26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884]), y_minus_x: FieldElement([-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577]), xy2d: FieldElement([-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473]), y_minus_x: FieldElement([-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644]), xy2d: FieldElement([-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599]), y_minus_x: FieldElement([-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768]), xy2d: FieldElement([-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328]), y_minus_x: FieldElement([-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369]), xy2d: FieldElement([20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815]), y_minus_x: FieldElement([-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025]), xy2d: FieldElement([-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448]), y_minus_x: FieldElement([6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981]), xy2d: FieldElement([30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501]), y_minus_x: FieldElement([17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073]), xy2d: FieldElement([-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845]), y_minus_x: FieldElement([-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211]), xy2d: FieldElement([18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096]), y_minus_x: FieldElement([33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803]), xy2d: FieldElement([-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965]), y_minus_x: FieldElement([-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505]), xy2d: FieldElement([18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782]), y_minus_x: FieldElement([5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900]), xy2d: FieldElement([-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208]), y_minus_x: FieldElement([8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232]), xy2d: FieldElement([17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271]), y_minus_x: FieldElement([-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326]), xy2d: FieldElement([-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300]), y_minus_x: FieldElement([8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570]), xy2d: FieldElement([15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994]), y_minus_x: FieldElement([-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913]), xy2d: FieldElement([31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730]), y_minus_x: FieldElement([842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096]), xy2d: FieldElement([-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411]), y_minus_x: FieldElement([-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905]), xy2d: FieldElement([-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870]), y_minus_x: FieldElement([-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498]), xy2d: FieldElement([12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677]), y_minus_x: FieldElement([10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647]), xy2d: FieldElement([-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468]), y_minus_x: FieldElement([21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375]), xy2d: FieldElement([-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725]), y_minus_x: FieldElement([-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612]), xy2d: FieldElement([-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944]), y_minus_x: FieldElement([30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928]), xy2d: FieldElement([9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139]), y_minus_x: FieldElement([-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963]), xy2d: FieldElement([-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734]), y_minus_x: FieldElement([-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680]), xy2d: FieldElement([-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931]), y_minus_x: FieldElement([-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654]), xy2d: FieldElement([22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180]), y_minus_x: FieldElement([-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684]), xy2d: FieldElement([-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501]), y_minus_x: FieldElement([-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413]), xy2d: FieldElement([6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874]), y_minus_x: FieldElement([22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962]), xy2d: FieldElement([-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152]), y_minus_x: FieldElement([9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063]), xy2d: FieldElement([7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146]), y_minus_x: FieldElement([-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183]), xy2d: FieldElement([-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421]), y_minus_x: FieldElement([-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622]), xy2d: FieldElement([-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663]), y_minus_x: FieldElement([31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753]), xy2d: FieldElement([4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862]), y_minus_x: FieldElement([-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118]), xy2d: FieldElement([26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380]), y_minus_x: FieldElement([16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824]), xy2d: FieldElement([28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438]), y_minus_x: FieldElement([-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584]), xy2d: FieldElement([-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471]), y_minus_x: FieldElement([18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610]), xy2d: FieldElement([19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650]), y_minus_x: FieldElement([14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369]), xy2d: FieldElement([19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462]), y_minus_x: FieldElement([-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793]), xy2d: FieldElement([-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226]), y_minus_x: FieldElement([18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019]), xy2d: FieldElement([-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171]), y_minus_x: FieldElement([-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132]), xy2d: FieldElement([-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181]), y_minus_x: FieldElement([-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210]), xy2d: FieldElement([-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935]), y_minus_x: FieldElement([24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105]), xy2d: FieldElement([-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852]), y_minus_x: FieldElement([5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581]), xy2d: FieldElement([-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844]), y_minus_x: FieldElement([10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025]), xy2d: FieldElement([27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068]), y_minus_x: FieldElement([4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192]), xy2d: FieldElement([-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259]), y_minus_x: FieldElement([-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426]), xy2d: FieldElement([-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305]), y_minus_x: FieldElement([13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832]), xy2d: FieldElement([28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011]), y_minus_x: FieldElement([24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447]), xy2d: FieldElement([17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245]), y_minus_x: FieldElement([-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859]), xy2d: FieldElement([28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707]), y_minus_x: FieldElement([10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848]), xy2d: FieldElement([-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391]), y_minus_x: FieldElement([15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215]), xy2d: FieldElement([-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713]), y_minus_x: FieldElement([21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849]), xy2d: FieldElement([-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940]), y_minus_x: FieldElement([-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031]), xy2d: FieldElement([-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243]), y_minus_x: FieldElement([-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116]), xy2d: FieldElement([-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509]), y_minus_x: FieldElement([-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883]), xy2d: FieldElement([15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660]), y_minus_x: FieldElement([4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273]), xy2d: FieldElement([-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560]), y_minus_x: FieldElement([-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135]), xy2d: FieldElement([2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739]), y_minus_x: FieldElement([18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756]), xy2d: FieldElement([-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347]), y_minus_x: FieldElement([-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028]), xy2d: FieldElement([21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799]), y_minus_x: FieldElement([-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609]), xy2d: FieldElement([-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989]), y_minus_x: FieldElement([-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523]), xy2d: FieldElement([4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045]), y_minus_x: FieldElement([19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377]), xy2d: FieldElement([24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016]), y_minus_x: FieldElement([510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426]), xy2d: FieldElement([18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396]), y_minus_x: FieldElement([9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080]), xy2d: FieldElement([12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275]), y_minus_x: FieldElement([11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074]), xy2d: FieldElement([20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717]), y_minus_x: FieldElement([-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101]), xy2d: FieldElement([24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632]), y_minus_x: FieldElement([-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415]), xy2d: FieldElement([-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876]), y_minus_x: FieldElement([22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625]), xy2d: FieldElement([-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164]), y_minus_x: FieldElement([26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595]), xy2d: FieldElement([-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858]), y_minus_x: FieldElement([15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193]), xy2d: FieldElement([8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942]), y_minus_x: FieldElement([-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635]), xy2d: FieldElement([21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935]), y_minus_x: FieldElement([-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415]), xy2d: FieldElement([-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018]), y_minus_x: FieldElement([4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778]), xy2d: FieldElement([366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385]), y_minus_x: FieldElement([18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503]), xy2d: FieldElement([476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056]), y_minus_x: FieldElement([-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838]), xy2d: FieldElement([24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691]), y_minus_x: FieldElement([-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118]), xy2d: FieldElement([-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269]), y_minus_x: FieldElement([-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904]), xy2d: FieldElement([-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193]), y_minus_x: FieldElement([-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910]), xy2d: FieldElement([-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667]), y_minus_x: FieldElement([25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481]), xy2d: FieldElement([-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640]), y_minus_x: FieldElement([-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278]), xy2d: FieldElement([-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272]), y_minus_x: FieldElement([17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012]), xy2d: FieldElement([-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046]), y_minus_x: FieldElement([13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345]), xy2d: FieldElement([-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937]), y_minus_x: FieldElement([31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636]), xy2d: FieldElement([-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429]), y_minus_x: FieldElement([-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576]), xy2d: FieldElement([31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490]), y_minus_x: FieldElement([-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104]), xy2d: FieldElement([33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275]), y_minus_x: FieldElement([-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511]), xy2d: FieldElement([22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439]), y_minus_x: FieldElement([23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939]), xy2d: FieldElement([-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310]), y_minus_x: FieldElement([3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608]), xy2d: FieldElement([-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101]), y_minus_x: FieldElement([21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418]), xy2d: FieldElement([18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356]), y_minus_x: FieldElement([9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996]), xy2d: FieldElement([-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728]), y_minus_x: FieldElement([-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658]), xy2d: FieldElement([-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001]), y_minus_x: FieldElement([-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766]), xy2d: FieldElement([18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458]), y_minus_x: FieldElement([-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628]), xy2d: FieldElement([-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062]), y_minus_x: FieldElement([25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616]), xy2d: FieldElement([31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383]), y_minus_x: FieldElement([-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814]), xy2d: FieldElement([-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417]), y_minus_x: FieldElement([2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222]), xy2d: FieldElement([33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597]), y_minus_x: FieldElement([23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970]), xy2d: FieldElement([1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647]), y_minus_x: FieldElement([13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511]), xy2d: FieldElement([-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032]), }, ], [ - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834]), y_minus_x: FieldElement([-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461]), xy2d: FieldElement([29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516]), y_minus_x: FieldElement([-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547]), xy2d: FieldElement([-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038]), y_minus_x: FieldElement([-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741]), xy2d: FieldElement([16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747]), y_minus_x: FieldElement([-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323]), xy2d: FieldElement([31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373]), y_minus_x: FieldElement([15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228]), xy2d: FieldElement([-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399]), y_minus_x: FieldElement([11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831]), xy2d: FieldElement([-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313]), y_minus_x: FieldElement([-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958]), xy2d: FieldElement([-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577]), }, - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: FieldElement([-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743]), y_minus_x: FieldElement([29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684]), xy2d: FieldElement([-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476]), @@ -1569,7 +1569,7 @@ pub const base: [[PreComputedPoint; 8]; 32] = [ #[cfg(test)] mod test { use field::FieldElement; - use curve::PreComputedPoint; + use curve::AffineNielsPoint; use curve::CompressedEdwardsY; use curve::ExtendedPoint; use curve::Identity; diff --git a/src/curve.rs b/src/curve.rs index 5d770d1..00c4049 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -56,8 +56,8 @@ //! in ["Twisted Edwards Curves"](https://eprint.iacr.org/2008/013). //! //! Following the implementation strategy in the ref10 reference -//! implementation for Ed25519, we use several different models for -//! curve points: +//! implementation for [Ed25519](https://ed25519.cr.yp.to/ed25519-20110926.pdf), +//! we use several different models for curve points: //! //! * CompletedPoint: points in 𝗣^1 x 𝗣^1; //! * ExtendedPoint: points in 𝗣^3; @@ -66,8 +66,8 @@ //! Finally, to accelerate additions, we use two cached point formats, //! one for the affine model and one for the 𝗣^3 model: //! -//! * PreComputedPoint: `(y+x, y-x, 2dxy)` -//! * CachedPoint: `(Y+X, Y-X, Z, 2dXY)` +//! * AffineNielsPoint: `(y+x, y-x, 2dxy)` +//! * ProjectiveNielsPoint: `(Y+X, Y-X, Z, 2dXY)` //! //! [1]: https://moderncrypto.org/mail-archive/curves/2016/000807.html @@ -206,23 +206,25 @@ pub struct CompletedPoint { T: FieldElement, } -/// A pre-computed point in the affine model for the curve, -/// represented as (y+x, y-x, 2dxy). These precomputations -/// accelerate addition and subtraction. +/// A pre-computed point in the affine model for the curve, represented as +/// (y+x, y-x, 2dxy). These precomputations accelerate addition and +/// subtraction, and were introduced by Niels Duif in the ed25519 paper +/// ["High-Speed High-Security Signatures"](https://ed25519.cr.yp.to/ed25519-20110926.pdf). // Safe to derive Eq because affine coordinates. #[derive(Copy, Clone, Eq, PartialEq)] #[allow(missing_docs)] -pub struct PreComputedPoint { +pub struct AffineNielsPoint { pub y_plus_x: FieldElement, pub y_minus_x: FieldElement, pub xy2d: FieldElement, } -/// A pre-computed point in the P³(𝔽ₚ) model for the curve, -/// represented as (Y+X, Y-X, Z, 2dXY). These precomputations -/// accelerate addition and subtraction. +/// A pre-computed point in the P³(𝔽ₚ) model for the curve, represented as +/// (Y+X, Y-X, Z, 2dXY). These precomputations accelerate addition and +/// subtraction, and were introduced by Niels Duif in the ed25519 paper +/// ["High-Speed High-Security Signatures"](https://ed25519.cr.yp.to/ed25519-20110926.pdf). #[derive(Copy, Clone)] -pub struct CachedPoint { +pub struct ProjectiveNielsPoint { Y_plus_X: FieldElement, Y_minus_X: FieldElement, Z: FieldElement, @@ -257,18 +259,18 @@ impl Identity for ProjectivePoint { } } -impl Identity for CachedPoint { - fn identity() -> CachedPoint { - CachedPoint{ Y_plus_X: FieldElement::one(), +impl Identity for ProjectiveNielsPoint { + fn identity() -> ProjectiveNielsPoint { + ProjectiveNielsPoint{ Y_plus_X: FieldElement::one(), Y_minus_X: FieldElement::one(), Z: FieldElement::one(), T2d: FieldElement::zero() } } } -impl Identity for PreComputedPoint { - fn identity() -> PreComputedPoint { - PreComputedPoint{ +impl Identity for AffineNielsPoint { + fn identity() -> AffineNielsPoint { + AffineNielsPoint{ y_plus_x: FieldElement::one(), y_minus_x: FieldElement::one(), xy2d: FieldElement::zero(), @@ -312,8 +314,8 @@ impl ValidityCheck for ExtendedPoint { // Constant-time assignment // ------------------------------------------------------------------------ -impl CTAssignable for CachedPoint { - fn conditional_assign(&mut self, other: &CachedPoint, choice: u8) { +impl CTAssignable for ProjectiveNielsPoint { + fn conditional_assign(&mut self, other: &ProjectiveNielsPoint, choice: u8) { self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice); self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice); self.Z.conditional_assign(&other.Z, choice); @@ -321,8 +323,8 @@ impl CTAssignable for CachedPoint { } } -impl CTAssignable for PreComputedPoint { - fn conditional_assign(&mut self, other: &PreComputedPoint, choice: u8) { +impl CTAssignable for AffineNielsPoint { + fn conditional_assign(&mut self, other: &AffineNielsPoint, choice: u8) { // PreComputedGroupElementCMove() self.y_plus_x.conditional_assign(&other.y_plus_x, choice); self.y_minus_x.conditional_assign(&other.y_minus_x, choice); @@ -398,9 +400,9 @@ impl ProjectivePoint { } impl ExtendedPoint { - /// Convert to a CachedPoint - pub fn to_cached(&self) -> CachedPoint { - CachedPoint{ + /// Convert to a ProjectiveNielsPoint + pub fn to_cached(&self) -> ProjectiveNielsPoint { + ProjectiveNielsPoint{ Y_plus_X: &self.Y + &self.X, Y_minus_X: &self.Y - &self.X, Z: self.Z, @@ -426,14 +428,14 @@ impl ExtendedPoint { self.to_projective().compress() } - /// Dehomogenize to a PreComputedPoint. + /// Dehomogenize to a AffineNielsPoint. /// Mainly for testing. - pub fn to_precomputed(&self) -> PreComputedPoint { + pub fn to_precomputed(&self) -> AffineNielsPoint { let recip = self.Z.invert(); let x = &self.X * &recip; let y = &self.Y * &recip; let xy2d = &(&x * &y) * &constants::d2; - PreComputedPoint{ + AffineNielsPoint{ y_plus_x: &y + &x, y_minus_x: &y - &x, xy2d: xy2d @@ -497,10 +499,10 @@ impl ExtendedPoint { // Addition and Subtraction // ------------------------------------------------------------------------ -impl<'a,'b> Add<&'b CachedPoint> for &'a ExtendedPoint { +impl<'a,'b> Add<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; - fn add(self, other: &'b CachedPoint) -> CompletedPoint { + fn add(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { let Y_plus_X = &self.Y + &self.X; let Y_minus_X = &self.Y - &self.X; let PP = &Y_plus_X * &other.Y_plus_X; @@ -518,10 +520,10 @@ impl<'a,'b> Add<&'b CachedPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { +impl<'a,'b> Sub<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; - fn sub(self, other: &'b CachedPoint) -> CompletedPoint { + fn sub(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { let Y_plus_X = &self.Y + &self.X; let Y_minus_X = &self.Y - &self.X; let PM = &Y_plus_X * &other.Y_minus_X; @@ -539,10 +541,10 @@ impl<'a,'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Add<&'b PreComputedPoint> for &'a ExtendedPoint { +impl<'a,'b> Add<&'b AffineNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; - fn add(self, other: &'b PreComputedPoint) -> CompletedPoint { + fn add(self, other: &'b AffineNielsPoint) -> CompletedPoint { let Y_plus_X = &self.Y + &self.X; let Y_minus_X = &self.Y - &self.X; let PP = &Y_plus_X * &other.y_plus_x; @@ -559,10 +561,10 @@ impl<'a,'b> Add<&'b PreComputedPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Sub<&'b PreComputedPoint> for &'a ExtendedPoint { +impl<'a,'b> Sub<&'b AffineNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; - fn sub(self, other: &'b PreComputedPoint) -> CompletedPoint { + fn sub(self, other: &'b AffineNielsPoint) -> CompletedPoint { let Y_plus_X = &self.Y + &self.X; let Y_minus_X = &self.Y - &self.X; let PM = &Y_plus_X * &other.y_minus_x; @@ -606,11 +608,11 @@ impl<'a> Neg for &'a ExtendedPoint { } } -impl<'a> Neg for &'a CachedPoint { - type Output = CachedPoint; +impl<'a> Neg for &'a ProjectiveNielsPoint { + type Output = ProjectiveNielsPoint; - fn neg(self) -> CachedPoint { - CachedPoint{ + fn neg(self) -> ProjectiveNielsPoint { + ProjectiveNielsPoint{ Y_plus_X: self.Y_minus_X, Y_minus_X: self.Y_plus_X, Z: self.Z, @@ -620,11 +622,11 @@ impl<'a> Neg for &'a CachedPoint { } -impl<'a> Neg for &'a PreComputedPoint { - type Output = PreComputedPoint; +impl<'a> Neg for &'a AffineNielsPoint { + type Output = AffineNielsPoint; - fn neg(self) -> PreComputedPoint { - PreComputedPoint{ + fn neg(self) -> AffineNielsPoint { + AffineNielsPoint{ y_plus_x: self.y_minus_x, y_minus_x: self.y_plus_x, xy2d: -(&self.xy2d) @@ -649,7 +651,7 @@ impl ScalarMult for ExtendedPoint { /// the basepoint, `basepoint_mult` is approximately 4x faster. fn scalar_mult(&self, scalar: &Scalar) -> ExtendedPoint { let A = self.to_cached(); - let mut As: [CachedPoint; 8] = [A; 8]; + let mut As: [ProjectiveNielsPoint; 8] = [A; 8]; for i in 0..7 { As[i+1] = (self + &As[i]).to_extended().to_cached(); } @@ -780,7 +782,7 @@ pub fn double_scalar_mult_vartime(a: &Scalar, A: &ExtendedPoint, b: &Scalar) -> let b_naf = b.non_adjacent_form(); // Build a lookup table of odd multiples of A - let mut Ai = [CachedPoint::identity(); 8]; + let mut Ai = [ProjectiveNielsPoint::identity(); 8]; let A2 = A.double(); Ai[0] = A.to_cached(); for i in 0..7 { @@ -900,16 +902,16 @@ impl Debug for CompletedPoint { } } -impl Debug for PreComputedPoint { +impl Debug for AffineNielsPoint { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "PreComputedPoint(\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n)", + write!(f, "AffineNielsPoint(\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n)", &self.y_plus_x, &self.y_minus_x, &self.xy2d) } } -impl Debug for CachedPoint { +impl Debug for ProjectiveNielsPoint { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CachedPoint(\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n)", + write!(f, "ProjectiveNielsPoint(\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n)", &self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d) } } @@ -1024,7 +1026,7 @@ mod test { assert_eq!( bp_added.compress(), BASE2_CMPRSSD); } - /// Test `impl Add for ExtendedPoint` + /// Test `impl Add for ExtendedPoint` /// using the basepoint, basepoint2 constants #[test] fn test_basepoint_plus_basepoint_cached() { @@ -1033,13 +1035,13 @@ mod test { assert_eq!( bp_added.compress(), BASE2_CMPRSSD); } - /// Test `impl Add for ExtendedPoint` + /// Test `impl Add for ExtendedPoint` /// using the basepoint, basepoint2 constants #[test] fn test_basepoint_plus_basepoint_precomputed() { let bp = BASE_CMPRSSD.decompress().unwrap(); // on decode, Z =1, so x = X/Z = X, y = Y/Z = Y, xy = T - let bp_precomputed = PreComputedPoint{ + let bp_precomputed = AffineNielsPoint{ y_plus_x: &bp.Y + &bp.X, y_minus_x: &bp.Y - &bp.X, xy2d: &bp.T * &constants::d2, @@ -1154,10 +1156,10 @@ mod test { } #[test] - fn test_PreComputedPoint_conditional_assign() { - let id = PreComputedPoint::identity(); - let mut p1 = PreComputedPoint::identity(); - let p2: PreComputedPoint = PreComputedPoint{ + fn test_AffineNielsPoint_conditional_assign() { + let id = AffineNielsPoint::identity(); + let mut p1 = AffineNielsPoint::identity(); + let p2: AffineNielsPoint = AffineNielsPoint{ y_plus_x: FieldElement([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), y_minus_x: FieldElement([11, 22, 33, 44, 55, 66, 77, 88, 99, 100]), xy2d: FieldElement([10, 20, 30, 40, 50, 60, 70, 80, 90, 101]), From 2cef5fcecdefed6a78c41d2ecfa032e5cb815c3a Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 22 Feb 2017 22:08:18 -0800 Subject: [PATCH 006/101] Add CompressedEdwardsY::as_bytes --- src/curve.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 34085d4..ec9c093 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -79,7 +79,7 @@ use core::fmt::Debug; use core::iter::Iterator; -use core::ops::{Add, Sub, Neg, Index}; +use core::ops::{Add, Sub, Neg}; use core::cmp::{PartialEq, Eq}; use constants; @@ -106,21 +106,18 @@ pub struct CompressedEdwardsY(pub [u8; 32]); impl Debug for CompressedEdwardsY { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedPoint: {:?}", &self.0[..]) - } -} - -impl Index for CompressedEdwardsY { - type Output = u8; - - fn index<'a>(&'a self, _index: usize) -> &'a u8 { - let ret: &'a u8 = &(self.0[_index]); - ret + write!(f, "CompressedPoint: {:?}", self.as_bytes()) } } impl CompressedEdwardsY { /// View this `CompressedEdwardsY` as an array of bytes. + pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + &self.0 + } + + /// Copy this `CompressedEdwardsY` to an array of bytes. + /// XXX is this useful? pub fn to_bytes(&self) -> [u8;32] { self.0 } @@ -130,7 +127,7 @@ impl CompressedEdwardsY { /// Returns `None` if the input is not the `y`-coordinate of a /// curve point. pub fn decompress(&self) -> Option { // FromBytes() - let Y = FieldElement::from_bytes(&self.0); + let Y = FieldElement::from_bytes(self.as_bytes()); let Z = FieldElement::one(); let YY = Y.square(); let u = &YY - &Z; // u = y²-1 @@ -140,7 +137,7 @@ impl CompressedEdwardsY { if is_nonzero_square != 1u8 { return None; } // Flip the sign of X if it's not correct - let compressed_sign_bit = self[31] >> 7; + let compressed_sign_bit = self.as_bytes()[31] >> 7; let current_sign_bit = X.is_negative_ed25519(); X.conditional_negate(current_sign_bit ^ compressed_sign_bit); @@ -317,7 +314,8 @@ impl CTAssignable for AffineNielsPoint { impl CTEq for ExtendedPoint { fn ct_eq(&self, other: &ExtendedPoint) -> u8 { - arrays_equal_ct(&self.compress().0, &other.compress().0) + arrays_equal_ct( self.compress().as_bytes(), + other.compress().as_bytes()) } } @@ -977,7 +975,7 @@ mod test { /// Test sign handling in decompression #[test] fn test_decompression_sign_handling() { - let mut m_bp_bytes: [u8;32] = BASE_CMPRSSD.to_bytes().clone(); + let mut m_bp_bytes: [u8;32] = BASE_CMPRSSD.as_bytes().clone(); // Set the high bit of the last byte to flip the sign m_bp_bytes[31] |= 1 << 7; let m_bp = CompressedEdwardsY(m_bp_bytes).decompress().unwrap(); From f39566cf16d48b90a6c0793631ebc49a5956a5a2 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 22 Feb 2017 22:12:57 -0800 Subject: [PATCH 007/101] Change CompressedDecaf::to_bytes to ::as_bytes --- src/decaf.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/decaf.rs b/src/decaf.rs index 1b777c9..2537fbb 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -50,15 +50,15 @@ pub struct CompressedDecaf(pub [u8; 32]); /// The result of compressing a `DecafPoint`. impl CompressedDecaf { /// View this `CompressedDecaf` as an array of bytes. - pub fn to_bytes(&self) -> [u8;32] { - self.0 + pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + &self.0 } /// Attempt to decompress to an `DecafPoint`. pub fn decompress(&self) -> Option { // XXX should decoding be CT ? // XXX need to check that xy is nonnegative and reject otherwise - let s = FieldElement::from_bytes(&self.0); + let s = FieldElement::from_bytes(self.as_bytes()); // Check that s = |s| and reject otherwise. let mut abs_s = s; @@ -267,7 +267,7 @@ impl BasepointMult for DecafPoint { impl Debug for CompressedDecaf { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedDecaf: {:?}", &self.0[..]) + write!(f, "CompressedDecaf: {:?}", self.as_bytes()) } } From 1dac2f53bb8f6edf233a064f17ade13923268c26 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 22 Feb 2017 23:06:59 -0800 Subject: [PATCH 008/101] Implement Identity for CompressedEdwardsY --- src/curve.rs | 15 +++++++++++++++ src/decaf.rs | 4 +--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index ec9c093..8130d24 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -218,6 +218,15 @@ pub trait Identity { fn identity() -> Self; } +impl Identity for CompressedEdwardsY { + fn identity() -> CompressedEdwardsY { + CompressedEdwardsY([1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0]) + } +} + impl Identity for ExtendedPoint { fn identity() -> ExtendedPoint { ExtendedPoint{ X: FieldElement::zero(), @@ -1161,6 +1170,12 @@ mod test { assert!(p2.is_small_order() == false); } + #[test] + fn test_compressed_identity() { + assert_eq!(ExtendedPoint::identity().compress(), + CompressedEdwardsY::identity()); + } + #[test] fn test_is_identity() { assert!(ExtendedPoint::identity().is_identity()); diff --git a/src/decaf.rs b/src/decaf.rs index 2537fbb..93f22e2 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -308,9 +308,7 @@ mod test { fn test_decaf_decompress_id() { let compressed_id = CompressedDecaf::identity(); let id = compressed_id.decompress().unwrap(); - // This should compress (as ed25519) to the following: - let mut bytes = [0u8; 32]; bytes[0] = 1; - assert_eq!(id.0.compress(), CompressedEdwardsY(bytes)); + assert_eq!(id.0.compress(), CompressedEdwardsY::identity()); } #[test] From 950519b97b4c631525245d7d5bdd37c606fc7bcd Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 23 Feb 2017 03:15:55 -0800 Subject: [PATCH 009/101] Implement Debug for Scalar --- src/scalar.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/scalar.rs b/src/scalar.rs index 85c77be..228294c 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -30,8 +30,8 @@ //! limbs. use core::cmp::{Eq, PartialEq}; -use core::ops::{Index, IndexMut}; -use core::ops::{Neg}; +use core::ops::{Neg, Index, IndexMut}; +use core::fmt::Debug; #[cfg(feature = "std")] use rand::Rng; @@ -50,6 +50,12 @@ use subtle::arrays_equal_ct; #[derive(Copy, Clone)] pub struct Scalar(pub [u8; 32]); +impl Debug for Scalar { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "Scalar: {:?}", &self.0[..]) + } +} + impl Eq for Scalar{} impl PartialEq for Scalar { /// Test equality between two `Scalar`s. From e5c0d789fde40ad5046e49310fc178dba766e9f3 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 23 Feb 2017 03:26:57 -0800 Subject: [PATCH 010/101] Add a Scalar::as_bytes() method. --- src/scalar.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/scalar.rs b/src/scalar.rs index 228294c..ed10297 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -165,6 +165,11 @@ impl Scalar { Scalar::reduce(&scalar_bytes) } + /// View this `Scalar` as a sequence of bytes. + pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + &self.0 + } + /// Construct the additive identity pub fn zero() -> Self { Scalar([0u8; 32]) From a93798d209294e3ea018a8960518523e7eb0e4b6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 27 Feb 2017 11:19:06 -0800 Subject: [PATCH 011/101] Add a function to hash a byte slice to a scalar. --- Cargo.toml | 10 ++++++++++ src/lib.rs | 5 +++++ src/scalar.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index da90912..691f464 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,16 @@ version = "0.3.3" optional = true version = "0.3" +[dependencies.digest] +version = "0.4" + +[dependencies.generic-array] +# same version that digest depends on +version = "^0.6" + +[dev-dependencies.sha2] +version = "0.4" + [features] default = ["std"] std = ["rand"] diff --git a/src/lib.rs b/src/lib.rs index fe26b70..13fec92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,10 +38,15 @@ extern crate std; #[cfg(test)] extern crate test; +#[cfg(test)] +extern crate sha2; #[macro_use] extern crate arrayref; +extern crate generic_array; +extern crate digest; + #[cfg(feature = "std")] extern crate rand; diff --git a/src/scalar.rs b/src/scalar.rs index 85c77be..db19a9e 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -36,6 +36,10 @@ use core::ops::{Neg}; #[cfg(feature = "std")] use rand::Rng; +use digest::Digest; +use generic_array::GenericArray; +use generic_array::typenum::U64; + use constants; use utils::{load3, load4}; use subtle::CTAssignable; @@ -159,6 +163,35 @@ impl Scalar { Scalar::reduce(&scalar_bytes) } + /// Hash a slice of bytes into a scalar. + /// + /// Takes a type parameter `D`, which is any `Digest` producing 64 + /// bytes (512 bits) of output. + /// + /// # Example + /// + /// ``` + /// # extern crate curve25519_dalek; + /// # use curve25519_dalek::scalar::Scalar; + /// extern crate sha2; + /// use sha2::Sha512; + /// + /// # fn main() { + /// let msg = "To really appreciate architecture, you may even need to commit a murder"; + /// let s = Scalar::hash_from_bytes::(msg.as_bytes()); + /// # } + /// ``` + /// + pub fn hash_from_bytes(input: &[u8]) -> Scalar + where D: Digest + Default { + let mut hash = D::default(); + hash.input(input); + // XXX this seems clumsy + let mut output = [0u8;64]; + output.copy_from_slice(hash.result().as_slice()); + Scalar::reduce(&output) + } + /// Construct the additive identity pub fn zero() -> Self { Scalar([0u8; 32]) From fe15bc1d0b676f3b3d3ae21d2a41edcf1fc6276d Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 27 Feb 2017 11:22:07 -0800 Subject: [PATCH 012/101] Add note on fn main() in doctest --- src/scalar.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scalar.rs b/src/scalar.rs index db19a9e..60d92ba 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -176,6 +176,8 @@ impl Scalar { /// extern crate sha2; /// use sha2::Sha512; /// + /// # // Need fn main() here in comment so the doctest compiles + /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests /// # fn main() { /// let msg = "To really appreciate architecture, you may even need to commit a murder"; /// let s = Scalar::hash_from_bytes::(msg.as_bytes()); From 45fbcb45f63a558f12501153da05e44b8d98a80e Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 27 Dec 2016 12:42:49 -0500 Subject: [PATCH 013/101] First notes and code on Montgomery conversion --- src/constants.rs | 5 +++ src/curve.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++ src/field.rs | 2 + 3 files changed, 116 insertions(+) diff --git a/src/constants.rs b/src/constants.rs index 0535515..43194a3 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -72,6 +72,11 @@ pub const SQRT_MINUS_A: FieldElement = FieldElement([ // sqrtMinusA 12222970, 8312128, 11511410, -9067497, 15300785, 241793, -25456130, -14121551, 12187136, -3972024, ]); +/// SQRT_MINUS_APLUS2 is sqrt(-486664) +pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ + -12222970, -8312128, -11511410, 9067497, -15300785, + -241793, 25456130, 14121551, -12187136, 3972024]); + /// SQRT_MINUS_HALF is sqrt(-1/2) pub const SQRT_MINUS_HALF: FieldElement = FieldElement([ // sqrtMinusHalf -17256545, 3971863, 28865457, -1750208, 27359696, diff --git a/src/curve.rs b/src/curve.rs index 34085d4..d48fba1 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -148,6 +148,56 @@ impl CompressedEdwardsY { } } +/// In "Montgomery u" format, as used in X25519, a point `(u,v)` on +/// the Montgomery curve +/// +/// v^2 = u * (u^2 + 486662*u + 1) +/// +/// is represented just by `u`. Note that we use `(u,v)` instead of +/// `(x,y)` for Montgomery coordinates to avoid confusion with Edwards +/// coordinates. For Montgomery curves, it is possible to compute the +/// `u`-coordinate of `n(u,v)` just from `n` and `u`, so it is not +/// necessary to use `v` for a Diffie-Hellman key exchange. +/// +/// XXX add note on monty, twist security, edwards impl of x25519, rfc7748 +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct CompressedMontgomeryU(pub [u8; 32]); + +impl CompressedMontgomeryU { + /// View this `CompressedMontgomeryU` as an array of bytes. + pub fn to_bytes(&self) -> [u8;32] { + self.0 + } + + /// Attempt to decompress to an `ExtendedPoint`. + /// + /// Note that since there are two curve points with the same + /// `u`-coordinate, the `u`-coordinate does not fully specify a + /// point. + /// + /// XXX match behaviour in Signal specification re: sign choice + /// and rewrite this note + /// + /// XXX check for div by zero: when is u = -1 ? + /// XXX exceptional points for the birational map + pub fn decompress(&self) -> Option { + // u = (1 + y) / (1 - y) + // v = sqrt(-486664) * u / x + // + // so + // + // y = (u - 1) / (u + 1) + + let u = FieldElement::from_bytes(&self.0); + let u_plus_1_inv = (&u + &FieldElement::one()).invert(); + let y = &(&u - &FieldElement::one()) * &u_plus_1_inv; + + // XXX this does two inversions: the above + one in .decompress() + // is it possible to do one? + CompressedEdwardsY(y.to_bytes()).decompress() + } +} + // ------------------------------------------------------------------------ // Internal point representations // ------------------------------------------------------------------------ @@ -376,6 +426,26 @@ impl ProjectivePoint { s[31] ^= (x.is_negative_ed25519() << 7) as u8; CompressedEdwardsY(s) } + + /// Convert this point to a `CompressedMontgomeryU`. + /// Note that this discards the sign. + /// + /// XXX check for div by zero: when is Z = Y ? + /// XXX exceptional points for the birational map + pub fn compress_montgomery(&self) -> CompressedMontgomeryU { + // u = (1 + y) / (1 - y) + // v = sqrt(-486664) * u / x + // + // since y = Y/Z, x = X/Z, + // + // u = (1 + Y/Z) / (1 - Y/Z); + // = (Z + Y) / (Z - Y); + let Z_plus_Y = &self.Z + &self.Y; + let Z_minus_Y = &self.Z - &self.Y; + let u = &Z_plus_Y * &Z_minus_Y.invert(); + + CompressedMontgomeryU(u.to_bytes()) + } } impl ExtendedPoint { @@ -420,6 +490,11 @@ impl ExtendedPoint { xy2d: xy2d } } + + /// Compress this point to `CompressedMontgomeryU` format + pub fn compress_montgomery(&self) -> CompressedMontgomeryU { + self.to_projective().compress_montgomery() + } } impl CompletedPoint { @@ -912,6 +987,13 @@ mod test { use super::*; use super::select_precomputed_point; + /// The X25519 basepoint, in compressed Montgomery form. + static BASE_CMPRSSD_MONTY: CompressedMontgomeryU = + CompressedMontgomeryU([0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + /// X coordinate of the basepoint. /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202 static BASE_X_COORD_BYTES: [u8; 32] = @@ -958,6 +1040,33 @@ mod test { 0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85, 0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13, 0x2b, 0x42]); + #[test] + /// Test that the constant for sqrt(-486664) really is a square + /// root of -486664. + /// XXX this should be a test in constants.rs ?? + fn test_sqrt_minus_aplus2() { + let minus_aplus2 = FieldElement([-486664,0,0,0,0,0,0,0,0,0]); + let sqrt = constants::SQRT_MINUS_APLUS2; + let sq = &sqrt * &sqrt; + assert_eq!(sq, minus_aplus2); + } + + /// Test Montgomery conversion against the X25519 basepoint. + #[test] + fn test_basepoint_to_montgomery() { + let bp = BASE_CMPRSSD.decompress().unwrap(); + let bp_monty = bp.compress_montgomery(); + assert_eq!(bp_monty, BASE_CMPRSSD_MONTY); + } + + /// Test Montgomery conversion against the X25519 basepoint. + #[test] + fn test_basepoint_from_montgomery() { + let bp = BASE_CMPRSSD_MONTY.decompress().unwrap(); + let bp_compressed_edwards = bp.compress(); + assert_eq!(bp_compressed_edwards, BASE_CMPRSSD); + } + /// Test round-trip decompression for the basepoint. #[test] fn test_basepoint_decompression_compression() { diff --git a/src/field.rs b/src/field.rs index 926804e..cb29d70 100644 --- a/src/field.rs +++ b/src/field.rs @@ -798,6 +798,8 @@ impl FieldElement { /// Given a nonzero field element, compute its inverse. /// The inverse is computed as self^(p-2), since /// x^(p-2)x = x^(p-1) = 1 (mod p). + /// + /// XXX should we add a debug_assert that self is nonzero? pub fn invert(&self) -> FieldElement { // The bits of p-2 = 2^255 -19 -2 are 11010111111...11. // From 19d452c2dc23a17165c571147dff570eb52501cc Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 2 Jan 2017 09:24:58 -0500 Subject: [PATCH 014/101] Test decompressing an invalid montgomery point --- src/curve.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index d48fba1..99c08e9 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1067,6 +1067,21 @@ mod test { assert_eq!(bp_compressed_edwards, BASE_CMPRSSD); } + /// If u = -1, then v^2 = u*(u^2+486662*u+1) = 486660. + /// But 486660 is nonsquare mod p, so this should fail. + /// + /// XXX what does Signal do here? + #[test] + #[should_panic] + fn test_u_minus_one_monty() { + let mut m1 = FieldElement::zero(); + m1[0] = -1; + let m1_bytes = m1.to_bytes(); + let div_by_zero_u = CompressedMontgomeryU(m1_bytes); + let p = div_by_zero_u.decompress().unwrap(); + println!("{:?}", p); + } + /// Test round-trip decompression for the basepoint. #[test] fn test_basepoint_decompression_compression() { From db53b58e89f43663ad5941e52063f95801cf2ea3 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 27 Feb 2017 21:13:24 -0800 Subject: [PATCH 015/101] Properly handle exceptional points. --- src/curve.rs | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 99c08e9..30b7d5e 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -189,6 +189,18 @@ impl CompressedMontgomeryU { // y = (u - 1) / (u + 1) let u = FieldElement::from_bytes(&self.0); + + // If u = -1, then v^2 = u*(u^2+486662*u+1) = 486660. + // But 486660 is nonsquare mod p, so this is not a curve point. + // + // XXX what does Signal do here? + // + // Note: currently, without this check, u = -1 will accidentally + // decode to a valid (but incorrect) point, since 0.invert() = 0. + if u == FieldElement::minus_one() { + return None; + } + let u_plus_1_inv = (&u + &FieldElement::one()).invert(); let y = &(&u - &FieldElement::one()) * &u_plus_1_inv; @@ -430,9 +442,11 @@ impl ProjectivePoint { /// Convert this point to a `CompressedMontgomeryU`. /// Note that this discards the sign. /// - /// XXX check for div by zero: when is Z = Y ? - /// XXX exceptional points for the birational map - pub fn compress_montgomery(&self) -> CompressedMontgomeryU { + /// # Return + /// - `None` if `self` is the identity point; + /// - `Some(CompressedMontgomeryU)` otherwise. + /// + pub fn compress_montgomery(&self) -> Option { // u = (1 + y) / (1 - y) // v = sqrt(-486664) * u / x // @@ -440,11 +454,18 @@ impl ProjectivePoint { // // u = (1 + Y/Z) / (1 - Y/Z); // = (Z + Y) / (Z - Y); + // + // exceptional points: + // y = 1 <=> Y/Z = 1 <=> Z - Y = 0 let Z_plus_Y = &self.Z + &self.Y; let Z_minus_Y = &self.Z - &self.Y; let u = &Z_plus_Y * &Z_minus_Y.invert(); - CompressedMontgomeryU(u.to_bytes()) + if Z_minus_Y.is_zero() == 0u8 { + CompressedMontgomeryU(u.to_bytes()) + } else { + None + } } } @@ -1072,14 +1093,20 @@ mod test { /// /// XXX what does Signal do here? #[test] - #[should_panic] fn test_u_minus_one_monty() { let mut m1 = FieldElement::zero(); m1[0] = -1; let m1_bytes = m1.to_bytes(); let div_by_zero_u = CompressedMontgomeryU(m1_bytes); - let p = div_by_zero_u.decompress().unwrap(); - println!("{:?}", p); + assert!(div_by_zero_u.decompress().is_none()); + } + + /// Montgomery compression of the identity point should + /// fail (it's sent to infinity). + #[test] + fn test_identity_to_monty() { + let id = ExtendedPoint::identity(); + assert!(id.compressed_montgomery().is_none()); } /// Test round-trip decompression for the basepoint. From 5d3d114628075822c36582851f89e12cdca141bf Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 27 Feb 2017 23:15:39 -0800 Subject: [PATCH 016/101] fixup! Properly handle exceptional points. --- src/curve.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 30b7d5e..7a7e01c 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -462,7 +462,7 @@ impl ProjectivePoint { let u = &Z_plus_Y * &Z_minus_Y.invert(); if Z_minus_Y.is_zero() == 0u8 { - CompressedMontgomeryU(u.to_bytes()) + Some(CompressedMontgomeryU(u.to_bytes())) } else { None } @@ -512,8 +512,14 @@ impl ExtendedPoint { } } - /// Compress this point to `CompressedMontgomeryU` format - pub fn compress_montgomery(&self) -> CompressedMontgomeryU { + /// Convert this point to a `CompressedMontgomeryU`. + /// Note that this discards the sign. + /// + /// # Return + /// - `None` if `self` is the identity point; + /// - `Some(CompressedMontgomeryU)` otherwise. + /// + pub fn compress_montgomery(&self) -> Option { self.to_projective().compress_montgomery() } } @@ -1076,7 +1082,7 @@ mod test { #[test] fn test_basepoint_to_montgomery() { let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp_monty = bp.compress_montgomery(); + let bp_monty = bp.compress_montgomery().unwrap(); assert_eq!(bp_monty, BASE_CMPRSSD_MONTY); } @@ -1106,7 +1112,7 @@ mod test { #[test] fn test_identity_to_monty() { let id = ExtendedPoint::identity(); - assert!(id.compressed_montgomery().is_none()); + assert!(id.compress_montgomery().is_none()); } /// Test round-trip decompression for the basepoint. From 1c9637490c1d996df55fc0d16b155d2972d6f172 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 4 Mar 2017 02:00:59 +0000 Subject: [PATCH 017/101] Obsessive whitespace fix. --- src/curve.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 7a7e01c..7d176d7 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -121,7 +121,7 @@ impl Index for CompressedEdwardsY { impl CompressedEdwardsY { /// View this `CompressedEdwardsY` as an array of bytes. - pub fn to_bytes(&self) -> [u8;32] { + pub fn to_bytes(&self) -> [u8; 32] { self.0 } @@ -165,7 +165,7 @@ pub struct CompressedMontgomeryU(pub [u8; 32]); impl CompressedMontgomeryU { /// View this `CompressedMontgomeryU` as an array of bytes. - pub fn to_bytes(&self) -> [u8;32] { + pub fn to_bytes(&self) -> [u8; 32] { self.0 } From 915f41c643920d637e1d24904aeebe83e7b84ebf Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 4 Mar 2017 02:19:48 +0000 Subject: [PATCH 018/101] Fixup CompressedMontgomeryU::decompress() and ensure no divide-by-zeroes. Also, match Signal behaviour, and split off recovery of other coordinates into separate functions. --- src/curve.rs | 84 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 7d176d7..50e669b 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -171,43 +171,78 @@ impl CompressedMontgomeryU { /// Attempt to decompress to an `ExtendedPoint`. /// - /// Note that since there are two curve points with the same + /// # Note + /// + /// Since there are two curve points with the same /// `u`-coordinate, the `u`-coordinate does not fully specify a - /// point. + /// point. That is, roundtripping between an `ExtendedPoint` and + /// a `CompressedMontgomeryU` discards its sign bit. /// - /// XXX match behaviour in Signal specification re: sign choice - /// and rewrite this note + /// # Warning /// - /// XXX check for div by zero: when is u = -1 ? - /// XXX exceptional points for the birational map + /// This function is *not* constant time. + /// + /// # Return + /// + /// An `Option`, which will be `None` if either condition holds: + /// + /// * `u = -1`, or + /// * `v` is not square. + // + // XXX any other exceptional points for the birational map? pub fn decompress(&self) -> Option { - // u = (1 + y) / (1 - y) - // v = sqrt(-486664) * u / x - // - // so - // - // y = (u - 1) / (u + 1) - - let u = FieldElement::from_bytes(&self.0); + let u: FieldElement = FieldElement::from_bytes(&self.0); // If u = -1, then v^2 = u*(u^2+486662*u+1) = 486660. // But 486660 is nonsquare mod p, so this is not a curve point. // - // XXX what does Signal do here? - // // Note: currently, without this check, u = -1 will accidentally // decode to a valid (but incorrect) point, since 0.invert() = 0. if u == FieldElement::minus_one() { return None; } - let u_plus_1_inv = (&u + &FieldElement::one()).invert(); - let y = &(&u - &FieldElement::one()) * &u_plus_1_inv; + let y: FieldElement = CompressedMontgomeryU::to_edwards_y(&u); // y = (u-1)/(u+1) - // XXX this does two inversions: the above + one in .decompress() - // is it possible to do one? CompressedEdwardsY(y.to_bytes()).decompress() } + + /// Given a Montgomery `u` coordinate, compute an Edwards `y` via + /// `y = (u-1)/(u+1)`. + /// + /// # Note + /// + /// Since `u = (1+y)/(1-y)` and `v = √(u(u²+Au+1))`, we can see that + /// `y = (u-1)/(u+1)`. + /// + /// # Return + /// + /// A `FieldElement` corresponding to this coordinate, but in Edwards form. + fn to_edwards_y(u: &FieldElement) -> FieldElement { + &(u - &FieldElement::one()) * &(u + &FieldElement::one()).invert() + } + + /// Given a Montgomery `u` coordinate, compute the corresponding + /// Montgomery `v` coordinate by computing the right-hand side of + /// the Montgomery field equation, `v² = u(u² + Au +1)`. + /// + /// # Return + /// + /// A tuple of (`u8`, `FieldElement`), where the `u8` is `1` if the v² was + /// actually a square and `0` if otherwise, along with a `FieldElement`: the + /// Montgomery `v` corresponding to this `u`. + fn to_montgomery_v(u: &FieldElement) -> (u8, FieldElement) { + let one: FieldElement = FieldElement::one(); + let v_squared: FieldElement = u * &(&(&u.square() + &(&(&constants::A * u) + &one))); + let v_inv: FieldElement; + let v: FieldElement; + let okay: u8; + + let (okay, v_inv) = v_squared.invsqrt(); + let v = &v_inv * &v_squared; + + (okay, v) + } } // ------------------------------------------------------------------------ @@ -1325,6 +1360,15 @@ mod test { assert!(ExtendedPoint::identity().is_identity()); } + #[test] + fn test_montgomery_u_is_neg_one_rejected() { + let fe_u: FieldElement = FieldElement::minus_one(); + let u: CompressedMontgomeryU = CompressedMontgomeryU(fe_u.to_bytes()); + let result: Option = u.decompress(); + + assert!(result.is_none()); + } + #[bench] fn bench_basepoint_mult(b: &mut Bencher) { b.iter(|| ExtendedPoint::basepoint_mult(&A_SCALAR)); From b9de92aeafd38ea5829794ddcc8f2b1c9c51b619 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 4 Mar 2017 02:22:34 +0000 Subject: [PATCH 019/101] Add benchmarks for Edwards-Y and Mongomery-U decompression. --- src/curve.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index 50e669b..e87ae3c 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1443,4 +1443,20 @@ mod test { b.iter(| | p1.mult_by_pow_2(4) ); } + + #[bench] + fn bench_compress_edwards(b: &mut Bencher) { + let mut rng: OsRng = OsRng::new().unwrap(); + let p1: ExtendedPoint = ExtendedPoint::basepoint_mult(&Scalar::random(&mut rng)); + + b.iter(| | p1.compress() ); + } + + #[bench] + fn bench_compress_montgomery(b: &mut Bencher) { + let mut rng: OsRng = OsRng::new().unwrap(); + let p1: ExtendedPoint = ExtendedPoint::basepoint_mult(&Scalar::random(&mut rng)); + + b.iter(| | p1.compress_montgomery() ); + } } From cfd0e8ad6ea66c7f0813bf121de94a5d12a82391 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 4 Mar 2017 02:23:07 +0000 Subject: [PATCH 020/101] Add method for recovery of Edwards x-coordinate given Montgomery (u, v). This function is necessary for matching Signal's hash_to_point() behaviour. --- src/curve.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index e87ae3c..92457c5 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -243,6 +243,41 @@ impl CompressedMontgomeryU { (okay, v) } + + /// Given Montgomery coordinates `(u, v)`, recover the Edwards `x` coordinate. + /// + /// # Inputs + /// + /// * `u` and `v` are both `&FieldElement`s, corresponding the the `(u, v)` + /// coordinates of this `CompressedMontgomeryU`. + /// * `sign` is an &u8. + /// + /// ## Explanation of choice of `sign` + /// + /// ### Original Signal behaviour: + /// + /// - `1u8` will leave `x` negative if it is negative, and will negate + /// `x` if it is positive, and + /// - `0u8` will leave `x` positive if it is positive, and will negate + /// `x` if it is negative. + /// + /// Hence, if `sign` is `1u8`, the returned `x` will be negative. + /// Otherwise, if `sign` is `0u8`, the returned `x` will be positive. + /// + /// # Return + /// + /// A `FieldElement`, the Edwards `x` coordinate, by using `(u, v)` to + /// convert from Montgomery to Edwards form via the right-hand side of the + /// equation: `x=(u/v)*sqrt(-A-2)`. + fn to_edwards_x(u: &FieldElement, v: &FieldElement, sign: &u8) -> FieldElement { + let mut x: FieldElement = &(u * &v.invert()) * &constants::SQRT_MINUS_APLUS2; + let neg_x: FieldElement = -(&x); + let current_sign: u8 = x.is_negative_ed25519(); + + // Negate x to match the sign: + x.conditional_assign(&neg_x, current_sign ^ sign); + x + } } // ------------------------------------------------------------------------ From 20ace8da48da63fd2730f192f705f013778e2fb5 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 4 Mar 2017 02:26:36 +0000 Subject: [PATCH 021/101] Rename compress() to compress_edwards(). --- src/curve.rs | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 92457c5..a05f90b 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -449,7 +449,7 @@ impl CTAssignable for AffineNielsPoint { impl CTEq for ExtendedPoint { fn ct_eq(&self, other: &ExtendedPoint) -> u8 { - arrays_equal_ct(&self.compress().0, &other.compress().0) + arrays_equal_ct(&self.compress_edwards().0, &other.compress_edwards().0) } } @@ -498,7 +498,7 @@ impl ProjectivePoint { } /// Convert this point to a `CompressedEdwardsY` - pub fn compress(&self) -> CompressedEdwardsY { + pub fn compress_edwards(&self) -> CompressedEdwardsY { let recip = self.Z.invert(); let x = &self.X * &recip; let y = &self.Y * &recip; @@ -563,11 +563,6 @@ impl ExtendedPoint { } } - /// Compress this point to `CompressedEdwardsY` format - pub fn compress(&self) -> CompressedEdwardsY { - self.to_projective().compress() - } - /// Dehomogenize to a AffineNielsPoint. /// Mainly for testing. pub fn to_precomputed(&self) -> AffineNielsPoint { @@ -582,6 +577,11 @@ impl ExtendedPoint { } } + /// Compress this point to `CompressedEdwardsY` format. + pub fn compress_edwards(&self) -> CompressedEdwardsY { + self.to_projective().compress_edwards() + } + /// Convert this point to a `CompressedMontgomeryU`. /// Note that this discards the sign. /// @@ -1160,7 +1160,7 @@ mod test { #[test] fn test_basepoint_from_montgomery() { let bp = BASE_CMPRSSD_MONTY.decompress().unwrap(); - let bp_compressed_edwards = bp.compress(); + let bp_compressed_edwards = bp.compress_edwards(); assert_eq!(bp_compressed_edwards, BASE_CMPRSSD); } @@ -1193,8 +1193,8 @@ mod test { let bp2 = BASE2_CMPRSSD.decompress().unwrap(); assert!( bp.is_valid()); assert!(bp2.is_valid()); - let compressed = bp.compress(); - let compressed2 = bp2.compress(); + let compressed = bp.compress_edwards(); + let compressed2 = bp2.compress_edwards(); // Check that decompression actually gives the correct X coordinate assert_eq!(base_X, bp.X); assert_eq!(compressed, BASE_CMPRSSD); @@ -1219,7 +1219,7 @@ mod test { #[test] fn test_basepoint_mult_one_vs_basepoint() { let bp = ExtendedPoint::basepoint_mult(&Scalar::one()); - let compressed = bp.compress(); + let compressed = bp.compress_edwards(); assert_eq!(compressed, BASE_CMPRSSD); } @@ -1229,7 +1229,7 @@ mod test { fn test_basepoint_plus_basepoint() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_added = &bp + &bp; - assert_eq!( bp_added.compress(), BASE2_CMPRSSD); + assert_eq!( bp_added.compress_edwards(), BASE2_CMPRSSD); } /// Test `impl Add for ExtendedPoint` @@ -1238,7 +1238,7 @@ mod test { fn test_basepoint_plus_basepoint_cached() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_added = (&bp + &bp.to_cached()).to_extended(); - assert_eq!( bp_added.compress(), BASE2_CMPRSSD); + assert_eq!( bp_added.compress_edwards(), BASE2_CMPRSSD); } /// Test `impl Add for ExtendedPoint` @@ -1253,7 +1253,7 @@ mod test { xy2d: &bp.T * &constants::d2, }; let bp_added = (&bp + &bp_precomputed).to_extended(); - assert_eq!( bp_added.compress(), BASE2_CMPRSSD); + assert_eq!( bp_added.compress_edwards(), BASE2_CMPRSSD); } #[test] @@ -1278,14 +1278,14 @@ mod test { let aB_pc = aB.to_precomputed(); let id = ExtendedPoint::identity(); let P = &id + &aB_pc; - assert_eq!(P.to_extended().compress(), aB.compress()) + assert_eq!(P.to_extended().compress_edwards(), aB.compress_edwards()) } /// Test basepoint_mult versus a known scalar multiple from ed25519.py #[test] fn test_basepoint_mult() { let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); - assert_eq!(aB.compress(), A_TIMES_BASEPOINT); + assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT); } /// Test scalar_mult versus a known scalar multiple from ed25519.py @@ -1293,7 +1293,7 @@ mod test { fn test_scalar_mult() { let bp = BASE_CMPRSSD.decompress().unwrap(); let aB = bp.scalar_mult(&A_SCALAR); - assert_eq!(aB.compress(), A_TIMES_BASEPOINT); + assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT); } /// Test double_scalar_mult_vartime vs ed25519.py @@ -1301,7 +1301,7 @@ mod test { fn test_double_scalar_mult_vartime() { let A = A_TIMES_BASEPOINT.decompress().unwrap(); let result = double_scalar_mult_vartime(&A_SCALAR, &A, &B_SCALAR); - assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); + assert_eq!(result.compress_edwards(), DOUBLE_SCALAR_MULT_RESULT); } /// Test basepoint.double() versus the 2*basepoint constant. @@ -1309,7 +1309,7 @@ mod test { fn test_basepoint_double() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_doubled = bp.double(); - assert_eq!(bp_doubled.compress(), BASE2_CMPRSSD); + assert_eq!(bp_doubled.compress_edwards(), BASE2_CMPRSSD); } /// Test that computing 2*basepoint is the same as basepoint.double() @@ -1322,7 +1322,7 @@ mod test { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_doubled = bp.double(); let bp2 = ExtendedPoint::basepoint_mult(&two); - assert_eq!(bp_doubled.compress(), bp2.compress()); + assert_eq!(bp_doubled.compress_edwards(), bp2.compress_edwards()); } #[test] @@ -1330,7 +1330,7 @@ mod test { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_roundtrip = bp.to_projective().to_extended(); - assert_eq!(BASE_CMPRSSD, bp_roundtrip.compress()); + assert_eq!(BASE_CMPRSSD, bp_roundtrip.compress_edwards()); } /// Test computing 16*basepoint vs mult_by_pow_2 @@ -1338,7 +1338,7 @@ mod test { fn test_mult_by_pow_2() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp16 = bp.mult_by_pow_2(4); - assert_eq!(bp16.compress(), BASE16_CMPRSSD); + assert_eq!(bp16.compress_edwards(), BASE16_CMPRSSD); } /// The basepoint, doubled, minus the basepoint should equal the basepoint. @@ -1348,7 +1348,7 @@ mod test { let p2: ExtendedPoint = BASE2_CMPRSSD.decompress().unwrap(); let p3: ExtendedPoint = (&p2 - &p1.to_cached()).to_extended(); - assert_eq!(p1.compress(), p3.compress()); + assert_eq!(p1.compress_edwards(), p3.compress_edwards()); } /// The basepoint plus the identity should equal the basepoint. @@ -1358,7 +1358,7 @@ mod test { let p2: ExtendedPoint = ExtendedPoint::identity(); let p3: ExtendedPoint = (&p1 + &p2.to_cached()).to_extended(); - assert_eq!(p1.compress(), p3.compress()); + assert_eq!(p1.compress_edwards(), p3.compress_edwards()); } #[test] @@ -1484,7 +1484,7 @@ mod test { let mut rng: OsRng = OsRng::new().unwrap(); let p1: ExtendedPoint = ExtendedPoint::basepoint_mult(&Scalar::random(&mut rng)); - b.iter(| | p1.compress() ); + b.iter(| | p1.compress_edwards() ); } #[bench] From 2c83d48cfa4648cf93e8dd2041fbf0da1b073f43 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Sat, 4 Mar 2017 05:29:19 +0000 Subject: [PATCH 022/101] Demote a docstring note to inline code comment to avoid confusing users. --- src/curve.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 92457c5..da2d1a1 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -210,15 +210,11 @@ impl CompressedMontgomeryU { /// Given a Montgomery `u` coordinate, compute an Edwards `y` via /// `y = (u-1)/(u+1)`. /// - /// # Note - /// - /// Since `u = (1+y)/(1-y)` and `v = √(u(u²+Au+1))`, we can see that - /// `y = (u-1)/(u+1)`. - /// /// # Return /// /// A `FieldElement` corresponding to this coordinate, but in Edwards form. fn to_edwards_y(u: &FieldElement) -> FieldElement { + // Since `u = (1+y)/(1-y)` and `v = √(u(u²+Au+1))`, so `y = (u-1)/(u+1)`. &(u - &FieldElement::one()) * &(u + &FieldElement::one()).invert() } From e5f5dea4444d034177256e78ce585b65a6b9e5c5 Mon Sep 17 00:00:00 2001 From: Henry & Isis Date: Sun, 5 Mar 2017 15:27:26 -0800 Subject: [PATCH 023/101] Rename to_{cached,precomputed} to to_{projective,affine}_niels --- src/constants.rs | 4 ++-- src/curve.rs | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 43194a3..8b43ceb 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1682,12 +1682,12 @@ mod test { let mut P = bp; for i in 0..32 { // P = (16^2)^i * B - let mut jP = P.to_precomputed(); + let mut jP = P.to_affine_niels(); for j in 1..9 { // constants::base[i][j-1] is supposed to be // j * (16^2)^i * B assert_eq!(constants::base[i][j-1], jP); - jP = (&P + &jP).to_extended().to_precomputed(); + jP = (&P + &jP).to_extended().to_affine_niels(); } P = P.mult_by_pow_2(8); } diff --git a/src/curve.rs b/src/curve.rs index b248b19..fb1f8c2 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -478,7 +478,7 @@ impl ProjectivePoint { impl ExtendedPoint { /// Convert to a ProjectiveNielsPoint - pub fn to_cached(&self) -> ProjectiveNielsPoint { + pub fn to_projective_niels(&self) -> ProjectiveNielsPoint { ProjectiveNielsPoint{ Y_plus_X: &self.Y + &self.X, Y_minus_X: &self.Y - &self.X, @@ -507,7 +507,7 @@ impl ExtendedPoint { /// Dehomogenize to a AffineNielsPoint. /// Mainly for testing. - pub fn to_precomputed(&self) -> AffineNielsPoint { + pub fn to_affine_niels(&self) -> AffineNielsPoint { let recip = self.Z.invert(); let x = &self.X * &recip; let y = &self.Y * &recip; @@ -672,14 +672,14 @@ impl<'a,'b> Sub<&'b AffineNielsPoint> for &'a ExtendedPoint { impl<'a,'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint { type Output = ExtendedPoint; fn add(self, other: &'b ExtendedPoint) -> ExtendedPoint { - (self + &other.to_cached()).to_extended() + (self + &other.to_projective_niels()).to_extended() } } impl<'a,'b> Sub<&'b ExtendedPoint> for &'a ExtendedPoint { type Output = ExtendedPoint; fn sub(self, other: &'b ExtendedPoint) -> ExtendedPoint { - (self - &other.to_cached()).to_extended() + (self - &other.to_projective_niels()).to_extended() } } @@ -738,10 +738,10 @@ impl ScalarMult for ExtendedPoint { /// Uses a window of size 4. Note: for scalar multiplication of /// the basepoint, `basepoint_mult` is approximately 4x faster. fn scalar_mult(&self, scalar: &Scalar) -> ExtendedPoint { - let A = self.to_cached(); + let A = self.to_projective_niels(); let mut As: [ProjectiveNielsPoint; 8] = [A; 8]; for i in 0..7 { - As[i+1] = (self + &As[i]).to_extended().to_cached(); + As[i+1] = (self + &As[i]).to_extended().to_projective_niels(); } let e = scalar.to_radix_16(); let mut h = ExtendedPoint::identity(); @@ -872,9 +872,9 @@ pub fn double_scalar_mult_vartime(a: &Scalar, A: &ExtendedPoint, b: &Scalar) -> // Build a lookup table of odd multiples of A let mut Ai = [ProjectiveNielsPoint::identity(); 8]; let A2 = A.double(); - Ai[0] = A.to_cached(); + Ai[0] = A.to_projective_niels(); for i in 0..7 { - Ai[i+1] = (&A2 + &Ai[i]).to_extended().to_cached(); + Ai[i+1] = (&A2 + &Ai[i]).to_extended().to_projective_niels(); } // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] @@ -1174,7 +1174,7 @@ mod test { #[test] fn test_basepoint_plus_basepoint_cached() { let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp_added = (&bp + &bp.to_cached()).to_extended(); + let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); assert_eq!( bp_added.compress(), BASE2_CMPRSSD); } @@ -1209,10 +1209,10 @@ mod test { /// Sanity check for conversion to precomputed points #[test] - fn test_convert_to_precomputed() { + fn test_convert_to_affine_niels() { // construct a point as aB so it has denominators (ie. Z != 1) let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); - let aB_pc = aB.to_precomputed(); + let aB_pc = aB.to_affine_niels(); let id = ExtendedPoint::identity(); let P = &id + &aB_pc; assert_eq!(P.to_extended().compress(), aB.compress()) @@ -1283,7 +1283,7 @@ mod test { fn test_ge_sub() { let p1: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); let p2: ExtendedPoint = BASE2_CMPRSSD.decompress().unwrap(); - let p3: ExtendedPoint = (&p2 - &p1.to_cached()).to_extended(); + let p3: ExtendedPoint = (&p2 - &p1.to_projective_niels()).to_extended(); assert_eq!(p1.compress(), p3.compress()); } @@ -1293,7 +1293,7 @@ mod test { fn test_ge_add() { let p1: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); let p2: ExtendedPoint = ExtendedPoint::identity(); - let p3: ExtendedPoint = (&p1 + &p2.to_cached()).to_extended(); + let p3: ExtendedPoint = (&p1 + &p2.to_projective_niels()).to_extended(); assert_eq!(p1.compress(), p3.compress()); } @@ -1363,7 +1363,7 @@ mod test { #[bench] fn bench_extended_add_cached(b: &mut Bencher) { let p1 = BASE_CMPRSSD.decompress().unwrap(); - let p2 = BASE2_CMPRSSD.decompress().unwrap().to_cached(); + let p2 = BASE2_CMPRSSD.decompress().unwrap().to_projective_niels(); b.iter(| | &p1 + &p2); } @@ -1371,7 +1371,7 @@ mod test { #[bench] fn bench_extended_add_cached_to_extended(b: &mut Bencher) { let p1 = BASE_CMPRSSD.decompress().unwrap(); - let p2 = BASE2_CMPRSSD.decompress().unwrap().to_cached(); + let p2 = BASE2_CMPRSSD.decompress().unwrap().to_projective_niels(); b.iter(| | (&p1 + &p2).to_extended()); } From 9f0c6c86f3b03891e26cc1a3a28394d47e815838 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 7 Mar 2017 01:33:38 +0000 Subject: [PATCH 024/101] Change another unittest compress() to compress_edwards(). --- src/curve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index 359c8d4..56c5171 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1395,7 +1395,7 @@ mod test { #[test] fn test_compressed_identity() { - assert_eq!(ExtendedPoint::identity().compress(), + assert_eq!(ExtendedPoint::identity().compress_edwards(), CompressedEdwardsY::identity()); } From 31c350b6f2c1a0c35643f6acffbeddb271381677 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 6 Mar 2017 23:53:38 -0800 Subject: [PATCH 025/101] Split benchmarks into their own module --- src/curve.rs | 74 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index fb1f8c2..810953e 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1047,21 +1047,21 @@ mod test { 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70]); /// 4493907448824000747700850167940867464579944529806937181821189941592931634714 - static A_SCALAR: Scalar = Scalar([ + pub static A_SCALAR: Scalar = Scalar([ 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09]); /// 2506056684125797857694181776241676200180934651973138769173342316833279714961 - static B_SCALAR: Scalar = Scalar([ + pub static B_SCALAR: Scalar = Scalar([ 0x91, 0x26, 0x7a, 0xcf, 0x25, 0xc2, 0x09, 0x1b, 0xa2, 0x17, 0x74, 0x7b, 0x66, 0xf0, 0xb3, 0x2e, 0x9d, 0xf2, 0xa5, 0x67, 0x41, 0xcf, 0xda, 0xc4, 0x56, 0xa7, 0xd4, 0xaa, 0xb8, 0x60, 0x8a, 0x05]); /// A_SCALAR * basepoint, computed with ed25519.py - static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([ + pub static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([ 0xea, 0x27, 0xe2, 0x60, 0x53, 0xdf, 0x1b, 0x59, 0x56, 0xf1, 0x4d, 0x5d, 0xec, 0x3c, 0x34, 0xc3, 0x84, 0xa2, 0x69, 0xb7, 0x4c, 0xc3, 0x80, 0x3e, @@ -1337,15 +1337,27 @@ mod test { fn test_is_identity() { assert!(ExtendedPoint::identity().is_identity()); } +} + +// ------------------------------------------------------------------------ +// Benchmarks +// ------------------------------------------------------------------------ + +#[cfg(test)] +mod bench { + use test::Bencher; + use constants; + use super::*; + use super::test::{A_SCALAR, A_TIMES_BASEPOINT, B_SCALAR}; #[bench] - fn bench_basepoint_mult(b: &mut Bencher) { + fn basepoint_mult(b: &mut Bencher) { b.iter(|| ExtendedPoint::basepoint_mult(&A_SCALAR)); } #[bench] - fn bench_scalar_mult(b: &mut Bencher) { - let bp = BASE_CMPRSSD.decompress().unwrap(); + fn scalar_mult(b: &mut Bencher) { + let bp = constants::BASEPOINT; b.iter(|| bp.scalar_mult(&A_SCALAR)); } @@ -1355,61 +1367,61 @@ mod test { } #[bench] - fn bench_double_scalar_mult_vartime(bench: &mut Bencher) { + fn bench_double_scalar_mult_vartime(b: &mut Bencher) { let A = A_TIMES_BASEPOINT.decompress().unwrap(); - bench.iter(|| double_scalar_mult_vartime(&A_SCALAR, &A, &B_SCALAR)); + b.iter(|| double_scalar_mult_vartime(&A_SCALAR, &A, &B_SCALAR)); } #[bench] - fn bench_extended_add_cached(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap(); - let p2 = BASE2_CMPRSSD.decompress().unwrap().to_projective_niels(); + fn add_extended_and_cached_output_completed(b: &mut Bencher) { + let p1 = constants::BASEPOINT; + let p2 = constants::BASEPOINT.to_projective_niels(); - b.iter(| | &p1 + &p2); + b.iter(|| &p1 + &p2); } #[bench] - fn bench_extended_add_cached_to_extended(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap(); - let p2 = BASE2_CMPRSSD.decompress().unwrap().to_projective_niels(); + fn add_extended_and_cached_output_extended(b: &mut Bencher) { + let p1 = constants::BASEPOINT; + let p2 = constants::BASEPOINT.to_projective_niels(); - b.iter(| | (&p1 + &p2).to_extended()); + b.iter(|| (&p1 + &p2).to_extended()); } #[bench] - fn bench_extended_add_precomputed(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap(); + fn add_extended_and_precomputed_output_completed(b: &mut Bencher) { + let p1 = constants::BASEPOINT; let p2 = select_precomputed_point(6, &constants::base[27]); - b.iter(| | &p1 + &p2); + b.iter(|| &p1 + &p2); } #[bench] - fn bench_extended_add_precomputed_to_extended(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap(); + fn add_extended_and_precomputed_output_extended(b: &mut Bencher) { + let p1 = constants::BASEPOINT; let p2 = select_precomputed_point(6, &constants::base[27]); - b.iter(| | (&p1 + &p2).to_extended()); + b.iter(|| (&p1 + &p2).to_extended()); } #[bench] - fn bench_double(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap().to_projective(); + fn projective_double_output_completed(b: &mut Bencher) { + let p1 = constants::BASEPOINT.to_projective(); - b.iter(| | p1.double() ); + b.iter(|| p1.double() ); } #[bench] - fn bench_double_to_extended(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap().to_projective(); + fn extended_double_output_extended(b: &mut Bencher) { + let p1 = constants::BASEPOINT; - b.iter(| | p1.double().to_extended() ); + b.iter(|| p1.double() ); } #[bench] - fn bench_mult_by_pow2_4(b: &mut Bencher) { - let p1 = BASE_CMPRSSD.decompress().unwrap(); + fn mult_by_cofactor(b: &mut Bencher) { + let p1 = constants::BASEPOINT; - b.iter(| | p1.mult_by_pow_2(4) ); + b.iter(|| p1.mult_by_cofactor() ); } } From 3a9ee16a30283d5c4f4b720cb2abffc2b2f79c0e Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 6 Mar 2017 23:59:49 -0800 Subject: [PATCH 026/101] Remove test_ prefix from test functions in curve.rs --- src/curve.rs | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 810953e..6ae073a 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1078,7 +1078,7 @@ mod test { /// Test that the constant for sqrt(-486664) really is a square /// root of -486664. /// XXX this should be a test in constants.rs ?? - fn test_sqrt_minus_aplus2() { + fn sqrt_minus_aplus2() { let minus_aplus2 = FieldElement([-486664,0,0,0,0,0,0,0,0,0]); let sqrt = constants::SQRT_MINUS_APLUS2; let sq = &sqrt * &sqrt; @@ -1087,7 +1087,7 @@ mod test { /// Test Montgomery conversion against the X25519 basepoint. #[test] - fn test_basepoint_to_montgomery() { + fn basepoint_to_montgomery() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_monty = bp.compress_montgomery().unwrap(); assert_eq!(bp_monty, BASE_CMPRSSD_MONTY); @@ -1095,7 +1095,7 @@ mod test { /// Test Montgomery conversion against the X25519 basepoint. #[test] - fn test_basepoint_from_montgomery() { + fn basepoint_from_montgomery() { let bp = BASE_CMPRSSD_MONTY.decompress().unwrap(); let bp_compressed_edwards = bp.compress(); assert_eq!(bp_compressed_edwards, BASE_CMPRSSD); @@ -1106,7 +1106,7 @@ mod test { /// /// XXX what does Signal do here? #[test] - fn test_u_minus_one_monty() { + fn u_minus_one_monty() { let mut m1 = FieldElement::zero(); m1[0] = -1; let m1_bytes = m1.to_bytes(); @@ -1117,14 +1117,14 @@ mod test { /// Montgomery compression of the identity point should /// fail (it's sent to infinity). #[test] - fn test_identity_to_monty() { + fn identity_to_monty() { let id = ExtendedPoint::identity(); assert!(id.compress_montgomery().is_none()); } /// Test round-trip decompression for the basepoint. #[test] - fn test_basepoint_decompression_compression() { + fn basepoint_decompression_compression() { let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES); let bp = BASE_CMPRSSD.decompress().unwrap(); let bp2 = BASE2_CMPRSSD.decompress().unwrap(); @@ -1140,7 +1140,7 @@ mod test { /// Test sign handling in decompression #[test] - fn test_decompression_sign_handling() { + fn decompression_sign_handling() { let mut m_bp_bytes: [u8;32] = BASE_CMPRSSD.as_bytes().clone(); // Set the high bit of the last byte to flip the sign m_bp_bytes[31] |= 1 << 7; @@ -1154,7 +1154,7 @@ mod test { /// Test that computing 1*basepoint gives the correct basepoint. #[test] - fn test_basepoint_mult_one_vs_basepoint() { + fn basepoint_mult_one_vs_basepoint() { let bp = ExtendedPoint::basepoint_mult(&Scalar::one()); let compressed = bp.compress(); assert_eq!(compressed, BASE_CMPRSSD); @@ -1163,7 +1163,7 @@ mod test { /// Test `impl Add for ExtendedPoint` /// using basepoint + basepoint versus the 2*basepoint constant. #[test] - fn test_basepoint_plus_basepoint() { + fn basepoint_plus_basepoint() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_added = &bp + &bp; assert_eq!( bp_added.compress(), BASE2_CMPRSSD); @@ -1172,7 +1172,7 @@ mod test { /// Test `impl Add for ExtendedPoint` /// using the basepoint, basepoint2 constants #[test] - fn test_basepoint_plus_basepoint_cached() { + fn basepoint_plus_basepoint_cached() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); assert_eq!( bp_added.compress(), BASE2_CMPRSSD); @@ -1181,7 +1181,7 @@ mod test { /// Test `impl Add for ExtendedPoint` /// using the basepoint, basepoint2 constants #[test] - fn test_basepoint_plus_basepoint_precomputed() { + fn basepoint_plus_basepoint_precomputed() { let bp = BASE_CMPRSSD.decompress().unwrap(); // on decode, Z =1, so x = X/Z = X, y = Y/Z = Y, xy = T let bp_precomputed = AffineNielsPoint{ @@ -1194,7 +1194,7 @@ mod test { } #[test] - fn test_extended_point_equality() { + fn extended_point_equality() { let two = [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; let id1 = ExtendedPoint::identity(); @@ -1209,7 +1209,7 @@ mod test { /// Sanity check for conversion to precomputed points #[test] - fn test_convert_to_affine_niels() { + fn convert_to_affine_niels() { // construct a point as aB so it has denominators (ie. Z != 1) let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); let aB_pc = aB.to_affine_niels(); @@ -1220,14 +1220,14 @@ mod test { /// Test basepoint_mult versus a known scalar multiple from ed25519.py #[test] - fn test_basepoint_mult() { + fn basepoint_mult() { let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); assert_eq!(aB.compress(), A_TIMES_BASEPOINT); } /// Test scalar_mult versus a known scalar multiple from ed25519.py #[test] - fn test_scalar_mult() { + fn scalar_mult() { let bp = BASE_CMPRSSD.decompress().unwrap(); let aB = bp.scalar_mult(&A_SCALAR); assert_eq!(aB.compress(), A_TIMES_BASEPOINT); @@ -1235,7 +1235,7 @@ mod test { /// Test double_scalar_mult_vartime vs ed25519.py #[test] - fn test_double_scalar_mult_vartime() { + fn double_scalar_mult_vartime_vs_ed25519py() { let A = A_TIMES_BASEPOINT.decompress().unwrap(); let result = double_scalar_mult_vartime(&A_SCALAR, &A, &B_SCALAR); assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); @@ -1243,7 +1243,7 @@ mod test { /// Test basepoint.double() versus the 2*basepoint constant. #[test] - fn test_basepoint_double() { + fn basepoint_double() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_doubled = bp.double(); assert_eq!(bp_doubled.compress(), BASE2_CMPRSSD); @@ -1251,7 +1251,7 @@ mod test { /// Test that computing 2*basepoint is the same as basepoint.double() #[test] - fn test_scalar_mult_two_vs_double() { + fn scalar_mult_two_vs_double() { // XXX this seems like a pain point: better way to construct small // scalars? let two = Scalar([ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1263,7 +1263,7 @@ mod test { } #[test] - fn test_basepoint_projective_extended_round_trip() { + fn basepoint_projective_extended_round_trip() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp_roundtrip = bp.to_projective().to_extended(); @@ -1272,7 +1272,7 @@ mod test { /// Test computing 16*basepoint vs mult_by_pow_2 #[test] - fn test_mult_by_pow_2() { + fn mult_by_pow_2() { let bp = BASE_CMPRSSD.decompress().unwrap(); let bp16 = bp.mult_by_pow_2(4); assert_eq!(bp16.compress(), BASE16_CMPRSSD); @@ -1280,7 +1280,7 @@ mod test { /// The basepoint, doubled, minus the basepoint should equal the basepoint. #[test] - fn test_ge_sub() { + fn ge_sub() { let p1: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); let p2: ExtendedPoint = BASE2_CMPRSSD.decompress().unwrap(); let p3: ExtendedPoint = (&p2 - &p1.to_projective_niels()).to_extended(); @@ -1290,7 +1290,7 @@ mod test { /// The basepoint plus the identity should equal the basepoint. #[test] - fn test_ge_add() { + fn ge_add() { let p1: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); let p2: ExtendedPoint = ExtendedPoint::identity(); let p3: ExtendedPoint = (&p1 + &p2.to_projective_niels()).to_extended(); @@ -1299,7 +1299,7 @@ mod test { } #[test] - fn test_AffineNielsPoint_conditional_assign() { + fn AffineNielsPoint_conditional_assign() { let id = AffineNielsPoint::identity(); let mut p1 = AffineNielsPoint::identity(); let p2: AffineNielsPoint = AffineNielsPoint{ @@ -1319,7 +1319,7 @@ mod test { } #[test] - fn test_is_small_order() { + fn is_small_order() { let p1: ExtendedPoint = ExtendedPoint::identity(); let p2: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); @@ -1328,13 +1328,13 @@ mod test { } #[test] - fn test_compressed_identity() { + fn compressed_identity() { assert_eq!(ExtendedPoint::identity().compress(), CompressedEdwardsY::identity()); } #[test] - fn test_is_identity() { + fn is_identity() { assert!(ExtendedPoint::identity().is_identity()); } } From 0585af6c68f3b3b8a96fcfe13692254b2a2fc03d Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:03:59 -0800 Subject: [PATCH 027/101] Move sqrt(-(A+2)) test to constants.rs --- src/constants.rs | 10 ++++++++++ src/curve.rs | 11 ----------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 8b43ceb..6c4b53b 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1625,6 +1625,16 @@ mod test { assert_eq!(one, &two * &constants::HALF); } + #[test] + /// Test that the constant for sqrt(-486664) really is a square + /// root of -486664. + fn sqrt_minus_aplus2() { + let minus_aplus2 = FieldElement([-486664,0,0,0,0,0,0,0,0,0]); + let sqrt = constants::SQRT_MINUS_APLUS2; + let sq = &sqrt * &sqrt; + assert_eq!(sq, minus_aplus2); + } + #[test] /// Test that SQRT_M1 and MSQRT_M1 are square roots of -1 fn test_sqrt_minus_one() { diff --git a/src/curve.rs b/src/curve.rs index 6ae073a..74a4862 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1074,17 +1074,6 @@ mod test { 0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85, 0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13, 0x2b, 0x42]); - #[test] - /// Test that the constant for sqrt(-486664) really is a square - /// root of -486664. - /// XXX this should be a test in constants.rs ?? - fn sqrt_minus_aplus2() { - let minus_aplus2 = FieldElement([-486664,0,0,0,0,0,0,0,0,0]); - let sqrt = constants::SQRT_MINUS_APLUS2; - let sq = &sqrt * &sqrt; - assert_eq!(sq, minus_aplus2); - } - /// Test Montgomery conversion against the X25519 basepoint. #[test] fn basepoint_to_montgomery() { From b5b0ac7628d9189fbc89754b6e0ea378e1b49f0c Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:11:16 -0800 Subject: [PATCH 028/101] Add doc comments to test vectors --- src/curve.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index 74a4862..625e73e 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1034,12 +1034,14 @@ mod test { [0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21]; + /// Compressed Edwards Y form of 2*basepoint. static BASE2_CMPRSSD: CompressedEdwardsY = CompressedEdwardsY([0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0xe, 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22]); + /// Compressed Edwards Y form of 16*basepoint. static BASE16_CMPRSSD: CompressedEdwardsY = CompressedEdwardsY([0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, @@ -1068,6 +1070,7 @@ mod test { 0xa8, 0xe2, 0xe7, 0xc9, 0x42, 0x5e, 0x40, 0xa5]); /// A_SCALAR * (A_TIMES_BASEPOINT) + B_SCALAR * BASEPOINT + /// computed with ed25519.py static DOUBLE_SCALAR_MULT_RESULT: CompressedEdwardsY = CompressedEdwardsY([ 0x7d, 0xfd, 0x6c, 0x45, 0xaf, 0x6d, 0x6e, 0x0e, 0xba, 0x20, 0x37, 0x1a, 0x23, 0x64, 0x59, 0xc4, From 94416eb1cb9ccbd1546e72f2fdf211cde9e3c33c Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:11:47 -0800 Subject: [PATCH 029/101] Clean decompression_sign_handling --- src/curve.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 625e73e..ecadf5c 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1119,29 +1119,27 @@ mod test { fn basepoint_decompression_compression() { let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES); let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp2 = BASE2_CMPRSSD.decompress().unwrap(); assert!( bp.is_valid()); - assert!(bp2.is_valid()); let compressed = bp.compress(); - let compressed2 = bp2.compress(); // Check that decompression actually gives the correct X coordinate assert_eq!(base_X, bp.X); assert_eq!(compressed, BASE_CMPRSSD); - assert_eq!(compressed2, BASE2_CMPRSSD); } /// Test sign handling in decompression #[test] fn decompression_sign_handling() { - let mut m_bp_bytes: [u8;32] = BASE_CMPRSSD.as_bytes().clone(); - // Set the high bit of the last byte to flip the sign - m_bp_bytes[31] |= 1 << 7; - let m_bp = CompressedEdwardsY(m_bp_bytes).decompress().unwrap(); - let bp = BASE_CMPRSSD.decompress().unwrap(); - assert_eq!(m_bp.X, -(&bp.X)); - assert_eq!(m_bp.Y, bp.Y); - assert_eq!(m_bp.Z, bp.Z); - assert_eq!(m_bp.T, -(&bp.T)); + // Manually set the high bit of the last byte to flip the sign + let mut minus_basepoint_bytes = BASE_CMPRSSD.as_bytes().clone(); + minus_basepoint_bytes[31] |= 1 << 7; + let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes) + .decompress().unwrap(); + // Test projective coordinates exactly since we know they should + // only differ by a flipped sign. + assert_eq!(minus_basepoint.X, -(&constants::BASEPOINT.X)); + assert_eq!(minus_basepoint.Y, constants::BASEPOINT.Y); + assert_eq!(minus_basepoint.Z, constants::BASEPOINT.Z); + assert_eq!(minus_basepoint.T, -(&constants::BASEPOINT.T)); } /// Test that computing 1*basepoint gives the correct basepoint. From 78fe9c490dc147b7dfe3a67fc8ebdf60d2d6990b Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:48:36 -0800 Subject: [PATCH 030/101] Eliminate BASE_CMPRSSD or rename it to constants::BASE_CMPRSSD and do misc cleanup --- src/curve.rs | 124 +++++++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 72 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index ecadf5c..47f16dd 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1017,9 +1017,7 @@ mod test { use scalar::Scalar; use subtle::CTAssignable; use constants; - use constants::BASE_CMPRSSD; use super::*; - use super::select_precomputed_point; /// The X25519 basepoint, in compressed Montgomery form. static BASE_CMPRSSD_MONTY: CompressedMontgomeryU = @@ -1080,17 +1078,15 @@ mod test { /// Test Montgomery conversion against the X25519 basepoint. #[test] fn basepoint_to_montgomery() { - let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp_monty = bp.compress_montgomery().unwrap(); - assert_eq!(bp_monty, BASE_CMPRSSD_MONTY); + assert_eq!(constants::BASEPOINT.compress_montgomery().unwrap(), + BASE_CMPRSSD_MONTY); } /// Test Montgomery conversion against the X25519 basepoint. #[test] fn basepoint_from_montgomery() { - let bp = BASE_CMPRSSD_MONTY.decompress().unwrap(); - let bp_compressed_edwards = bp.compress(); - assert_eq!(bp_compressed_edwards, BASE_CMPRSSD); + assert_eq!(BASE_CMPRSSD_MONTY.decompress().unwrap().compress(), + constants::BASE_CMPRSSD); } /// If u = -1, then v^2 = u*(u^2+486662*u+1) = 486660. @@ -1118,19 +1114,18 @@ mod test { #[test] fn basepoint_decompression_compression() { let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES); - let bp = BASE_CMPRSSD.decompress().unwrap(); - assert!( bp.is_valid()); - let compressed = bp.compress(); + let bp = constants::BASE_CMPRSSD.decompress().unwrap(); + assert!(bp.is_valid()); // Check that decompression actually gives the correct X coordinate assert_eq!(base_X, bp.X); - assert_eq!(compressed, BASE_CMPRSSD); + assert_eq!(bp.compress(), constants::BASE_CMPRSSD); } /// Test sign handling in decompression #[test] fn decompression_sign_handling() { // Manually set the high bit of the last byte to flip the sign - let mut minus_basepoint_bytes = BASE_CMPRSSD.as_bytes().clone(); + let mut minus_basepoint_bytes = constants::BASE_CMPRSSD.as_bytes().clone(); minus_basepoint_bytes[31] |= 1 << 7; let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes) .decompress().unwrap(); @@ -1147,14 +1142,14 @@ mod test { fn basepoint_mult_one_vs_basepoint() { let bp = ExtendedPoint::basepoint_mult(&Scalar::one()); let compressed = bp.compress(); - assert_eq!(compressed, BASE_CMPRSSD); + assert_eq!(compressed, constants::BASE_CMPRSSD); } /// Test `impl Add for ExtendedPoint` /// using basepoint + basepoint versus the 2*basepoint constant. #[test] - fn basepoint_plus_basepoint() { - let bp = BASE_CMPRSSD.decompress().unwrap(); + fn basepoint_plus_basepoint_vs_basepoint2() { + let bp = constants::BASEPOINT; let bp_added = &bp + &bp; assert_eq!( bp_added.compress(), BASE2_CMPRSSD); } @@ -1162,8 +1157,8 @@ mod test { /// Test `impl Add for ExtendedPoint` /// using the basepoint, basepoint2 constants #[test] - fn basepoint_plus_basepoint_cached() { - let bp = BASE_CMPRSSD.decompress().unwrap(); + fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() { + let bp = constants::BASEPOINT; let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); assert_eq!( bp_added.compress(), BASE2_CMPRSSD); } @@ -1171,55 +1166,49 @@ mod test { /// Test `impl Add for ExtendedPoint` /// using the basepoint, basepoint2 constants #[test] - fn basepoint_plus_basepoint_precomputed() { - let bp = BASE_CMPRSSD.decompress().unwrap(); - // on decode, Z =1, so x = X/Z = X, y = Y/Z = Y, xy = T - let bp_precomputed = AffineNielsPoint{ - y_plus_x: &bp.Y + &bp.X, - y_minus_x: &bp.Y - &bp.X, - xy2d: &bp.T * &constants::d2, - }; - let bp_added = (&bp + &bp_precomputed).to_extended(); - assert_eq!( bp_added.compress(), BASE2_CMPRSSD); + fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() { + let bp = constants::BASEPOINT; + let bp_affine_niels = bp.to_affine_niels(); + let bp_added = (&bp + &bp_affine_niels).to_extended(); + assert_eq!( bp_added.compress(), BASE2_CMPRSSD); } + /// Check that equality of `ExtendedPoints` handles projective + /// coordinates correctly. #[test] - fn extended_point_equality() { - let two = [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + fn extended_point_equality_handles_scaling() { + let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; let id1 = ExtendedPoint::identity(); let id2 = ExtendedPoint{ X: FieldElement::zero(), - Y: FieldElement::from_bytes(&two), - Z: FieldElement::from_bytes(&two), - T: FieldElement::zero()}; - + Y: FieldElement::from_bytes(&two_bytes), + Z: FieldElement::from_bytes(&two_bytes), + T: FieldElement::zero() + }; assert!(id1.ct_eq(&id2) == 1u8); } /// Sanity check for conversion to precomputed points #[test] - fn convert_to_affine_niels() { + fn to_affine_niels_clears_denominators() { // construct a point as aB so it has denominators (ie. Z != 1) let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); - let aB_pc = aB.to_affine_niels(); - let id = ExtendedPoint::identity(); - let P = &id + &aB_pc; - assert_eq!(P.to_extended().compress(), aB.compress()) + let aB_affine_niels = aB.to_affine_niels(); + let also_aB = (&ExtendedPoint::identity() + &aB_affine_niels).to_extended(); + assert_eq!(aB.compress(), also_aB.compress()); } /// Test basepoint_mult versus a known scalar multiple from ed25519.py #[test] - fn basepoint_mult() { + fn basepoint_mult_vs_ed25519py() { let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); assert_eq!(aB.compress(), A_TIMES_BASEPOINT); } /// Test scalar_mult versus a known scalar multiple from ed25519.py #[test] - fn scalar_mult() { - let bp = BASE_CMPRSSD.decompress().unwrap(); - let aB = bp.scalar_mult(&A_SCALAR); + fn scalar_mult_vs_ed25519py() { + let aB = constants::BASEPOINT.scalar_mult(&A_SCALAR); assert_eq!(aB.compress(), A_TIMES_BASEPOINT); } @@ -1233,45 +1222,36 @@ mod test { /// Test basepoint.double() versus the 2*basepoint constant. #[test] - fn basepoint_double() { - let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp_doubled = bp.double(); - assert_eq!(bp_doubled.compress(), BASE2_CMPRSSD); + fn basepoint_double_vs_basepoint2() { + assert_eq!(constants::BASEPOINT.double().compress(), BASE2_CMPRSSD); } /// Test that computing 2*basepoint is the same as basepoint.double() #[test] - fn scalar_mult_two_vs_double() { - // XXX this seems like a pain point: better way to construct small - // scalars? - let two = Scalar([ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]); - let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp_doubled = bp.double(); - let bp2 = ExtendedPoint::basepoint_mult(&two); - assert_eq!(bp_doubled.compress(), bp2.compress()); + fn basepoint_mult_two_vs_basepoint2() { + let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; + let bp2 = ExtendedPoint::basepoint_mult(&Scalar(two_bytes)); + assert_eq!(bp2.compress(), BASE2_CMPRSSD); } + /// Check that converting to projective and then back to extended round-trips. #[test] fn basepoint_projective_extended_round_trip() { - let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp_roundtrip = bp.to_projective().to_extended(); - - assert_eq!(BASE_CMPRSSD, bp_roundtrip.compress()); + assert_eq!(constants::BASEPOINT.to_projective().to_extended().compress(), + constants::BASE_CMPRSSD); } - /// Test computing 16*basepoint vs mult_by_pow_2 + /// Test computing 16*basepoint vs mult_by_pow_2(4) #[test] - fn mult_by_pow_2() { - let bp = BASE_CMPRSSD.decompress().unwrap(); - let bp16 = bp.mult_by_pow_2(4); + fn basepoint16_vs_mult_by_pow_2_4() { + let bp16 = constants::BASEPOINT.mult_by_pow_2(4); assert_eq!(bp16.compress(), BASE16_CMPRSSD); } /// The basepoint, doubled, minus the basepoint should equal the basepoint. #[test] fn ge_sub() { - let p1: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); + let p1: ExtendedPoint = constants::BASE_CMPRSSD.decompress().unwrap(); let p2: ExtendedPoint = BASE2_CMPRSSD.decompress().unwrap(); let p3: ExtendedPoint = (&p2 - &p1.to_projective_niels()).to_extended(); @@ -1281,7 +1261,7 @@ mod test { /// The basepoint plus the identity should equal the basepoint. #[test] fn ge_add() { - let p1: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); + let p1: ExtendedPoint = constants::BASE_CMPRSSD.decompress().unwrap(); let p2: ExtendedPoint = ExtendedPoint::identity(); let p3: ExtendedPoint = (&p1 + &p2.to_projective_niels()).to_extended(); @@ -1310,11 +1290,11 @@ mod test { #[test] fn is_small_order() { - let p1: ExtendedPoint = ExtendedPoint::identity(); - let p2: ExtendedPoint = BASE_CMPRSSD.decompress().unwrap(); - - assert!(p1.is_small_order() == true); - assert!(p2.is_small_order() == false); + assert!(ExtendedPoint::identity().is_small_order() == true); + assert!(constants::BASEPOINT.is_small_order() == false); + for torsion_point in &constants::EIGHT_TORSION { + assert!(torsion_point.is_small_order() == true); + } } #[test] From 9414a2f4dbf83d2c2d2882f11821915685135619 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:49:21 -0800 Subject: [PATCH 031/101] Remove old tests that aren't so useful any more --- src/curve.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 47f16dd..7fd4568 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1248,26 +1248,6 @@ mod test { assert_eq!(bp16.compress(), BASE16_CMPRSSD); } - /// The basepoint, doubled, minus the basepoint should equal the basepoint. - #[test] - fn ge_sub() { - let p1: ExtendedPoint = constants::BASE_CMPRSSD.decompress().unwrap(); - let p2: ExtendedPoint = BASE2_CMPRSSD.decompress().unwrap(); - let p3: ExtendedPoint = (&p2 - &p1.to_projective_niels()).to_extended(); - - assert_eq!(p1.compress(), p3.compress()); - } - - /// The basepoint plus the identity should equal the basepoint. - #[test] - fn ge_add() { - let p1: ExtendedPoint = constants::BASE_CMPRSSD.decompress().unwrap(); - let p2: ExtendedPoint = ExtendedPoint::identity(); - let p3: ExtendedPoint = (&p1 + &p2.to_projective_niels()).to_extended(); - - assert_eq!(p1.compress(), p3.compress()); - } - #[test] fn AffineNielsPoint_conditional_assign() { let id = AffineNielsPoint::identity(); From 47143e91141cf39666c72386ccd9f582109b89fa Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:55:32 -0800 Subject: [PATCH 032/101] Rewrite conditional assignment test for AffineNielsPoints --- src/curve.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 7fd4568..ee2c74e 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1248,24 +1248,17 @@ mod test { assert_eq!(bp16.compress(), BASE16_CMPRSSD); } + /// Test that the conditional assignment trait works for AffineNielsPoints. #[test] - fn AffineNielsPoint_conditional_assign() { + fn conditional_assign_for_affine_niels_point() { let id = AffineNielsPoint::identity(); let mut p1 = AffineNielsPoint::identity(); - let p2: AffineNielsPoint = AffineNielsPoint{ - y_plus_x: FieldElement([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), - y_minus_x: FieldElement([11, 22, 33, 44, 55, 66, 77, 88, 99, 100]), - xy2d: FieldElement([10, 20, 30, 40, 50, 60, 70, 80, 90, 101]), - }; + let bp = constants::BASEPOINT.to_affine_niels(); - p1.conditional_assign(&p2, 0); - assert_eq!(p1.y_plus_x, id.y_plus_x); - assert_eq!(p1.y_minus_x, id.y_minus_x); - assert_eq!(p1.xy2d, id.xy2d); - p1.conditional_assign(&p2, 1); - assert_eq!(p1.y_plus_x, p2.y_plus_x); - assert_eq!(p1.y_minus_x, p2.y_minus_x); - assert_eq!(p1.xy2d, p2.xy2d); + p1.conditional_assign(&bp, 0); + assert_eq!(p1, id); + p1.conditional_assign(&bp, 1); + assert_eq!(p1, bp); } #[test] From cf24cb89008db0264391c7577a8d2deca274c16d Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:56:17 -0800 Subject: [PATCH 033/101] Also test points that are not the identity --- src/curve.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index ee2c74e..52a3b90 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1278,7 +1278,8 @@ mod test { #[test] fn is_identity() { - assert!(ExtendedPoint::identity().is_identity()); + assert!(ExtendedPoint::identity().is_identity() == true); + assert!(constants::BASEPOINT.is_identity() == false); } } From e446bc8a1f5704fc8c38d8bd700a631b716368a6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 00:57:36 -0800 Subject: [PATCH 034/101] The identity point is already in EIGHT_TORSION --- src/curve.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index 52a3b90..c433767 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1263,8 +1263,9 @@ mod test { #[test] fn is_small_order() { - assert!(ExtendedPoint::identity().is_small_order() == true); + // The basepoint has large prime order assert!(constants::BASEPOINT.is_small_order() == false); + // constants::EIGHT_TORSION has all points of small order. for torsion_point in &constants::EIGHT_TORSION { assert!(torsion_point.is_small_order() == true); } From 913e699145772a3207c1bdcb5e45016516e0e911 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 01:28:38 -0800 Subject: [PATCH 035/101] Rename Decaf tests --- src/decaf.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/decaf.rs b/src/decaf.rs index 93f22e2..aa2ded0 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -297,28 +297,27 @@ mod test { use super::*; #[test] - #[should_panic] - fn test_decaf_decompress_negative_s_fails() { + fn decaf_decompress_negative_s_fails() { // constants::d is neg, so decompression should fail as |d| != d. let bad_compressed = CompressedDecaf(constants::d.to_bytes()); - bad_compressed.decompress().unwrap(); + assert!(bad_compressed.decompress().is_none()); } #[test] - fn test_decaf_decompress_id() { + fn decaf_decompress_id() { let compressed_id = CompressedDecaf::identity(); let id = compressed_id.decompress().unwrap(); assert_eq!(id.0.compress(), CompressedEdwardsY::identity()); } #[test] - fn test_decaf_compress_id() { + fn decaf_compress_id() { let id = DecafPoint::identity(); assert_eq!(id.compress(), CompressedDecaf::identity()); } #[test] - fn test_decaf_basepoint_roundtrip() { + fn decaf_basepoint_roundtrip() { let bp_compressed_decaf = DecafPoint::basepoint().compress(); let bp_recaf = bp_compressed_decaf.decompress().unwrap().0; // Check that bp_recaf differs from bp by a point of order 4 @@ -328,7 +327,7 @@ mod test { } #[test] - fn test_decaf_four_torsion_basepoint() { + fn decaf_four_torsion_basepoint() { let bp = DecafPoint::basepoint(); let bp_coset = bp.coset4(); for i in 0..4 { @@ -337,7 +336,7 @@ mod test { } #[test] - fn test_decaf_four_torsion_random() { + fn decaf_four_torsion_random() { let mut rng = OsRng::new().unwrap(); let s = Scalar::random(&mut rng); let P = DecafPoint::basepoint_mult(&s); @@ -348,16 +347,16 @@ mod test { } #[test] - fn test_decaf_random_roundtrip() { + fn decaf_random_roundtrip() { let mut rng = OsRng::new().unwrap(); for j in 0..100 { - let s = Scalar::random(&mut rng); - let P = DecafPoint::basepoint_mult(&s); - let compressed_P = P.compress(); - let Q = compressed_P.decompress().unwrap(); - for i in 0..4 { - assert_eq!(P, Q); - } + let s = Scalar::random(&mut rng); + let P = DecafPoint::basepoint_mult(&s); + let compressed_P = P.compress(); + let Q = compressed_P.decompress().unwrap(); + for i in 0..4 { + assert_eq!(P, Q); + } } } } From b61ed818b87dc27f3021a46bd0890f832d690e9c Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 01:32:11 -0800 Subject: [PATCH 036/101] Remove all remaining warnings --- src/constants.rs | 13 ------------- src/curve.rs | 4 ---- src/decaf.rs | 7 ++----- src/scalar.rs | 2 -- 4 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 6c4b53b..112d060 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1574,19 +1574,12 @@ pub const base: [[AffineNielsPoint; 8]; 32] = [ #[cfg(test)] mod test { use field::FieldElement; - use curve::AffineNielsPoint; - use curve::CompressedEdwardsY; - use curve::ExtendedPoint; - use curve::Identity; use curve::IsIdentity; use curve::ValidityCheck; use constants; #[test] fn test_eight_torsion() { - let mut bytes = [0;32]; - bytes[0] = 1; - let compressed_id = CompressedEdwardsY(bytes); for i in 0..8 { let Q = constants::EIGHT_TORSION[i].mult_by_pow_2(3); assert!(Q.is_valid()); @@ -1596,9 +1589,6 @@ mod test { #[test] fn test_four_torsion() { - let mut bytes = [0;32]; - bytes[0] = 1; - let compressed_id = CompressedEdwardsY(bytes); for i in (0..8).filter(|i| i % 2 == 0) { let Q = constants::EIGHT_TORSION[i].mult_by_pow_2(2); assert!(Q.is_valid()); @@ -1608,9 +1598,6 @@ mod test { #[test] fn test_two_torsion() { - let mut bytes = [0;32]; - bytes[0] = 1; - let compressed_id = CompressedEdwardsY(bytes); for i in (0..8).filter(|i| i % 4 == 0) { let Q = constants::EIGHT_TORSION[i].mult_by_pow_2(1); assert!(Q.is_valid()); diff --git a/src/curve.rs b/src/curve.rs index c433767..e965078 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -80,7 +80,6 @@ use core::fmt::Debug; use core::iter::Iterator; use core::ops::{Add, Sub, Neg}; -use core::cmp::{PartialEq, Eq}; use constants; use field::FieldElement; @@ -1010,9 +1009,6 @@ impl Debug for ProjectiveNielsPoint { #[cfg(test)] mod test { - use test::Bencher; - use rand::OsRng; - use field::FieldElement; use scalar::Scalar; use subtle::CTAssignable; diff --git a/src/decaf.rs b/src/decaf.rs index aa2ded0..ec8e488 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -289,7 +289,6 @@ mod test { use scalar::Scalar; use constants; - use constants::BASE_CMPRSSD; use curve::CompressedEdwardsY; use curve::ExtendedPoint; use curve::BasepointMult; @@ -349,14 +348,12 @@ mod test { #[test] fn decaf_random_roundtrip() { let mut rng = OsRng::new().unwrap(); - for j in 0..100 { + for _ in 0..100 { let s = Scalar::random(&mut rng); let P = DecafPoint::basepoint_mult(&s); let compressed_P = P.compress(); let Q = compressed_P.decompress().unwrap(); - for i in 0..4 { - assert_eq!(P, Q); - } + assert_eq!(P, Q); } } } diff --git a/src/scalar.rs b/src/scalar.rs index 4aed3f4..0f70a19 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -37,7 +37,6 @@ use core::fmt::Debug; use rand::Rng; use digest::Digest; -use generic_array::GenericArray; use generic_array::typenum::U64; use constants; @@ -593,7 +592,6 @@ impl UnpackedScalar { #[cfg(test)] mod test { - use rand::Rng; use rand::OsRng; use super::*; use test::Bencher; From 0e9dc1d38dbc813e96ee02eef1f40e9b4a2baf18 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 23:01:49 -0800 Subject: [PATCH 037/101] Remove warnings about unused variables These bindings are shadowed by the later let statements, so they're considered unused. --- src/curve.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 5ec04ea..c8e53da 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -228,9 +228,6 @@ impl CompressedMontgomeryU { fn to_montgomery_v(u: &FieldElement) -> (u8, FieldElement) { let one: FieldElement = FieldElement::one(); let v_squared: FieldElement = u * &(&(&u.square() + &(&(&constants::A * u) + &one))); - let v_inv: FieldElement; - let v: FieldElement; - let okay: u8; let (okay, v_inv) = v_squared.invsqrt(); let v = &v_inv * &v_squared; From ab6d32efe17f74a3b169ca2c8ad1c610325b4b97 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 7 Mar 2017 23:03:48 -0800 Subject: [PATCH 038/101] Make functions pub to suppress dead code warnings --- src/curve.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index c8e53da..9357f5a 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -211,7 +211,7 @@ impl CompressedMontgomeryU { /// # Return /// /// A `FieldElement` corresponding to this coordinate, but in Edwards form. - fn to_edwards_y(u: &FieldElement) -> FieldElement { + pub fn to_edwards_y(u: &FieldElement) -> FieldElement { // Since `u = (1+y)/(1-y)` and `v = √(u(u²+Au+1))`, so `y = (u-1)/(u+1)`. &(u - &FieldElement::one()) * &(u + &FieldElement::one()).invert() } @@ -225,7 +225,7 @@ impl CompressedMontgomeryU { /// A tuple of (`u8`, `FieldElement`), where the `u8` is `1` if the v² was /// actually a square and `0` if otherwise, along with a `FieldElement`: the /// Montgomery `v` corresponding to this `u`. - fn to_montgomery_v(u: &FieldElement) -> (u8, FieldElement) { + pub fn to_montgomery_v(u: &FieldElement) -> (u8, FieldElement) { let one: FieldElement = FieldElement::one(); let v_squared: FieldElement = u * &(&(&u.square() + &(&(&constants::A * u) + &one))); @@ -260,7 +260,7 @@ impl CompressedMontgomeryU { /// A `FieldElement`, the Edwards `x` coordinate, by using `(u, v)` to /// convert from Montgomery to Edwards form via the right-hand side of the /// equation: `x=(u/v)*sqrt(-A-2)`. - fn to_edwards_x(u: &FieldElement, v: &FieldElement, sign: &u8) -> FieldElement { + pub fn to_edwards_x(u: &FieldElement, v: &FieldElement, sign: &u8) -> FieldElement { let mut x: FieldElement = &(u * &v.invert()) * &constants::SQRT_MINUS_APLUS2; let neg_x: FieldElement = -(&x); let current_sign: u8 = x.is_negative_ed25519(); From 384cf1df310c774ab516c5bc55d215049ba62d58 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 8 Mar 2017 00:19:08 -0800 Subject: [PATCH 039/101] no_std import cleanups - Gate no_std on the "std" feature - Import core when std is present - Import collections when std is absent - Add a placeholder gated "use" directive for Box in curve.rs --- src/curve.rs | 3 +++ src/lib.rs | 13 ++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 5d770d1..13c9686 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -91,6 +91,9 @@ use subtle::CTAssignable; use subtle::CTEq; use subtle::CTNegatable; +#[cfg(not(feature = "std"))] +use collections::boxed::Box; + // ------------------------------------------------------------------------ // Compressed points // ------------------------------------------------------------------------ diff --git a/src/lib.rs b/src/lib.rs index fe26b70..41d0898 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,8 @@ // - Isis Agora Lovecruft // - Henry de Valence -#![no_std] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(collections))] #![allow(unused_features)] #![feature(test)] #![deny(missing_docs)] // refuse to compile if documentation is missing @@ -32,19 +33,21 @@ //! hatred of the Daleks. Rusty destroys the other Daleks and departs the //! ship, determined to track down and bring an end to the Dalek race. -#[cfg(test)] -#[macro_use] -extern crate std; - #[cfg(test)] extern crate test; #[macro_use] extern crate arrayref; +#[cfg(feature = "std")] +extern crate core; + #[cfg(feature = "std")] extern crate rand; +#[cfg(not(feature = "std"))] +extern crate collections; + // Modules for low-level operations directly on field elements and curve points. pub mod field; From 2039a66cb3c33558aea2e57c6fa90a8590d0b960 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Fri, 10 Mar 2017 02:35:38 +0000 Subject: [PATCH 040/101] Fix two decaf unittests to use compress_edwards(). --- src/decaf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decaf.rs b/src/decaf.rs index 93f22e2..c9cda46 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -308,7 +308,7 @@ mod test { fn test_decaf_decompress_id() { let compressed_id = CompressedDecaf::identity(); let id = compressed_id.decompress().unwrap(); - assert_eq!(id.0.compress(), CompressedEdwardsY::identity()); + assert_eq!(id.0.compress_edwards(), CompressedEdwardsY::identity()); } #[test] @@ -324,7 +324,7 @@ mod test { // Check that bp_recaf differs from bp by a point of order 4 let diff = &ExtendedPoint::basepoint() - &bp_recaf; let diff4 = diff.mult_by_pow_2(4); - assert_eq!(diff4.compress(), ExtendedPoint::identity().compress()); + assert_eq!(diff4.compress_edwards(), ExtendedPoint::identity().compress_edwards()); } #[test] From 1f871ea0a002422bf28269f993f40d6f6b1000b4 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Fri, 10 Mar 2017 02:36:01 +0000 Subject: [PATCH 041/101] Obsessive whitespace fix. --- src/field.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field.rs b/src/field.rs index cb29d70..3094b0f 100644 --- a/src/field.rs +++ b/src/field.rs @@ -331,7 +331,7 @@ impl FieldElement { /// # Return /// /// Returns a new FieldElement. - pub fn from_bytes(data: &[u8;32]) -> FieldElement { //FeFromBytes + pub fn from_bytes(data: &[u8; 32]) -> FieldElement { //FeFromBytes let mut h = [0i64;10]; h[0] = load4(&data[ 0..]); h[1] = load3(&data[ 4..]) << 6; From f9c237bd6a606b9a8d8dff307e6cb1fa25472a1a Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Fri, 10 Mar 2017 02:36:15 +0000 Subject: [PATCH 042/101] Typo fix in utils module docstring. --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index ad53166..c6bfae3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,7 +9,7 @@ // - Isis Agora Lovecruft // - Henry de Valence -//! Miscellaneous common utility function. +//! Miscellaneous common utility functions. /// Convert an array of (at least) three bytes into an i64. #[inline] From 7a2ea44ce647342539bbedca5639bae5de15de83 Mon Sep 17 00:00:00 2001 From: Henry & Isis Date: Sat, 11 Mar 2017 12:01:29 -0800 Subject: [PATCH 043/101] Test multiplication by basepoint order --- src/curve.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index beb92a3..903375a 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1270,6 +1270,13 @@ mod test { assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT); } + /// Test that multiplication by the basepoint order kills the basepoint + #[test] + fn basepoint_mult_by_basepoint_order() { + let should_be_id = ExtendedPoint::basepoint_mult(&constants::l); + assert!(should_be_id.is_identity()); + } + /// Test scalar_mult versus a known scalar multiple from ed25519.py #[test] fn scalar_mult_vs_ed25519py() { From 05fa1318b900b67e5833653d9022cbcced24b64f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 6 Mar 2017 21:11:01 -0800 Subject: [PATCH 044/101] First work on dynamic basepoint table generation --- src/curve.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index 903375a..11a37a8 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -81,6 +81,9 @@ use core::fmt::Debug; use core::iter::Iterator; use core::ops::{Add, Sub, Neg}; +#[cfg(feature = "std")] +use std::boxed::Box; + use constants; use field::FieldElement; use scalar::Scalar; @@ -822,6 +825,83 @@ impl ScalarMult for ExtendedPoint { } } +/// Precomputation +#[derive(Clone)] +pub struct BasepointTable(pub [[AffineNielsPoint; 8]; 32]); + +impl BasepointTable { + /// Create a table of precomputed multiples of `basepoint`. + pub fn create(basepoint: &ExtendedPoint) -> Box { + // Create the table storage + // XXX this is a dirty hack, does placement new work here? + let mut table: Box<[[AffineNielsPoint; 8]; 32]> = unsafe { + Box::from_raw( + Box::into_raw( // 8 * 32 = 256 + vec![AffineNielsPoint::identity(); 256].into_boxed_slice() + ) as *mut [[AffineNielsPoint; 8]; 32] + ) + }; + let mut P = basepoint.clone(); + for i in 0..32 { + // P = (16^2)^i * B + let mut jP = P.to_affine_niels(); + for j in 1..9 { + // table[i][j-1] is supposed to be j*(16^2)^i*B + table[i][j-1] = jP; + jP = (&P + &jP).to_extended().to_affine_niels(); + } + P = P.mult_by_pow_2(8); + } + // XXX can we do just 1 alloc instead of 2? + return Box::new(BasepointTable(*table)); + } + + /// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by + /// computing the multiple `aB` of the basepoint `B`. + /// + /// Precondition: the scalar must be reduced. + /// + /// The computation proceeds as follows, as described on page 13 + /// of the Ed25519 paper. Write the scalar `a` in radix 16 with + /// coefficients in [-8,8), i.e., + /// + /// a = a_0 + a_1*16^1 + ... + a_63*16^63, + /// + /// with -8 ≤ a_i < 8. Then + /// + /// a*B = a_0*B + a_1*16^1*B + ... + a_63*16^63*B. + /// + /// Grouping even and odd coefficients gives + /// + /// a*B = a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B + /// + a_1*16^1*B + a_3*16^3*B + ... + a_63*16^63*B + /// = (a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B) + /// + 16*(a_1*16^0*B + a_3*16^2*B + ... + a_63*16^62*B). + /// + /// We then use the `select_precomputed_point` function, which + /// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`, + /// and returns `x * 16^2i * B` in constant time. + fn basepoint_mult(&self, scalar: &Scalar) -> ExtendedPoint { //GeScalarMultBase + let e = scalar.to_radix_16(); + let mut h = ExtendedPoint::identity(); + let mut t: CompletedPoint; + + for i in (0..64).filter(|x| x % 2 == 1) { + t = &h + &select_precomputed_point(e[i], &self.0[i/2]); + h = t.to_extended(); + } + + h = h.mult_by_pow_2(4); + + for i in (0..64).filter(|x| x % 2 == 0) { + t = &h + &select_precomputed_point(e[i], &self.0[i/2]); + h = t.to_extended(); + } + + h + } +} + /// Trait for scalar multiplication of a distinguished basepoint. pub trait BasepointMult { /// Return the basepoint `B`. @@ -1277,6 +1357,15 @@ mod test { assert!(should_be_id.is_identity()); } + /// Test precomputed basepoint mult + #[test] + fn test_precomputed_basepoint_mult() { + let table = BasepointTable::create(&constants::BASEPOINT); + let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR); + let aB_2 = table.basepoint_mult(&A_SCALAR); + assert_eq!(aB_1.compress(), aB_2.compress()); + } + /// Test scalar_mult versus a known scalar multiple from ed25519.py #[test] fn scalar_mult_vs_ed25519py() { From 640f40287fe94a2d000537d93479796d7b8a3ece Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 6 Mar 2017 21:48:31 -0800 Subject: [PATCH 045/101] Wrap the existing basepoint table as a BasepointTable --- src/constants.rs | 26 ++--------- src/curve.rs | 111 +++++++++++++++-------------------------------- 2 files changed, 40 insertions(+), 97 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 112d060..6072293 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -23,6 +23,7 @@ use field::FieldElement; use curve::ExtendedPoint; use curve::AffineNielsPoint; use curve::CompressedEdwardsY; +use curve::BasepointTable; use scalar::Scalar; pub const d: FieldElement = FieldElement([ @@ -100,7 +101,7 @@ pub const BASE_CMPRSSD: CompressedEdwardsY = 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); /// Basepoint has y = 4/5. -pub const BASEPOINT: ExtendedPoint = ExtendedPoint{ +pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{ X: FieldElement([-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491]), Y: FieldElement([-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886]), Z: FieldElement([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), @@ -225,7 +226,7 @@ pub const bi: [AffineNielsPoint; 8] = [ /// /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`, /// for `0 ≤ i < 32`, `1 ≤ j < 9`. -pub const base: [[AffineNielsPoint; 8]; 32] = [ +pub const ED25519_BASEPOINT_TABLE: BasepointTable = BasepointTable([ [ AffineNielsPoint{ y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), @@ -1569,7 +1570,7 @@ pub const base: [[AffineNielsPoint; 8]; 32] = [ y_minus_x: FieldElement([29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684]), xy2d: FieldElement([-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476]), }, -]]; +]]); #[cfg(test)] mod test { @@ -1670,23 +1671,4 @@ mod test { let a_minus_d = &a - &constants::d; assert_eq!(a_minus_d, constants::a_minus_d); } - - /// Test the values in the lookup table of precomputed multiples - /// of the basepoint. - #[test] - fn test_precomputed_basepoint_multiples() { - let bp = constants::BASE_CMPRSSD.decompress().unwrap(); - let mut P = bp; - for i in 0..32 { - // P = (16^2)^i * B - let mut jP = P.to_affine_niels(); - for j in 1..9 { - // constants::base[i][j-1] is supposed to be - // j * (16^2)^i * B - assert_eq!(constants::base[i][j-1], jP); - jP = (&P + &jP).to_extended().to_affine_niels(); - } - P = P.mult_by_pow_2(8); - } - } } diff --git a/src/curve.rs b/src/curve.rs index 11a37a8..804d180 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -912,52 +912,11 @@ pub trait BasepointMult { impl BasepointMult for ExtendedPoint { fn basepoint() -> ExtendedPoint { - constants::BASEPOINT + constants::ED25519_BASEPOINT } - /// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by - /// computing the multiple `aB` of the basepoint `B`. - /// - /// Precondition: the scalar must be reduced. - /// - /// The computation proceeds as follows, as described on page 13 - /// of the Ed25519 paper. Write the scalar `a` in radix 16 with - /// coefficients in [-8,8), i.e., - /// - /// a = a_0 + a_1*16^1 + ... + a_63*16^63, - /// - /// with -8 ≤ a_i < 8. Then - /// - /// a*B = a_0*B + a_1*16^1*B + ... + a_63*16^63*B. - /// - /// Grouping even and odd coefficients gives - /// - /// a*B = a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B - /// + a_1*16^1*B + a_3*16^3*B + ... + a_63*16^63*B - /// = (a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B) - /// + 16*(a_1*16^0*B + a_3*16^2*B + ... + a_63*16^62*B). - /// - /// We then use the `select_precomputed_point` function, which - /// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`, - /// and returns `x * 16^2i * B` in constant time. - fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint { //GeScalarMultBase - let e = scalar.to_radix_16(); - let mut h = ExtendedPoint::identity(); - let mut t: CompletedPoint; - - for i in (0..64).filter(|x| x % 2 == 1) { - t = &h + &select_precomputed_point(e[i], &constants::base[i/2]); - h = t.to_extended(); - } - - h = h.mult_by_pow_2(4); - - for i in (0..64).filter(|x| x % 2 == 0) { - t = &h + &select_precomputed_point(e[i], &constants::base[i/2]); - h = t.to_extended(); - } - - h + fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint { + constants::ED25519_BASEPOINT_TABLE.basepoint_mult(scalar) } } @@ -1222,7 +1181,7 @@ mod test { /// Test Montgomery conversion against the X25519 basepoint. #[test] fn basepoint_to_montgomery() { - assert_eq!(constants::BASEPOINT.compress_montgomery().unwrap(), + assert_eq!(constants::ED25519_BASEPOINT.compress_montgomery().unwrap(), BASE_CMPRSSD_MONTY); } @@ -1275,10 +1234,10 @@ mod test { .decompress().unwrap(); // Test projective coordinates exactly since we know they should // only differ by a flipped sign. - assert_eq!(minus_basepoint.X, -(&constants::BASEPOINT.X)); - assert_eq!(minus_basepoint.Y, constants::BASEPOINT.Y); - assert_eq!(minus_basepoint.Z, constants::BASEPOINT.Z); - assert_eq!(minus_basepoint.T, -(&constants::BASEPOINT.T)); + assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT.X)); + assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT.Y); + assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT.Z); + assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT.T)); } /// Test that computing 1*basepoint gives the correct basepoint. @@ -1293,7 +1252,7 @@ mod test { /// using basepoint + basepoint versus the 2*basepoint constant. #[test] fn basepoint_plus_basepoint_vs_basepoint2() { - let bp = constants::BASEPOINT; + let bp = constants::ED25519_BASEPOINT; let bp_added = &bp + &bp; assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD); } @@ -1302,7 +1261,7 @@ mod test { /// using the basepoint, basepoint2 constants #[test] fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() { - let bp = constants::BASEPOINT; + let bp = constants::ED25519_BASEPOINT; let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD); } @@ -1311,7 +1270,7 @@ mod test { /// using the basepoint, basepoint2 constants #[test] fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() { - let bp = constants::BASEPOINT; + let bp = constants::ED25519_BASEPOINT; let bp_affine_niels = bp.to_affine_niels(); let bp_added = (&bp + &bp_affine_niels).to_extended(); assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD); @@ -1360,16 +1319,17 @@ mod test { /// Test precomputed basepoint mult #[test] fn test_precomputed_basepoint_mult() { - let table = BasepointTable::create(&constants::BASEPOINT); + let table = BasepointTable::create(&constants::ED25519_BASEPOINT); let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR); let aB_2 = table.basepoint_mult(&A_SCALAR); - assert_eq!(aB_1.compress(), aB_2.compress()); + assert_eq!(aB_1.compress_edwards(), + aB_2.compress_edwards()); } /// Test scalar_mult versus a known scalar multiple from ed25519.py #[test] fn scalar_mult_vs_ed25519py() { - let aB = constants::BASEPOINT.scalar_mult(&A_SCALAR); + let aB = constants::ED25519_BASEPOINT.scalar_mult(&A_SCALAR); assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT); } @@ -1384,7 +1344,7 @@ mod test { /// Test basepoint.double() versus the 2*basepoint constant. #[test] fn basepoint_double_vs_basepoint2() { - assert_eq!(constants::BASEPOINT.double().compress_edwards(), + assert_eq!(constants::ED25519_BASEPOINT.double().compress_edwards(), BASE2_CMPRSSD); } @@ -1399,14 +1359,15 @@ mod test { /// Check that converting to projective and then back to extended round-trips. #[test] fn basepoint_projective_extended_round_trip() { - assert_eq!(constants::BASEPOINT.to_projective().to_extended().compress_edwards(), + assert_eq!(constants::ED25519_BASEPOINT + .to_projective().to_extended().compress_edwards(), constants::BASE_CMPRSSD); } /// Test computing 16*basepoint vs mult_by_pow_2(4) #[test] fn basepoint16_vs_mult_by_pow_2_4() { - let bp16 = constants::BASEPOINT.mult_by_pow_2(4); + let bp16 = constants::ED25519_BASEPOINT.mult_by_pow_2(4); assert_eq!(bp16.compress_edwards(), BASE16_CMPRSSD); } @@ -1415,7 +1376,7 @@ mod test { fn conditional_assign_for_affine_niels_point() { let id = AffineNielsPoint::identity(); let mut p1 = AffineNielsPoint::identity(); - let bp = constants::BASEPOINT.to_affine_niels(); + let bp = constants::ED25519_BASEPOINT.to_affine_niels(); p1.conditional_assign(&bp, 0); assert_eq!(p1, id); @@ -1426,7 +1387,7 @@ mod test { #[test] fn is_small_order() { // The basepoint has large prime order - assert!(constants::BASEPOINT.is_small_order() == false); + assert!(constants::ED25519_BASEPOINT.is_small_order() == false); // constants::EIGHT_TORSION has all points of small order. for torsion_point in &constants::EIGHT_TORSION { assert!(torsion_point.is_small_order() == true); @@ -1441,8 +1402,8 @@ mod test { #[test] fn is_identity() { - assert!(ExtendedPoint::identity().is_identity() == true); - assert!( constants::BASEPOINT.is_identity() == false); + assert!( ExtendedPoint::identity().is_identity() == true); + assert!(constants::ED25519_BASEPOINT.is_identity() == false); } } @@ -1464,13 +1425,13 @@ mod bench { #[bench] fn scalar_mult(b: &mut Bencher) { - let bp = constants::BASEPOINT; + let bp = constants::ED25519_BASEPOINT; b.iter(|| bp.scalar_mult(&A_SCALAR)); } #[bench] fn bench_select_precomputed_point(b: &mut Bencher) { - b.iter(|| select_precomputed_point(0, &constants::base[12])); + b.iter(|| select_precomputed_point(0, &constants::ED25519_BASEPOINT_TABLE.0[0])); } #[bench] @@ -1481,53 +1442,53 @@ mod bench { #[bench] fn add_extended_and_cached_output_completed(b: &mut Bencher) { - let p1 = constants::BASEPOINT; - let p2 = constants::BASEPOINT.to_projective_niels(); + let p1 = constants::ED25519_BASEPOINT; + let p2 = constants::ED25519_BASEPOINT.to_projective_niels(); b.iter(|| &p1 + &p2); } #[bench] fn add_extended_and_cached_output_extended(b: &mut Bencher) { - let p1 = constants::BASEPOINT; - let p2 = constants::BASEPOINT.to_projective_niels(); + let p1 = constants::ED25519_BASEPOINT; + let p2 = constants::ED25519_BASEPOINT.to_projective_niels(); b.iter(|| (&p1 + &p2).to_extended()); } #[bench] fn add_extended_and_precomputed_output_completed(b: &mut Bencher) { - let p1 = constants::BASEPOINT; - let p2 = select_precomputed_point(6, &constants::base[27]); + let p1 = constants::ED25519_BASEPOINT; + let p2 = constants::ED25519_BASEPOINT.to_affine_niels(); b.iter(|| &p1 + &p2); } #[bench] fn add_extended_and_precomputed_output_extended(b: &mut Bencher) { - let p1 = constants::BASEPOINT; - let p2 = select_precomputed_point(6, &constants::base[27]); + let p1 = constants::ED25519_BASEPOINT; + let p2 = constants::ED25519_BASEPOINT.to_affine_niels(); b.iter(|| (&p1 + &p2).to_extended()); } #[bench] fn projective_double_output_completed(b: &mut Bencher) { - let p1 = constants::BASEPOINT.to_projective(); + let p1 = constants::ED25519_BASEPOINT.to_projective(); b.iter(|| p1.double() ); } #[bench] fn extended_double_output_extended(b: &mut Bencher) { - let p1 = constants::BASEPOINT; + let p1 = constants::ED25519_BASEPOINT; b.iter(|| p1.double() ); } #[bench] fn mult_by_cofactor(b: &mut Bencher) { - let p1 = constants::BASEPOINT; + let p1 = constants::ED25519_BASEPOINT; b.iter(|| p1.mult_by_cofactor() ); } From a4ed8e2b81aabe7954aa76ed4217fa75f102945a Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 6 Mar 2017 22:08:32 -0800 Subject: [PATCH 046/101] Use box syntax instead of an unsafe block --- src/curve.rs | 8 +------- src/lib.rs | 1 + 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 804d180..96e0b16 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -834,13 +834,7 @@ impl BasepointTable { pub fn create(basepoint: &ExtendedPoint) -> Box { // Create the table storage // XXX this is a dirty hack, does placement new work here? - let mut table: Box<[[AffineNielsPoint; 8]; 32]> = unsafe { - Box::from_raw( - Box::into_raw( // 8 * 32 = 256 - vec![AffineNielsPoint::identity(); 256].into_boxed_slice() - ) as *mut [[AffineNielsPoint; 8]; 32] - ) - }; + let mut table = box [[AffineNielsPoint::identity(); 8]; 32]; let mut P = basepoint.clone(); for i in 0..32 { // P = (16^2)^i * B diff --git a/src/lib.rs b/src/lib.rs index 947a531..bcacba1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ #![cfg_attr(not(feature = "std"), feature(collections))] #![allow(unused_features)] #![feature(test)] +#![feature(box_syntax)] #![deny(missing_docs)] // refuse to compile if documentation is missing //! # curve25519-dalek From e757959bb89501b17ca656a3657068b4844fad15 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 6 Mar 2017 22:22:11 -0800 Subject: [PATCH 047/101] Add benchmark for basepoint table creation --- src/curve.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index 96e0b16..817a43e 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1486,4 +1486,10 @@ mod bench { b.iter(|| p1.mult_by_cofactor() ); } + + #[bench] + fn create_basepoint_table(b: &mut Bencher) { + let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); + b.iter(|| BasepointTable::create(&aB)); + } } From f312160d2cf81acbfff89e69445e399a26df7970 Mon Sep 17 00:00:00 2001 From: Henry & Isis Date: Fri, 10 Mar 2017 22:16:11 -0800 Subject: [PATCH 048/101] Fixup errors introduced from not running yolocrypto tests by default --- src/decaf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decaf.rs b/src/decaf.rs index db12cde..99fe115 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -253,7 +253,7 @@ impl BasepointMult for DecafPoint { // XXX is this actually in the image of the isogeny, // or do we need a different basepoint? fn basepoint() -> DecafPoint { - DecafPoint(constants::BASEPOINT) + DecafPoint(ExtendedPoint::basepoint()) } fn basepoint_mult(scalar: &Scalar) -> DecafPoint { @@ -322,7 +322,7 @@ mod test { // Check that bp_recaf differs from bp by a point of order 4 let diff = &ExtendedPoint::basepoint() - &bp_recaf; let diff4 = diff.mult_by_pow_2(4); - assert_eq!(diff4.compress_edwards(), ExtendedPoint::identity().compress_edwards()); + assert_eq!(diff4.compress_edwards(), CompressedEdwardsY::identity()); } #[test] From c873f725a5601e425042d9c6ddd2f9a42caae965 Mon Sep 17 00:00:00 2001 From: Henry & Isis Date: Fri, 10 Mar 2017 22:21:17 -0800 Subject: [PATCH 049/101] Rename `BasepointTable` as `EdwardsBasepointTable`. --- src/constants.rs | 4 ++-- src/curve.rs | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 6072293..bfc103d 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -23,7 +23,7 @@ use field::FieldElement; use curve::ExtendedPoint; use curve::AffineNielsPoint; use curve::CompressedEdwardsY; -use curve::BasepointTable; +use curve::EdwardsBasepointTable; use scalar::Scalar; pub const d: FieldElement = FieldElement([ @@ -226,7 +226,7 @@ pub const bi: [AffineNielsPoint; 8] = [ /// /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`, /// for `0 ≤ i < 32`, `1 ≤ j < 9`. -pub const ED25519_BASEPOINT_TABLE: BasepointTable = BasepointTable([ +pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable([ [ AffineNielsPoint{ y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), diff --git a/src/curve.rs b/src/curve.rs index 817a43e..b736f65 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -827,27 +827,27 @@ impl ScalarMult for ExtendedPoint { /// Precomputation #[derive(Clone)] -pub struct BasepointTable(pub [[AffineNielsPoint; 8]; 32]); +pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]); -impl BasepointTable { +impl EdwardsBasepointTable { /// Create a table of precomputed multiples of `basepoint`. - pub fn create(basepoint: &ExtendedPoint) -> Box { + pub fn create(basepoint: &ExtendedPoint) -> Box { // Create the table storage - // XXX this is a dirty hack, does placement new work here? - let mut table = box [[AffineNielsPoint::identity(); 8]; 32]; + // XXX can we be assured that this is not allocated on the stack? + // XXX can we skip the initialization without too much unsafety? + let mut table = box EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]); let mut P = basepoint.clone(); for i in 0..32 { // P = (16^2)^i * B let mut jP = P.to_affine_niels(); for j in 1..9 { // table[i][j-1] is supposed to be j*(16^2)^i*B - table[i][j-1] = jP; + table.0[i][j-1] = jP; jP = (&P + &jP).to_extended().to_affine_niels(); } P = P.mult_by_pow_2(8); } - // XXX can we do just 1 alloc instead of 2? - return Box::new(BasepointTable(*table)); + return table } /// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by @@ -1313,7 +1313,7 @@ mod test { /// Test precomputed basepoint mult #[test] fn test_precomputed_basepoint_mult() { - let table = BasepointTable::create(&constants::ED25519_BASEPOINT); + let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT); let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR); let aB_2 = table.basepoint_mult(&A_SCALAR); assert_eq!(aB_1.compress_edwards(), @@ -1490,6 +1490,6 @@ mod bench { #[bench] fn create_basepoint_table(b: &mut Bencher) { let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); - b.iter(|| BasepointTable::create(&aB)); + b.iter(|| EdwardsBasepointTable::create(&aB)); } } From 049556147fcc83de20ed0a071d9f90022dc7246c Mon Sep 17 00:00:00 2001 From: Henry & Isis Date: Fri, 10 Mar 2017 22:43:07 -0800 Subject: [PATCH 050/101] Add wrapper for basepoint precomputations for decaf --- src/curve.rs | 2 +- src/decaf.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index b736f65..f90e69b 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -875,7 +875,7 @@ impl EdwardsBasepointTable { /// We then use the `select_precomputed_point` function, which /// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`, /// and returns `x * 16^2i * B` in constant time. - fn basepoint_mult(&self, scalar: &Scalar) -> ExtendedPoint { //GeScalarMultBase + pub fn basepoint_mult(&self, scalar: &Scalar) -> ExtendedPoint { let e = scalar.to_radix_16(); let mut h = ExtendedPoint::identity(); let mut t: CompletedPoint; diff --git a/src/decaf.rs b/src/decaf.rs index 99fe115..71a8d1c 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -31,7 +31,11 @@ use subtle::CTNegatable; use core::ops::{Add, Sub, Neg}; +#[cfg(feature = "std")] +use std::boxed::Box; + use curve::ExtendedPoint; +use curve::EdwardsBasepointTable; use curve::BasepointMult; use curve::ScalarMult; use curve::Identity; @@ -261,6 +265,24 @@ impl BasepointMult for DecafPoint { } } + +/// Precomputation +#[derive(Clone)] +pub struct DecafBasepointTable(EdwardsBasepointTable); + +impl DecafBasepointTable { + /// Create a precomputed table of multiples of the given `basepoint`. + pub fn create(basepoint: &DecafPoint) -> Box { + let edwards_table = EdwardsBasepointTable::create(&basepoint.0); + box DecafBasepointTable(*edwards_table) + } + + /// Use the precomputed table to quickly compute `scalar * basepoint` + pub fn basepoint_mult(&self, scalar: &Scalar) -> DecafPoint { + DecafPoint(self.0.basepoint_mult(scalar)) + } +} + // ------------------------------------------------------------------------ // Debug traits // ------------------------------------------------------------------------ @@ -356,6 +378,18 @@ mod test { assert_eq!(P, Q); } } + + /// Test basepoint_mult versus a newly-generated DecafBasepointTable + #[test] + fn basepoint_mult_vs_decafbasepointtable() { + let table = DecafBasepointTable::create(&DecafPoint::basepoint()); + let mut rng = OsRng::new().unwrap(); + let s = Scalar::random(&mut rng); + let basepoint_mult_s = DecafPoint::basepoint_mult(&s); + let table_basepoint_mult_s = table.basepoint_mult(&s); + + assert_eq!(basepoint_mult_s, table_basepoint_mult_s); + } } #[cfg(test)] From 2610ab872a6a0b4174455b52de461655df59e5fe Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 16:28:43 -0700 Subject: [PATCH 051/101] Feature-gate basepoint table creation on a `nightly` feature --- Cargo.toml | 3 +++ src/curve.rs | 8 +++++--- src/lib.rs | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 691f464..f0189e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,9 +33,12 @@ version = "^0.6" version = "0.4" [features] +nightly = ["basepoint_table_creation"] default = ["std"] std = ["rand"] yolocrypto = [] +# Needs nightly for placement new +basepoint_table_creation = [] # The development profile, used for `cargo build`. [profile.dev] diff --git a/src/curve.rs b/src/curve.rs index f90e69b..054b164 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -81,9 +81,6 @@ use core::fmt::Debug; use core::iter::Iterator; use core::ops::{Add, Sub, Neg}; -#[cfg(feature = "std")] -use std::boxed::Box; - use constants; use field::FieldElement; use scalar::Scalar; @@ -95,6 +92,8 @@ use subtle::CTNegatable; #[cfg(not(feature = "std"))] use collections::boxed::Box; +#[cfg(feature = "std")] +use std::boxed::Box; // ------------------------------------------------------------------------ // Compressed points @@ -831,6 +830,7 @@ pub struct EdwardsBasepointTable(pub [[AffineNielsPoint; 8]; 32]); impl EdwardsBasepointTable { /// Create a table of precomputed multiples of `basepoint`. + #[cfg(feature="basepoint_table_creation")] pub fn create(basepoint: &ExtendedPoint) -> Box { // Create the table storage // XXX can we be assured that this is not allocated on the stack? @@ -1312,6 +1312,7 @@ mod test { /// Test precomputed basepoint mult #[test] + #[cfg(feature="basepoint_table_creation")] fn test_precomputed_basepoint_mult() { let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT); let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR); @@ -1487,6 +1488,7 @@ mod bench { b.iter(|| p1.mult_by_cofactor() ); } + #[cfg(feature="basepoint_table_creation")] #[bench] fn create_basepoint_table(b: &mut Bencher) { let aB = ExtendedPoint::basepoint_mult(&A_SCALAR); diff --git a/src/lib.rs b/src/lib.rs index bcacba1..b268354 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,9 +11,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(collections))] +#![cfg_attr(feature = "nightly", feature(box_syntax))] #![allow(unused_features)] #![feature(test)] -#![feature(box_syntax)] #![deny(missing_docs)] // refuse to compile if documentation is missing //! # curve25519-dalek From 10fa9898835870b3c6364837d6ce66ee493c1bae Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Mon, 13 Mar 2017 23:29:13 +0000 Subject: [PATCH 052/101] Print "CompressedEdwardsY" in Debug impl, not "CompressedPoint". --- src/curve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index 9357f5a..25b2b70 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -105,7 +105,7 @@ pub struct CompressedEdwardsY(pub [u8; 32]); impl Debug for CompressedEdwardsY { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedPoint: {:?}", self.as_bytes()) + write!(f, "CompressedEdwardsY: {:?}", self.as_bytes()) } } From 97b60d61ab64cf6cc84f1e1ff80a5cee6e26eddf Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:16:55 -0700 Subject: [PATCH 053/101] draft of 64-bit multiplication --- src/field.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 50 insertions(+) diff --git a/src/field.rs b/src/field.rs index 3094b0f..1ea123e 100644 --- a/src/field.rs +++ b/src/field.rs @@ -33,6 +33,48 @@ use utils::{load3, load4}; use constants; +/// doc +pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { + #[inline(always)] + fn m(a: u64, b: u64) -> u128 { (a as u128) * (b as u128) } + // Multiply to get 128-bit coefficients of output + let mut c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; + let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + ( m(a[4],b[2]) + m(a[3],b[3]) + m(a[2],b[4]) )*19; + let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + ( m(a[4],b[3]) + m(a[3],b[4]) )*19; + let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + ( m(a[4],b[4]) )*19; + let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); + // Now c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) + // where b is the bitlength of the input limbs. + + // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. + // After the first carry pass, all c[i] fit into u64. + + let low_51_bit_mask = (1u64 << 51) - 1; + c1 += (c0 >> 51) as u128; + let mut c0: u64 = (c0 as u64) & low_51_bit_mask; + c2 += (c1 >> 51) as u128; + let mut c1: u64 = (c1 as u64) & low_51_bit_mask; + c3 += (c2 >> 51) as u128; + let mut c2: u64 = (c2 as u64) & low_51_bit_mask; + c4 += (c3 >> 51) as u128; + let mut c3: u64 = (c3 as u64) & low_51_bit_mask; + c0 += ((c4 >> 51) as u64) * 19; + let mut c4: u64 = (c4 as u64) & low_51_bit_mask; + + c1 += c0 >> 51; + c0 = c0 & low_51_bit_mask; + c2 += c1 >> 51; + c1 = c1 & low_51_bit_mask; + c3 += c2 >> 51; + c2 = c2 & low_51_bit_mask; + c4 += c3 >> 51; + c3 = c3 & low_51_bit_mask; + c0 += (c4 >> 51) * 19; + c4 = c4 & low_51_bit_mask; + + [c0,c1,c2,c3,c4] +} + /// FieldElements are represented as an array of ten "Limbs", which are radix /// 25.5, that is, each Limb of a FieldElement alternates between being /// represented as a factor of 2^25 or 2^26 more than the last corresponding @@ -924,6 +966,13 @@ mod test { use test::Bencher; use subtle::CTNegatable; + #[bench] + fn bench_mul64(b: &mut Bencher) { + let x = [1u64; 5]; + let y = [1u64; 5]; + b.iter(|| mul64(&x,&y)); + } + #[bench] fn bench_fieldelement_a_mul_a(b: &mut Bencher) { let a = FieldElement::from_bytes(&A_BYTES); diff --git a/src/lib.rs b/src/lib.rs index b268354..af82b41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![cfg_attr(feature = "nightly", feature(box_syntax))] #![allow(unused_features)] #![feature(test)] +#![feature(i128_type)] #![deny(missing_docs)] // refuse to compile if documentation is missing //! # curve25519-dalek From 92bf47f990341c6c0c20f7bf73f70b29f922748f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:34 -0700 Subject: [PATCH 054/101] Clean up field tests --- src/field.rs | 86 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/src/field.rs b/src/field.rs index 1ea123e..92d7d31 100644 --- a/src/field.rs +++ b/src/field.rs @@ -961,40 +961,46 @@ impl FieldElement { } #[cfg(test)] -mod test { - use field::*; +mod bench { + use super::*; + use field; use test::Bencher; - use subtle::CTNegatable; #[bench] fn bench_mul64(b: &mut Bencher) { let x = [1u64; 5]; let y = [1u64; 5]; - b.iter(|| mul64(&x,&y)); + b.iter(|| mul64(&x, &y)); } #[bench] - fn bench_fieldelement_a_mul_a(b: &mut Bencher) { - let a = FieldElement::from_bytes(&A_BYTES); + fn mul_operator(b: &mut Bencher) { + let a = FieldElement::from_bytes(&field::test::A_BYTES); b.iter(|| &a*&a); } #[bench] - fn bench_fieldelement_a_sq(b: &mut Bencher) { - let a = FieldElement::from_bytes(&A_BYTES); + fn square(b: &mut Bencher) { + let a = FieldElement::from_bytes(&field::test::A_BYTES); b.iter(|| a.square()); } #[bench] - fn bench_fieldelement_a_inv(b: &mut Bencher) { - let a = FieldElement::from_bytes(&A_BYTES); + fn invert(b: &mut Bencher) { + let a = FieldElement::from_bytes(&field::test::A_BYTES); b.iter(|| a.invert()); } +} + +#[cfg(test)] +mod test { + use field::*; + use subtle::CTNegatable; /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\ /// 2228051251926706380353716438957572 - static A_BYTES: [u8;32] = + pub static A_BYTES: [u8;32] = [ 0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68, 0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7, 0x03, 0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4, @@ -1022,43 +1028,55 @@ mod test { 0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61, 0x21, 0x55]; #[test] - fn test_fieldelement_a_mul_a() { + fn a_mul_a_vs_a_squared_constant() { let a = FieldElement::from_bytes(&A_BYTES); let asq = FieldElement::from_bytes(&ASQ_BYTES); assert_eq!(asq, &a*&a); + } + + #[test] + fn a_square_vs_a_squared_constant() { + let a = FieldElement::from_bytes(&A_BYTES); + let asq = FieldElement::from_bytes(&ASQ_BYTES); assert_eq!(asq, a.square()); } #[test] - fn test_fieldelement_a_square2() { + fn a_square2_vs_a_squared_constant() { let a = FieldElement::from_bytes(&A_BYTES); let asq = FieldElement::from_bytes(&ASQ_BYTES); assert_eq!(a.square2(), &asq+&asq); } #[test] - fn test_fieldelement_a_inv() { + fn a_invert_vs_inverse_of_a_constant() { let a = FieldElement::from_bytes(&A_BYTES); let ainv = FieldElement::from_bytes(&AINV_BYTES); - assert_eq!(ainv, a.invert()); + let should_be_inverse = a.invert(); + assert_eq!(ainv, should_be_inverse); + assert_eq!(FieldElement::one(), &a * &should_be_inverse); } #[test] - fn test_fieldelement_a_p58() { + fn a_p58_vs_ap58_constant() { let a = FieldElement::from_bytes(&A_BYTES); let ap58 = FieldElement::from_bytes(&AP58_BYTES); assert_eq!(ap58, a.pow_p58()); } #[test] - fn test_fieldelement_a_chi() { + fn chi_on_square_and_nonsquare() { let a = FieldElement::from_bytes(&A_BYTES); // a is square assert_eq!(a.chi(), FieldElement::one()); + let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; + let two = FieldElement::from_bytes(&two_bytes); + // 2 is nonsquare + assert_eq!(two.chi(), FieldElement::minus_one()); } #[test] - fn test_fieldelement_eq() { + fn equality() { let a = FieldElement::from_bytes(&A_BYTES); let ainv = FieldElement::from_bytes(&AINV_BYTES); assert!(a == a); @@ -1068,42 +1086,44 @@ mod test { /// Notice that the last element has the high bit set, which /// should be ignored static B_BYTES: [u8;32] = - [113, 191, 169, 143, 91, 234, 121, 15, 241, 131, 217, 36, 230, 101, 92, 234, 8, 208, 170, 251, 97, 127, 70, 210, 58, 23, 166, 87, 240, 169, 184, 178]; + [113, 191, 169, 143, 91, 234, 121, 15, + 241, 131, 217, 36, 230, 101, 92, 234, + 8, 208, 170, 251, 97, 127, 70, 210, + 58, 23, 166, 87, 240, 169, 184, 178]; - static B_LIMBS: FieldElement = FieldElement( - [-5652623, 8034020, 8266223, -13556020, -5672552, -5582839, -12603138, 15161929, -16418207, 13296296]); + static B_LIMBS_RADIX_25_5: FieldElement = FieldElement( + [-5652623, 8034020, 8266223, -13556020, -5672552, + -5582839, -12603138, 15161929, -16418207, 13296296]); #[test] - fn test_fieldelement_frombytes_highbit_is_ignored() { + fn from_bytes_highbit_is_ignored() { let mut cleared_bytes = B_BYTES.clone(); cleared_bytes[31] &= 127u8; - let orig_elt = FieldElement::from_bytes(&B_BYTES); - let cleared_elt = FieldElement::from_bytes(&cleared_bytes); - for i in 0..10 { - assert!(orig_elt[i] == cleared_elt[i]); - } + let with_highbit_set = FieldElement::from_bytes(&B_BYTES); + let without_highbit_set = FieldElement::from_bytes(&cleared_bytes); + assert_eq!(without_highbit_set, with_highbit_set); } #[test] - fn test_fieldelement_to_bytes() { + fn from_bytes_vs_radix_25_5_limb_constants() { let test_elt = FieldElement::from_bytes(&B_BYTES); for i in 0..10 { - assert!(test_elt[i] == B_LIMBS[i]); + assert!(test_elt[i] == B_LIMBS_RADIX_25_5[i]); } } #[test] - fn test_fieldelement_from_bytes() { - let test_bytes = B_LIMBS.to_bytes(); + fn radix_25_5_limb_constants_to_bytes_vs_byte_constants() { + let test_bytes = B_LIMBS_RADIX_25_5.to_bytes(); for i in 0..31 { assert!(test_bytes[i] == B_BYTES[i]); } - // high bit is set to zero in to_bytes + // Check that high bit is set to zero in to_bytes assert!(test_bytes[31] == (B_BYTES[31] & 127u8)); } #[test] - fn test_conditional_negate() { + fn conditional_negate() { let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); let mut x = one; From 3a55a2f4101345bb250c7aad3f97506297e49336 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:38 -0700 Subject: [PATCH 055/101] Add a test for radix-51 multiplication --- src/field.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/field.rs b/src/field.rs index 92d7d31..fd5ba22 100644 --- a/src/field.rs +++ b/src/field.rs @@ -1034,6 +1034,14 @@ mod test { assert_eq!(asq, &a*&a); } + #[test] + fn mul64_on_a() { + let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; + let asq_constant_from_sage: [u64; 5] = [1696437425706869, 260630435370367, 277335390860868, 1743763050813710, 1739636627710249]; + let asq = mul64(&a, &a.clone()); + assert_eq!(asq, asq_constant_from_sage); + } + #[test] fn a_square_vs_a_squared_constant() { let a = FieldElement::from_bytes(&A_BYTES); From a884260341637f3263958cf183e5abcd10fdde12 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:40 -0700 Subject: [PATCH 056/101] Add radix_51 and radix_25_5 features and start feature-gating --- Cargo.toml | 6 +++++- src/field.rs | 43 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f0189e5..48160a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,11 +34,15 @@ version = "0.4" [features] nightly = ["basepoint_table_creation"] -default = ["std"] +default = ["std", "radix_25_5"] std = ["rand"] yolocrypto = [] # Needs nightly for placement new basepoint_table_creation = [] +# Radix-51 arithmetic using u128 +radix_51 = [] +# Radix-25.5 arithmetic using i64 +radix_25_5 = [] # The development profile, used for `cargo build`. [profile.dev] diff --git a/src/field.rs b/src/field.rs index fd5ba22..e9baaaa 100644 --- a/src/field.rs +++ b/src/field.rs @@ -75,18 +75,33 @@ pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { [c0,c1,c2,c3,c4] } +/// With the `radix51` feature enabled, `FieldElements` are represented +/// in radix 2^51 as five `u64`s. +#[cfg(feature="radix_51")] +pub type Limb = u64; + +/// FieldElement represents an element of the field GF(2^255 - 19). An element +/// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 +/// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on +/// context. +#[cfg(feature="radix_51")] +#[derive(Copy, Clone)] +pub struct FieldElement(pub [u64; 5]); + /// FieldElements are represented as an array of ten "Limbs", which are radix /// 25.5, that is, each Limb of a FieldElement alternates between being /// represented as a factor of 2^25 or 2^26 more than the last corresponding /// integer. +#[cfg(feature="radix_25_5")] pub type Limb = i32; /// FieldElement represents an element of the field GF(2^255 - 19). An element /// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 /// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on /// context. +#[cfg(feature="radix_25_5")] #[derive(Copy, Clone)] -pub struct FieldElement(pub [Limb; 10]); +pub struct FieldElement(pub [i32; 10]); impl Eq for FieldElement {} impl PartialEq for FieldElement { @@ -147,7 +162,7 @@ impl IndexMut for FieldElement { impl<'b> AddAssign<&'b FieldElement> for FieldElement { fn add_assign(&mut self, _rhs: &'b FieldElement) { // fsum() - for i in 0..10 { + for i in 0..self.0.len() { self[i] += _rhs[i]; } } @@ -163,11 +178,13 @@ impl<'a, 'b> Add<&'b FieldElement> for &'a FieldElement { } impl<'b> SubAssign<&'b FieldElement> for FieldElement { + #[cfg(feature="radix_25_5")] fn sub_assign(&mut self, _rhs: &'b FieldElement) { // fdifference() for i in 0..10 { self[i] -= _rhs[i]; } } + // XXX_radix_51 } impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement { @@ -204,6 +221,9 @@ impl<'a> Neg for &'a FieldElement { impl CTAssignable for FieldElement { /// Conditionally assign another FieldElement to this one. /// + /// XXX fixup tests to avoid limb specs + /// XXX_radix_51 + /// /// If `choice == 0`, replace `self` with `self`: /// /// ``` @@ -241,6 +261,7 @@ impl CTAssignable for FieldElement { impl FieldElement { /// Invert the sign of this field element + #[cfg(feature="radix_25_5")] pub fn negate(&mut self) { for i in 0..10 { self[i] = -self[i]; @@ -248,20 +269,32 @@ impl FieldElement { } /// Construct the additive identity + #[cfg(feature="radix_25_5")] pub fn zero() -> FieldElement { FieldElement([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + #[cfg(feature="radix_51")] + pub fn zero() -> FieldElement { + FieldElement([ 0, 0, 0, 0, 0 ]) + } /// Construct the multiplicative identity + #[cfg(feature="radix_25_5")] pub fn one() -> FieldElement { FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + #[cfg(feature="radix_51")] + pub fn one() -> FieldElement { + FieldElement([ 1, 0, 0, 0, 0 ]) + } /// Construct -1. + #[cfg(feature="radix_25_5")] pub fn minus_one() -> FieldElement { FieldElement([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + #[cfg(feature="radix_25_5")] fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine let mut c = [0i64;10]; let mut h = input.clone(); @@ -357,6 +390,7 @@ impl FieldElement { /// Create a FieldElement by demarshalling an array of 32 bytes. /// /// # Example + /// XXX eliminate limbs /// /// ``` /// # use curve25519_dalek::field::FieldElement; @@ -373,6 +407,7 @@ impl FieldElement { /// # Return /// /// Returns a new FieldElement. + #[cfg(feature="radix_25_5")] pub fn from_bytes(data: &[u8; 32]) -> FieldElement { //FeFromBytes let mut h = [0i64;10]; h[0] = load4(&data[ 0..]); @@ -391,6 +426,8 @@ impl FieldElement { /// Marshal this FieldElement into a 32-byte array. /// + /// XXX eliminate limbs + /// /// # Preconditions /// /// * `|h[i]|` bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. @@ -437,6 +474,7 @@ impl FieldElement { /// let bytes: [u8; 32] = fe.to_bytes(); /// assert!(data == bytes); /// ``` + #[cfg(feature="radix_25_5")] pub fn to_bytes(&self) -> [u8;32] { //FeToBytes let mut carry = [0i32; 10]; let mut h = self.clone(); @@ -655,6 +693,7 @@ impl FieldElement { /// Can get away with 11 carries, but then data flow is much deeper. /// /// * With tighter constraints on inputs can squeeze carries into int32. + #[cfg(feature="radix_25_5")] pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement { let f0 = self[0] as i64; let f1 = self[1] as i64; From afd42a4628f61549f0794312aa32c4804bdd1be4 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:43 -0700 Subject: [PATCH 057/101] More feature-gating --- src/constants.rs | 16 ++++++++++++++++ src/field.rs | 24 +++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index bfc103d..04aa289 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -26,15 +26,19 @@ use curve::CompressedEdwardsY; use curve::EdwardsBasepointTable; use scalar::Scalar; +#[cfg(feature="radix_25_5")] pub const d: FieldElement = FieldElement([ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, ]); +#[cfg(feature="radix_25_5")] pub const d2: FieldElement = FieldElement([ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, ]); +#[cfg(feature="radix_25_5")] pub const d4: FieldElement = FieldElement([ 23454405, -11679213, 5618422, -5756869, 458917, -1596832, -25103633, -12990876, -7676928, -14666033 ]); +#[cfg(feature="radix_25_5")] pub const a_minus_d: FieldElement = FieldElement([ 10913609, -13857413, 15372611, -6949391, -114729, 8787816, 6275908, 3247719, 18696448, 12055116, ]); @@ -47,21 +51,25 @@ pub const HALF_P_MINUS_1_BYTES: [u8; 32] = 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f]; /// Precomputed value of one of the square roots of -1 (mod p) +#[cfg(feature="radix_25_5")] pub const SQRT_M1: FieldElement = FieldElement([ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, ]); /// Precomputed value of the other square root of -1 (mod p), /// i.e., MSQRT_M1 = -SQRT_M1. +#[cfg(feature="radix_25_5")] pub const MSQRT_M1: FieldElement = FieldElement([ 32595792, 7943725, -9377950, -3500415, -12389472, 272473, 25146209, 2005654, -326686, -11406482, ]); /// Precomputed value of 1/2 (mod p). +#[cfg(feature="radix_25_5")] pub const HALF: FieldElement = FieldElement([ 10, 0, 0, 0, 0, 0, 0, 0, 0, -16777216, ]); /// In Montgomery form y² = x³+Ax²+x, Curve25519 has A=486662. +#[cfg(feature="radix_25_5")] pub const A: FieldElement = FieldElement([ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]); @@ -69,21 +77,25 @@ pub const A: FieldElement = FieldElement([ // XXX I think that this was used in Adam's code for his elligator // implementation, but that should maybe be using sqrt(-486664) // instead...? - hdevalence +#[cfg(feature="radix_25_5")] pub const SQRT_MINUS_A: FieldElement = FieldElement([ // sqrtMinusA 12222970, 8312128, 11511410, -9067497, 15300785, 241793, -25456130, -14121551, 12187136, -3972024, ]); /// SQRT_MINUS_APLUS2 is sqrt(-486664) +#[cfg(feature="radix_25_5")] pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ -12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024]); /// SQRT_MINUS_HALF is sqrt(-1/2) +#[cfg(feature="radix_25_5")] pub const SQRT_MINUS_HALF: FieldElement = FieldElement([ // sqrtMinusHalf -17256545, 3971863, 28865457, -1750208, 27359696, -16640980, 12573105, 1002827, -163343, 11073975, ]); /// HALF_Q_MINUS_1_BYTES is (2^255-20)/2 expressed in little endian form. +#[cfg(feature="radix_25_5")] pub const HALF_Q_MINUS_1_BYTES: [u8; 32] = [ // halfQMinus1Bytes 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -101,6 +113,7 @@ pub const BASE_CMPRSSD: CompressedEdwardsY = 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); /// Basepoint has y = 4/5. +#[cfg(feature="radix_25_5")] pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{ X: FieldElement([-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491]), Y: FieldElement([-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886]), @@ -128,6 +141,7 @@ pub const lminus1: Scalar = Scalar([ 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0 /// /// Thus Ɛ[4] is the points indexed by 0,2,4,6 and Ɛ[2] is the points /// indexed by 0,4. +#[cfg(feature="radix_25_5")] pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ ExtendedPoint{ X: FieldElement([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), @@ -179,6 +193,7 @@ pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ }, ]; +#[cfg(feature="radix_25_5")] pub const bi: [AffineNielsPoint; 8] = [ AffineNielsPoint{ y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), @@ -226,6 +241,7 @@ pub const bi: [AffineNielsPoint; 8] = [ /// /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`, /// for `0 ≤ i < 32`, `1 ≤ j < 9`. +#[cfg(feature="radix_25_5")] pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable([ [ AffineNielsPoint{ diff --git a/src/field.rs b/src/field.rs index e9baaaa..f5511a1 100644 --- a/src/field.rs +++ b/src/field.rs @@ -747,6 +747,7 @@ impl FieldElement { FieldElement::combine_coeffs(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) } + #[cfg(feature="radix_25_5")] fn square_inner(&self) -> [i64;10] { let f0 = self[0] as i64; let f1 = self[1] as i64; @@ -789,6 +790,8 @@ impl FieldElement { /// Calculates h = f*f. Can overlap h with f. /// + /// XXX limbs: better to talk about headroom? + /// /// # Preconditions /// /// * |f[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc. @@ -796,12 +799,15 @@ impl FieldElement { /// # Postconditions /// /// * |h[i]| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. + #[cfg(feature="radix_25_5")] pub fn square(&self) -> FieldElement { FieldElement::combine_coeffs(&self.square_inner()) } /// Square this field element and multiply the result by 2. /// + /// XXX explain why square2 exists vs square (overflow) + /// /// # Preconditions /// /// * |f[i]| bounded by 1.65*2^26, 1.65*2^25, 1.65*2^26, 1.65*2^25, etc. @@ -814,9 +820,10 @@ impl FieldElement { /// /// See fe_mul.c in ref10 implementation for discussion of implementation /// strategy. + #[cfg(feature="radix_25_5")] pub fn square2(&self) -> FieldElement { let mut coeffs = self.square_inner(); - for i in 0..10 { + for i in 0..self.0.len() { coeffs[i] += coeffs[i]; } FieldElement::combine_coeffs(&coeffs) @@ -1138,10 +1145,6 @@ mod test { 8, 208, 170, 251, 97, 127, 70, 210, 58, 23, 166, 87, 240, 169, 184, 178]; - static B_LIMBS_RADIX_25_5: FieldElement = FieldElement( - [-5652623, 8034020, 8266223, -13556020, -5672552, - -5582839, -12603138, 15161929, -16418207, 13296296]); - #[test] fn from_bytes_highbit_is_ignored() { let mut cleared_bytes = B_BYTES.clone(); @@ -1151,6 +1154,12 @@ mod test { assert_eq!(without_highbit_set, with_highbit_set); } + #[cfg(feature="radix_25_5")] + static B_LIMBS_RADIX_25_5: FieldElement = FieldElement( + [-5652623, 8034020, 8266223, -13556020, -5672552, + -5582839, -12603138, 15161929, -16418207, 13296296]); + + #[cfg(feature="radix_25_5")] #[test] fn from_bytes_vs_radix_25_5_limb_constants() { let test_elt = FieldElement::from_bytes(&B_BYTES); @@ -1159,6 +1168,7 @@ mod test { } } + #[cfg(feature="radix_25_5")] #[test] fn radix_25_5_limb_constants_to_bytes_vs_byte_constants() { let test_bytes = B_LIMBS_RADIX_25_5.to_bytes(); @@ -1171,8 +1181,8 @@ mod test { #[test] fn conditional_negate() { - let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); - let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); + let one = FieldElement::one(); + let minus_one = FieldElement::minus_one(); let mut x = one; x.conditional_negate(1u8); assert_eq!(x, minus_one); From eb66088cb9c41e495d1a1a44a62416af048ce650 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:46 -0700 Subject: [PATCH 058/101] Add to/from bytes for radix 51 --- src/field.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/utils.rs | 14 +++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/field.rs b/src/field.rs index f5511a1..0e01e85 100644 --- a/src/field.rs +++ b/src/field.rs @@ -29,7 +29,7 @@ use subtle::byte_is_nonzero; use subtle::CTAssignable; use subtle::CTEq; -use utils::{load3, load4}; +use utils::{load3, load4, load8}; use constants; @@ -75,6 +75,62 @@ pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { [c0,c1,c2,c3,c4] } +fn from_bytes_64(bytes: &[u8;32]) -> [u64; 5] { + let low_51_bit_mask = (1u64 << 51) - 1; + // load bits [ 0, 64), no shift + [ load8(&bytes[ 0..]) & low_51_bit_mask + // load bits [ 48,112), shift to [ 51,112) + , (load8(&bytes[ 6..]) >> 3) & low_51_bit_mask + // load bits [ 96,160), shift to [102,160) + , (load8(&bytes[12..]) >> 6) & low_51_bit_mask + // load bits [152,216), shift to [153,216) + , (load8(&bytes[19..]) >> 1) & low_51_bit_mask + // load bits [192,256), shift to [204,112) + , (load8(&bytes[24..]) >> 12) & low_51_bit_mask + ] +} + +fn to_bytes_64(limbs: &[u64;5]) -> [u8;32] { + let mut s = [0u8;32]; + s[ 0] = limbs[0] as u8; + s[ 1] = (limbs[0] >> 8) as u8; + s[ 2] = (limbs[0] >> 16) as u8; + s[ 3] = (limbs[0] >> 24) as u8; + s[ 4] = (limbs[0] >> 32) as u8; + s[ 5] = (limbs[0] >> 40) as u8; + s[ 6] = ((limbs[0] >> 48) | (limbs[1] << 3)) as u8; + s[ 7] = (limbs[1] >> 5) as u8; + s[ 8] = (limbs[1] >> 13) as u8; + s[ 9] = (limbs[1] >> 21) as u8; + s[10] = (limbs[1] >> 29) as u8; + s[11] = (limbs[1] >> 37) as u8; + s[12] = ((limbs[1] >> 45) | (limbs[2] << 6)) as u8; + s[13] = (limbs[2] >> 2) as u8; + s[14] = (limbs[2] >> 10) as u8; + s[15] = (limbs[2] >> 18) as u8; + s[16] = (limbs[2] >> 26) as u8; + s[17] = (limbs[2] >> 34) as u8; + s[18] = (limbs[2] >> 42) as u8; + s[19] = ((limbs[2] >> 50) | (limbs[3] << 1)) as u8; + s[20] = (limbs[3] >> 7) as u8; + s[21] = (limbs[3] >> 15) as u8; + s[22] = (limbs[3] >> 23) as u8; + s[23] = (limbs[3] >> 31) as u8; + s[24] = (limbs[3] >> 39) as u8; + s[25] = ((limbs[3] >> 47) | (limbs[4] << 4)) as u8; + s[26] = (limbs[4] >> 4) as u8; + s[27] = (limbs[4] >> 12) as u8; + s[28] = (limbs[4] >> 20) as u8; + s[29] = (limbs[4] >> 28) as u8; + s[30] = (limbs[4] >> 36) as u8; + s[31] = (limbs[4] >> 44) as u8; + + //Clear high bit + s[31] &= 127u8; + + return s +} + /// With the `radix51` feature enabled, `FieldElements` are represented /// in radix 2^51 as five `u64`s. #[cfg(feature="radix_51")] @@ -1088,6 +1144,15 @@ mod test { assert_eq!(asq, asq_constant_from_sage); } + #[test] + fn from_bytes_64_on_a() { + let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; + let should_be_a = from_bytes_64(&A_BYTES); + assert_eq!(a, should_be_a); + let should_be_a_bytes = to_bytes_64(&a); + assert_eq!(&A_BYTES, &should_be_a_bytes); + } + #[test] fn a_square_vs_a_squared_constant() { let a = FieldElement::from_bytes(&A_BYTES); diff --git a/src/utils.rs b/src/utils.rs index c6bfae3..34b5e10 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -29,3 +29,17 @@ pub fn load4(input: &[u8]) -> i64 { | ((input[2] as i64) << 16) | ((input[3] as i64) << 24) } + +/// Convert an array of (at least) eight bytes into a u64. +#[inline] +//#[allow(dead_code)] +pub fn load8(input: &[u8]) -> u64 { + (input[0] as u64) + | ((input[1] as u64) << 8) + | ((input[2] as u64) << 16) + | ((input[3] as u64) << 24) + | ((input[4] as u64) << 32) + | ((input[5] as u64) << 40) + | ((input[6] as u64) << 48) + | ((input[7] as u64) << 56) +} From 4db735ca444a0295d1cb46ff20f1beea287b1a99 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:49 -0700 Subject: [PATCH 059/101] Add subtraction stub --- src/field.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/field.rs b/src/field.rs index 0e01e85..706f0af 100644 --- a/src/field.rs +++ b/src/field.rs @@ -75,6 +75,16 @@ pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { [c0,c1,c2,c3,c4] } +fn subtract(a: &[u64; 5], b: &[u64; 5]) -> [u64; 5] { + // add p to avoid underflow + [ (a[0] + 2251799813685229) - b[0] + , (a[1] + 2251799813685247) - b[1] + , (a[2] + 2251799813685247) - b[2] + , (a[3] + 2251799813685247) - b[3] + , (a[4] + 2251799813685247) - b[4] + ] +} + fn from_bytes_64(bytes: &[u8;32]) -> [u64; 5] { let low_51_bit_mask = (1u64 << 51) - 1; // load bits [ 0, 64), no shift From 87001f9d6e871c2a74a1dc0a8088262030b2d62f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:17:59 -0700 Subject: [PATCH 060/101] Add utility for extracting constants in the new repr --- src/field.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/field.rs b/src/field.rs index 706f0af..ce18f07 100644 --- a/src/field.rs +++ b/src/field.rs @@ -1109,6 +1109,76 @@ mod test { use field::*; use subtle::CTNegatable; + #[test] + fn print_constants() { + use curve::*; + println!(""); + fn repr_fe(s: &str, fe: &FieldElement, t: &'static str) { + let f = from_bytes_64(&fe.to_bytes()); + println!("{}FieldElement([{}, {}, {}, {}, {}]){}", s, f[0], f[1], f[2], f[3], f[4], t); + } + fn repr_ext(s: &'static str, P: &ExtendedPoint) { + println!("{}ExtendedPoint {{", s); + repr_fe(" X: ", &P.X, ","); + repr_fe(" Y: ", &P.Y, ","); + repr_fe(" Z: ", &P.Z, ","); + repr_fe(" T: ", &P.T, ","); + println!("}};"); + } + fn repr_aff(s: &'static str, P: &AffineNielsPoint) { + println!("{}AffineNielsPoint {{", s); + repr_fe(" y_plus_x: ", &P.y_plus_x, ","); + repr_fe(" y_minus_x: ", &P.y_minus_x, ","); + repr_fe(" xy2d: ", &P.xy2d, ","); + println!("}};"); + } + fn print(name: &'static str, f: &FieldElement) { + repr_fe(format!("pub const {}: FieldElement = ", name).as_str(), f, ";"); + } + + print("d", &constants::d); + print("d2", &constants::d2); + print("d4", &constants::d4); + print("a_minus_d", &constants::a_minus_d); + + print("SQRT_M1", &constants::SQRT_M1); + print("MSQRT_M1", &constants::MSQRT_M1); + + print("HALF", &constants::HALF); + print("A", &constants::A); + print("SQRT_MINUS_A", &constants::SQRT_MINUS_A); + print("SQRT_MINUS_APLUS2", &constants::SQRT_MINUS_APLUS2); + print("SQRT_MINUS_HALF", &constants::SQRT_MINUS_HALF); + + repr_ext("pub const ED25519_BASEPOINT: ExtendedPoint = ", &constants::ED25519_BASEPOINT); + + println!("pub const EIGHT_TORSION: [ExtendedPoint; 8] ="); + + for i in 0..8 { + repr_ext("", &constants::EIGHT_TORSION[i]); + println!(","); + } + + println!("pub const bi: [AffineNielsPoint; 8] ="); + + for i in 0..8 { + repr_aff("", &constants::bi[i]); + println!(","); + } + + println!("pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable(["); + + let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT); + for i in 0..32 { + println!("\n\n"); + for j in 0..8 { + repr_aff("", &table.0[i][j]); + } + } + + panic!(); + } + /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\ /// 2228051251926706380353716438957572 From 4ef22b679ce33bb662ccfa9a65765268feb6a239 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:29 -0700 Subject: [PATCH 061/101] Implement sub_assign for radix_51 --- src/field.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/field.rs b/src/field.rs index ce18f07..b2bde0c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -75,16 +75,6 @@ pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { [c0,c1,c2,c3,c4] } -fn subtract(a: &[u64; 5], b: &[u64; 5]) -> [u64; 5] { - // add p to avoid underflow - [ (a[0] + 2251799813685229) - b[0] - , (a[1] + 2251799813685247) - b[1] - , (a[2] + 2251799813685247) - b[2] - , (a[3] + 2251799813685247) - b[3] - , (a[4] + 2251799813685247) - b[4] - ] -} - fn from_bytes_64(bytes: &[u8;32]) -> [u64; 5] { let low_51_bit_mask = (1u64 << 51) - 1; // load bits [ 0, 64), no shift @@ -250,7 +240,22 @@ impl<'b> SubAssign<&'b FieldElement> for FieldElement { self[i] -= _rhs[i]; } } - // XXX_radix_51 + #[cfg(feature="radix_51")] + fn sub_assign(&mut self, _rhs: &'b FieldElement) { + // To avoid underflow, first add p + // XXX how many copies should we add to preserve headroom? + self.0[0] += 2251799813685229; + self.0[1] += 2251799813685247; + self.0[2] += 2251799813685247; + self.0[3] += 2251799813685247; + self.0[4] += 2251799813685247; + // then subtract _rhs + self.0[0] -= _rhs.0[0]; + self.0[1] -= _rhs.0[1]; + self.0[2] -= _rhs.0[2]; + self.0[3] -= _rhs.0[3]; + self.0[4] -= _rhs.0[4]; + } } impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement { From 08ef9e5d1e14b146f573c1dc325204b31ffe5a89 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:30 -0700 Subject: [PATCH 062/101] Add constants in radix_51 form --- src/constants.rs | 1518 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1516 insertions(+), 2 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 04aa289..1dd931f 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -30,18 +30,26 @@ use scalar::Scalar; pub const d: FieldElement = FieldElement([ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, ]); +#[cfg(feature="radix_51")] +pub const d: FieldElement = FieldElement([929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575]); #[cfg(feature="radix_25_5")] pub const d2: FieldElement = FieldElement([ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, ]); +#[cfg(feature="radix_51")] +pub const d2: FieldElement = FieldElement([1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903]); #[cfg(feature="radix_25_5")] pub const d4: FieldElement = FieldElement([ 23454405, -11679213, 5618422, -5756869, 458917, -1596832, -25103633, -12990876, -7676928, -14666033 ]); +#[cfg(feature="radix_51")] +pub const d4: FieldElement = FieldElement([1468021120295602, 1865462880516853, 2144638232625316, 1379996857856750, 1267578991991807]); #[cfg(feature="radix_25_5")] pub const a_minus_d: FieldElement = FieldElement([ 10913609, -13857413, 15372611, -6949391, -114729, 8787816, 6275908, 3247719, 18696448, 12055116, ]); +#[cfg(feature="radix_51")] +pub const a_minus_d: FieldElement = FieldElement([1321844580190025, 1785434093556034, 589740348686294, 217950738957124, 809005158844672]); /// (p-1)/2, in little-endian bytes. pub const HALF_P_MINUS_1_BYTES: [u8; 32] = @@ -55,6 +63,8 @@ pub const HALF_P_MINUS_1_BYTES: [u8; 32] = pub const SQRT_M1: FieldElement = FieldElement([ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, ]); +#[cfg(feature="radix_51")] +pub const SQRT_M1: FieldElement = FieldElement([1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133]); /// Precomputed value of the other square root of -1 (mod p), /// i.e., MSQRT_M1 = -SQRT_M1. @@ -62,16 +72,22 @@ pub const SQRT_M1: FieldElement = FieldElement([ pub const MSQRT_M1: FieldElement = FieldElement([ 32595792, 7943725, -9377950, -3500415, -12389472, 272473, 25146209, 2005654, -326686, -11406482, ]); +#[cfg(feature="radix_51")] +pub const MSQRT_M1: FieldElement = FieldElement([533094393274173, 2016890930128738, 18285341111199, 134597186663265, 1486323764102114]); /// Precomputed value of 1/2 (mod p). #[cfg(feature="radix_25_5")] pub const HALF: FieldElement = FieldElement([ 10, 0, 0, 0, 0, 0, 0, 0, 0, -16777216, ]); +#[cfg(feature="radix_51")] +pub const HALF: FieldElement = FieldElement([2251799813685239, 2251799813685247, 2251799813685247, 2251799813685247, 1125899906842623]); /// In Montgomery form y² = x³+Ax²+x, Curve25519 has A=486662. #[cfg(feature="radix_25_5")] pub const A: FieldElement = FieldElement([ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]); +#[cfg(feature="radix_51")] +pub const A: FieldElement = FieldElement([486662, 0, 0, 0, 0]); /// SQRT_MINUS_A is sqrt(-486662) // XXX I think that this was used in Adam's code for his elligator @@ -81,21 +97,26 @@ pub const A: FieldElement = FieldElement([ pub const SQRT_MINUS_A: FieldElement = FieldElement([ // sqrtMinusA 12222970, 8312128, 11511410, -9067497, 15300785, 241793, -25456130, -14121551, 12187136, -3972024, ]); +#[cfg(feature="radix_51")] +pub const SQRT_MINUS_A: FieldElement = FieldElement([557817479725543, 1643290402203250, 16226468853936, 1304118542701054, 1985241807451647]); /// SQRT_MINUS_APLUS2 is sqrt(-486664) #[cfg(feature="radix_25_5")] pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ -12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024]); +#[cfg(feature="radix_51")] +pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([1693982333959686, 608509411481997, 2235573344831311, 947681270984193, 266558006233600]); /// SQRT_MINUS_HALF is sqrt(-1/2) #[cfg(feature="radix_25_5")] pub const SQRT_MINUS_HALF: FieldElement = FieldElement([ // sqrtMinusHalf -17256545, 3971863, 28865457, -1750208, 27359696, -16640980, 12573105, 1002827, -163343, 11073975, ]); +#[cfg(feature="radix_51")] +pub const SQRT_MINUS_HALF: FieldElement = FieldElement([266547196637087, 2134345371906993, 1135042577398223, 67298593331632, 743161882051057]); /// HALF_Q_MINUS_1_BYTES is (2^255-20)/2 expressed in little endian form. -#[cfg(feature="radix_25_5")] pub const HALF_Q_MINUS_1_BYTES: [u8; 32] = [ // halfQMinus1Bytes 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -120,6 +141,13 @@ pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{ Z: FieldElement([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), T: FieldElement([28827062, -6116119, -27349572, 244363, 8635006, 11264893, 19351346, 13413597, 16611511, -6414980]), }; +#[cfg(feature="radix_51")] +pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint { + X: FieldElement([1738742601995546, 1146398526822698, 2070867633025821, 562264141797630, 587772402128613]), + Y: FieldElement([1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039]), +}; /// `l` is the order of base point, i.e. 2^252 + /// 27742317777372353535851937790883648493, in little-endian form @@ -192,6 +220,64 @@ pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ T: FieldElement([25262188, 11972680, -11716002, 5869612, 18193162, -16297739, -20670665, 8559098, -3541543, 5011181]) }, ]; +#[cfg(feature="radix_51")] +pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ + ExtendedPoint { + X: FieldElement([0, 0, 0, 0, 0]), + Y: FieldElement([1, 0, 0, 0, 0]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([0, 0, 0, 0, 0]), + } + , + ExtendedPoint { + X: FieldElement([358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676]), + Y: FieldElement([84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([1448326834587521, 1857896831960481, 1093722731865333, 1677408490711241, 1915505153018406]), + } + , + ExtendedPoint { + X: FieldElement([533094393274173, 2016890930128738, 18285341111199, 134597186663265, 1486323764102114]), + Y: FieldElement([0, 0, 0, 0, 0]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([0, 0, 0, 0, 0]), + } + , + ExtendedPoint { + X: FieldElement([358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676]), + Y: FieldElement([2166873539340326, 1778179147085316, 1886209374839743, 1223329526802818, 105300633354275]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([803472979097708, 393902981724766, 1158077081819914, 574391322974006, 336294660666841]), + } + , + ExtendedPoint { + X: FieldElement([0, 0, 0, 0, 0]), + Y: FieldElement([2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([0, 0, 0, 0, 0]), + } + , + ExtendedPoint { + X: FieldElement([1893055065632419, 560215195444267, 1274149604399886, 821933901047523, 1691754969406571]), + Y: FieldElement([2166873539340326, 1778179147085316, 1886209374839743, 1223329526802818, 105300633354275]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([1448326834587521, 1857896831960481, 1093722731865333, 1677408490711241, 1915505153018406]), + } + , + ExtendedPoint { + X: FieldElement([1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133]), + Y: FieldElement([0, 0, 0, 0, 0]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([0, 0, 0, 0, 0]), + } + , + ExtendedPoint { + X: FieldElement([1893055065632419, 560215195444267, 1274149604399886, 821933901047523, 1691754969406571]), + Y: FieldElement([84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972]), + Z: FieldElement([1, 0, 0, 0, 0]), + T: FieldElement([803472979097708, 393902981724766, 1158077081819914, 574391322974006, 336294660666841]), + } +]; #[cfg(feature="radix_25_5")] pub const bi: [AffineNielsPoint; 8] = [ @@ -235,7 +321,57 @@ pub const bi: [AffineNielsPoint; 8] = [ y_minus_x: FieldElement([-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619]), xy2d: FieldElement([-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683]), }, - ]; +]; +#[cfg(feature="radix_51")] +pub const bi: [AffineNielsPoint; 8] = [ + AffineNielsPoint { + y_plus_x: FieldElement([1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563]), + y_minus_x: FieldElement([62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585]), + xy2d: FieldElement([301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911]), + y_minus_x: FieldElement([316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597]), + xy2d: FieldElement([1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016]), + y_minus_x: FieldElement([425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893]), + xy2d: FieldElement([1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985]), + y_minus_x: FieldElement([2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113]), + xy2d: FieldElement([965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([1802695059465007, 1664899123557221, 593559490740857, 2160434469266659, 927570450755031]), + y_minus_x: FieldElement([1725674970513508, 1933645953859181, 1542344539275782, 1767788773573747, 1297447965928905]), + xy2d: FieldElement([1381809363726107, 1430341051343062, 2061843536018959, 1551778050872521, 2036394857967624]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([1970894096313054, 528066325833207, 1619374932191227, 2207306624415883, 1169170329061080]), + y_minus_x: FieldElement([2070390218572616, 1458919061857835, 624171843017421, 1055332792707765, 433987520732508]), + xy2d: FieldElement([893653801273833, 1168026499324677, 1242553501121234, 1306366254304474, 1086752658510815]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([213454002618221, 939771523987438, 1159882208056014, 317388369627517, 621213314200687]), + y_minus_x: FieldElement([1971678598905747, 338026507889165, 762398079972271, 655096486107477, 42299032696322]), + xy2d: FieldElement([177130678690680, 1754759263300204, 1864311296286618, 1180675631479880, 1292726903152791]), + } + , + AffineNielsPoint { + y_plus_x: FieldElement([1913163449625248, 460779200291993, 2193883288642314, 1008900146920800, 1721983679009502]), + y_minus_x: FieldElement([1070401523076875, 1272492007800961, 1910153608563310, 2075579521696771, 1191169788841221]), + xy2d: FieldElement([692896803108118, 500174642072499, 2068223309439677, 1162190621851337, 1426986007309901]), + } +]; /// Table containing precomputed multiples of the basepoint `B = (x,4/5)`. /// @@ -1587,6 +1723,1384 @@ pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable xy2d: FieldElement([-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476]), }, ]]); +#[cfg(feature="radix_51")] +pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable([ + [ + AffineNielsPoint { + y_plus_x: FieldElement([1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563]), + y_minus_x: FieldElement([62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585]), + xy2d: FieldElement([301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1380971894829527, 790832306631236, 2067202295274102, 1995808275510000, 1566530869037010]), + y_minus_x: FieldElement([463307831301544, 432984605774163, 1610641361907204, 750899048855000, 1894842303421586]), + xy2d: FieldElement([748439484463711, 1033211726465151, 1396005112841647, 1611506220286469, 1972177495910992]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911]), + y_minus_x: FieldElement([316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597]), + xy2d: FieldElement([1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([934282339813791, 1846903124198670, 1172395437954843, 1007037127761661, 1830588347719256]), + y_minus_x: FieldElement([1694390458783935, 1735906047636159, 705069562067493, 648033061693059, 696214010414170]), + xy2d: FieldElement([1121406372216585, 192876649532226, 190294192191717, 1994165897297032, 2245000007398739]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016]), + y_minus_x: FieldElement([425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893]), + xy2d: FieldElement([1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1388594989461809, 316767091099457, 394298842192982, 1230079486801005, 1440737038838979]), + y_minus_x: FieldElement([7380825640100, 146210432690483, 304903576448906, 1198869323871120, 997689833219095]), + xy2d: FieldElement([1181317918772081, 114573476638901, 262805072233344, 265712217171332, 294181933805782]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985]), + y_minus_x: FieldElement([2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113]), + xy2d: FieldElement([965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2068619540119183, 1966274918058806, 957728544705549, 729906502578991, 159834893065166]), + y_minus_x: FieldElement([2073601412052185, 31021124762708, 264500969797082, 248034690651703, 1030252227928288]), + xy2d: FieldElement([551790716293402, 1989538725166328, 801169423371717, 2052451893578887, 678432056995012]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1368953770187805, 790347636712921, 437508475667162, 2142576377050580, 1932081720066286]), + y_minus_x: FieldElement([953638594433374, 1092333936795051, 1419774766716690, 805677984380077, 859228993502513]), + xy2d: FieldElement([1200766035879111, 20142053207432, 1465634435977050, 1645256912097844, 295121984874596]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1735718747031557, 1248237894295956, 1204753118328107, 976066523550493, 65943769534592]), + y_minus_x: FieldElement([1060098822528990, 1586825862073490, 212301317240126, 1975302711403555, 666724059764335]), + xy2d: FieldElement([1091990273418756, 1572899409348578, 80968014455247, 306009358661350, 1520450739132526]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1480517209436112, 1511153322193952, 1244343858991172, 304788150493241, 369136856496443]), + y_minus_x: FieldElement([2151330273626164, 762045184746182, 1688074332551515, 823046109005759, 907602769079491]), + xy2d: FieldElement([2047386910586836, 168470092900250, 1552838872594810, 340951180073789, 360819374702533]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1982622644432056, 2014393600336956, 128909208804214, 1617792623929191, 105294281913815]), + y_minus_x: FieldElement([980234343912898, 1712256739246056, 588935272190264, 204298813091998, 841798321043288]), + xy2d: FieldElement([197561292938973, 454817274782871, 1963754960082318, 2113372252160468, 971377527342673]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([164699448829328, 3127451757672, 1199504971548753, 1766155447043652, 1899238924683527]), + y_minus_x: FieldElement([732262946680281, 1674412764227063, 2182456405662809, 1350894754474250, 558458873295247]), + xy2d: FieldElement([2103305098582922, 1960809151316468, 715134605001343, 1454892949167181, 40827143824949]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1239289043050212, 1744654158124578, 758702410031698, 1796762995074688, 1603056663766]), + y_minus_x: FieldElement([2232056027107988, 987343914584615, 2115594492994461, 1819598072792159, 1119305654014850]), + xy2d: FieldElement([320153677847348, 939613871605645, 641883205761567, 1930009789398224, 329165806634126]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([980930490474130, 1242488692177893, 1251446316964684, 1086618677993530, 1961430968465772]), + y_minus_x: FieldElement([276821765317453, 1536835591188030, 1305212741412361, 61473904210175, 2051377036983058]), + xy2d: FieldElement([833449923882501, 1750270368490475, 1123347002068295, 185477424765687, 278090826653186]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([794524995833413, 1849907304548286, 53348672473145, 1272368559505217, 1147304168324779]), + y_minus_x: FieldElement([1504846112759364, 1203096289004681, 562139421471418, 274333017451844, 1284344053775441]), + xy2d: FieldElement([483048732424432, 2116063063343382, 30120189902313, 292451576741007, 1156379271702225]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([928372153029038, 2147692869914564, 1455665844462196, 1986737809425946, 185207050258089]), + y_minus_x: FieldElement([137732961814206, 706670923917341, 1387038086865771, 1965643813686352, 1384777115696347]), + xy2d: FieldElement([481144981981577, 2053319313589856, 2065402289827512, 617954271490316, 1106602634668125]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([696298019648792, 893299659040895, 1148636718636009, 26734077349617, 2203955659340681]), + y_minus_x: FieldElement([657390353372855, 998499966885562, 991893336905797, 810470207106761, 343139804608786]), + xy2d: FieldElement([791736669492960, 934767652997115, 824656780392914, 1759463253018643, 361530362383518]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2022541353055597, 2094700262587466, 1551008075025686, 242785517418164, 695985404963562]), + y_minus_x: FieldElement([1287487199965223, 2215311941380308, 1552928390931986, 1664859529680196, 1125004975265243]), + xy2d: FieldElement([677434665154918, 989582503122485, 1817429540898386, 1052904935475344, 1143826298169798]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([367266328308408, 318431188922404, 695629353755355, 634085657580832, 24581612564426]), + y_minus_x: FieldElement([773360688841258, 1815381330538070, 363773437667376, 539629987070205, 783280434248437]), + xy2d: FieldElement([180820816194166, 168937968377394, 748416242794470, 1227281252254508, 1567587861004268]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([478775558583645, 2062896624554807, 699391259285399, 358099408427873, 1277310261461761]), + y_minus_x: FieldElement([1984740906540026, 1079164179400229, 1056021349262661, 1659958556483663, 1088529069025527]), + xy2d: FieldElement([580736401511151, 1842931091388998, 1177201471228238, 2075460256527244, 1301133425678027]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1515728832059182, 1575261009617579, 1510246567196186, 191078022609704, 116661716289141]), + y_minus_x: FieldElement([1295295738269652, 1714742313707026, 545583042462581, 2034411676262552, 1513248090013606]), + xy2d: FieldElement([230710545179830, 30821514358353, 760704303452229, 390668103790604, 573437871383156]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1169380107545646, 263167233745614, 2022901299054448, 819900753251120, 2023898464874585]), + y_minus_x: FieldElement([2102254323485823, 1570832666216754, 34696906544624, 1993213739807337, 70638552271463]), + xy2d: FieldElement([894132856735058, 548675863558441, 845349339503395, 1942269668326667, 1615682209874691]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1287670217537834, 1222355136884920, 1846481788678694, 1150426571265110, 1613523400722047]), + y_minus_x: FieldElement([793388516527298, 1315457083650035, 1972286999342417, 1901825953052455, 338269477222410]), + xy2d: FieldElement([550201530671806, 778605267108140, 2063911101902983, 115500557286349, 2041641272971022]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([717255318455100, 519313764361315, 2080406977303708, 541981206705521, 774328150311600]), + y_minus_x: FieldElement([261715221532238, 1795354330069993, 1496878026850283, 499739720521052, 389031152673770]), + xy2d: FieldElement([1997217696294013, 1717306351628065, 1684313917746180, 1644426076011410, 1857378133465451]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1475434724792648, 76931896285979, 1116729029771667, 2002544139318042, 725547833803938]), + y_minus_x: FieldElement([2022306639183567, 726296063571875, 315345054448644, 1058733329149221, 1448201136060677]), + xy2d: FieldElement([1710065158525665, 1895094923036397, 123988286168546, 1145519900776355, 1607510767693874]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([561605375422540, 1071733543815037, 131496498800990, 1946868434569999, 828138133964203]), + y_minus_x: FieldElement([1548495173745801, 442310529226540, 998072547000384, 553054358385281, 644824326376171]), + xy2d: FieldElement([1445526537029440, 2225519789662536, 914628859347385, 1064754194555068, 1660295614401091]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1199690223111956, 24028135822341, 66638289244341, 57626156285975, 565093967979607]), + y_minus_x: FieldElement([876926774220824, 554618976488214, 1012056309841565, 839961821554611, 1414499340307677]), + xy2d: FieldElement([703047626104145, 1266841406201770, 165556500219173, 486991595001879, 1011325891650656]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1622861044480487, 1156394801573634, 1869132565415504, 327103985777730, 2095342781472284]), + y_minus_x: FieldElement([334886927423922, 489511099221528, 129160865966726, 1720809113143481, 619700195649254]), + xy2d: FieldElement([1646545795166119, 1758370782583567, 714746174550637, 1472693650165135, 898994790308209]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([333403773039279, 295772542452938, 1693106465353610, 912330357530760, 471235657950362]), + y_minus_x: FieldElement([1811196219982022, 1068969825533602, 289602974833439, 1988956043611592, 863562343398367]), + xy2d: FieldElement([906282429780072, 2108672665779781, 432396390473936, 150625823801893, 1708930497638539]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([925664675702328, 21416848568684, 1831436641861340, 601157008940113, 371818055044496]), + y_minus_x: FieldElement([1479786007267725, 1738881859066675, 68646196476567, 2146507056100328, 1247662817535471]), + xy2d: FieldElement([52035296774456, 939969390708103, 312023458773250, 59873523517659, 1231345905848899]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([643355106415761, 290186807495774, 2013561737429023, 319648069511546, 393736678496162]), + y_minus_x: FieldElement([129358342392716, 1932811617704777, 1176749390799681, 398040349861790, 1170779668090425]), + xy2d: FieldElement([2051980782668029, 121859921510665, 2048329875753063, 1235229850149665, 519062146124755]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1608170971973096, 415809060360428, 1350468408164766, 2038620059057678, 1026904485989112]), + y_minus_x: FieldElement([1837656083115103, 1510134048812070, 906263674192061, 1821064197805734, 565375124676301]), + xy2d: FieldElement([578027192365650, 2034800251375322, 2128954087207123, 478816193810521, 2196171989962750]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1633188840273139, 852787172373708, 1548762607215796, 1266275218902681, 1107218203325133]), + y_minus_x: FieldElement([462189358480054, 1784816734159228, 1611334301651368, 1303938263943540, 707589560319424]), + xy2d: FieldElement([1038829280972848, 38176604650029, 753193246598573, 1136076426528122, 595709990562434]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1408451820859834, 2194984964010833, 2198361797561729, 1061962440055713, 1645147963442934]), + y_minus_x: FieldElement([4701053362120, 1647641066302348, 1047553002242085, 1923635013395977, 206970314902065]), + xy2d: FieldElement([1750479161778571, 1362553355169293, 1891721260220598, 966109370862782, 1024913988299801]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([212699049131723, 1117950018299775, 1873945661751056, 1403802921984058, 130896082652698]), + y_minus_x: FieldElement([636808533673210, 1262201711667560, 390951380330599, 1663420692697294, 561951321757406]), + xy2d: FieldElement([520731594438141, 1446301499955692, 273753264629267, 1565101517999256, 1019411827004672]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([926527492029409, 1191853477411379, 734233225181171, 184038887541270, 1790426146325343]), + y_minus_x: FieldElement([1464651961852572, 1483737295721717, 1519450561335517, 1161429831763785, 405914998179977]), + xy2d: FieldElement([996126634382301, 796204125879525, 127517800546509, 344155944689303, 615279846169038]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([738724080975276, 2188666632415296, 1961313708559162, 1506545807547587, 1151301638969740]), + y_minus_x: FieldElement([622917337413835, 1218989177089035, 1284857712846592, 970502061709359, 351025208117090]), + xy2d: FieldElement([2067814584765580, 1677855129927492, 2086109782475197, 235286517313238, 1416314046739645]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([586844262630358, 307444381952195, 458399356043426, 602068024507062, 1028548203415243]), + y_minus_x: FieldElement([678489922928203, 2016657584724032, 90977383049628, 1026831907234582, 615271492942522]), + xy2d: FieldElement([301225714012278, 1094837270268560, 1202288391010439, 644352775178361, 1647055902137983]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1210746697896478, 1416608304244708, 686487477217856, 1245131191434135, 1051238336855737]), + y_minus_x: FieldElement([1135604073198207, 1683322080485474, 769147804376683, 2086688130589414, 900445683120379]), + xy2d: FieldElement([1971518477615628, 401909519527336, 448627091057375, 1409486868273821, 1214789035034363]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1364039144731711, 1897497433586190, 2203097701135459, 145461396811251, 1349844460790699]), + y_minus_x: FieldElement([1045230323257973, 818206601145807, 630513189076103, 1672046528998132, 807204017562437]), + xy2d: FieldElement([439961968385997, 386362664488986, 1382706320807688, 309894000125359, 2207801346498567]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1229004686397588, 920643968530863, 123975893911178, 681423993215777, 1400559197080973]), + y_minus_x: FieldElement([2003766096898049, 170074059235165, 1141124258967971, 1485419893480973, 1573762821028725]), + xy2d: FieldElement([729905708611432, 1270323270673202, 123353058984288, 426460209632942, 2195574535456672]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1271140255321235, 2044363183174497, 52125387634689, 1445120246694705, 942541986339084]), + y_minus_x: FieldElement([1761608437466135, 583360847526804, 1586706389685493, 2157056599579261, 1170692369685772]), + xy2d: FieldElement([871476219910823, 1878769545097794, 2241832391238412, 548957640601001, 690047440233174]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([297194732135507, 1366347803776820, 1301185512245601, 561849853336294, 1533554921345731]), + y_minus_x: FieldElement([999628998628371, 1132836708493400, 2084741674517453, 469343353015612, 678782988708035]), + xy2d: FieldElement([2189427607417022, 699801937082607, 412764402319267, 1478091893643349, 2244675696854460]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1712292055966563, 204413590624874, 1405738637332841, 408981300829763, 861082219276721]), + y_minus_x: FieldElement([508561155940631, 966928475686665, 2236717801150132, 424543858577297, 2089272956986143]), + xy2d: FieldElement([221245220129925, 1156020201681217, 491145634799213, 542422431960839, 828100817819207]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([153756971240384, 1299874139923977, 393099165260502, 1058234455773022, 996989038681183]), + y_minus_x: FieldElement([559086812798481, 573177704212711, 1629737083816402, 1399819713462595, 1646954378266038]), + xy2d: FieldElement([1887963056288059, 228507035730124, 1468368348640282, 930557653420194, 613513962454686]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1224529808187553, 1577022856702685, 2206946542980843, 625883007765001, 279930793512158]), + y_minus_x: FieldElement([1076287717051609, 1114455570543035, 187297059715481, 250446884292121, 1885187512550540]), + xy2d: FieldElement([902497362940219, 76749815795675, 1657927525633846, 1420238379745202, 1340321636548352]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1129576631190784, 1281994010027327, 996844254743018, 257876363489249, 1150850742055018]), + y_minus_x: FieldElement([628740660038789, 1943038498527841, 467786347793886, 1093341428303375, 235413859513003]), + xy2d: FieldElement([237425418909360, 469614029179605, 1512389769174935, 1241726368345357, 441602891065214]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1736417953058555, 726531315520508, 1833335034432527, 1629442561574747, 624418919286085]), + y_minus_x: FieldElement([1960754663920689, 497040957888962, 1909832851283095, 1271432136996826, 2219780368020940]), + xy2d: FieldElement([1537037379417136, 1358865369268262, 2130838645654099, 828733687040705, 1999987652890901]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([629042105241814, 1098854999137608, 887281544569320, 1423102019874777, 7911258951561]), + y_minus_x: FieldElement([1811562332665373, 1501882019007673, 2213763501088999, 359573079719636, 36370565049116]), + xy2d: FieldElement([218907117361280, 1209298913016966, 1944312619096112, 1130690631451061, 1342327389191701]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1369976867854704, 1396479602419169, 1765656654398856, 2203659200586299, 998327836117241]), + y_minus_x: FieldElement([2230701885562825, 1348173180338974, 2172856128624598, 1426538746123771, 444193481326151]), + xy2d: FieldElement([784210426627951, 918204562375674, 1284546780452985, 1324534636134684, 1872449409642708]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([319638829540294, 596282656808406, 2037902696412608, 1557219121643918, 341938082688094]), + y_minus_x: FieldElement([1901860206695915, 2004489122065736, 1625847061568236, 973529743399879, 2075287685312905]), + xy2d: FieldElement([1371853944110545, 1042332820512553, 1949855697918254, 1791195775521505, 37487364849293]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([687200189577855, 1082536651125675, 644224940871546, 340923196057951, 343581346747396]), + y_minus_x: FieldElement([2082717129583892, 27829425539422, 145655066671970, 1690527209845512, 1865260509673478]), + xy2d: FieldElement([1059729620568824, 2163709103470266, 1440302280256872, 1769143160546397, 869830310425069]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1609516219779025, 777277757338817, 2101121130363987, 550762194946473, 1905542338659364]), + y_minus_x: FieldElement([2024821921041576, 426948675450149, 595133284085473, 471860860885970, 600321679413000]), + xy2d: FieldElement([598474602406721, 1468128276358244, 1191923149557635, 1501376424093216, 1281662691293476]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1721138489890707, 1264336102277790, 433064545421287, 1359988423149466, 1561871293409447]), + y_minus_x: FieldElement([719520245587143, 393380711632345, 132350400863381, 1543271270810729, 1819543295798660]), + xy2d: FieldElement([396397949784152, 1811354474471839, 1362679985304303, 2117033964846756, 498041172552279]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1812471844975748, 1856491995543149, 126579494584102, 1036244859282620, 1975108050082550]), + y_minus_x: FieldElement([650623932407995, 1137551288410575, 2125223403615539, 1725658013221271, 2134892965117796]), + xy2d: FieldElement([522584000310195, 1241762481390450, 1743702789495384, 2227404127826575, 1686746002148897]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([427904865186312, 1703211129693455, 1585368107547509, 1436984488744336, 761188534613978]), + y_minus_x: FieldElement([318101947455002, 248138407995851, 1481904195303927, 309278454311197, 1258516760217879]), + xy2d: FieldElement([1275068538599310, 513726919533379, 349926553492294, 688428871968420, 1702400196000666]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1061864036265233, 961611260325381, 321859632700838, 1045600629959517, 1985130202504038]), + y_minus_x: FieldElement([1558816436882417, 1962896332636523, 1337709822062152, 1501413830776938, 294436165831932]), + xy2d: FieldElement([818359826554971, 1862173000996177, 626821592884859, 573655738872376, 1749691246745455]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1988022651432119, 1082111498586040, 1834020786104821, 1454826876423687, 692929915223122]), + y_minus_x: FieldElement([2146513703733331, 584788900394667, 464965657279958, 2183973639356127, 238371159456790]), + xy2d: FieldElement([1129007025494441, 2197883144413266, 265142755578169, 971864464758890, 1983715884903702]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1291366624493075, 381456718189114, 1711482489312444, 1815233647702022, 892279782992467]), + y_minus_x: FieldElement([444548969917454, 1452286453853356, 2113731441506810, 645188273895859, 810317625309512]), + xy2d: FieldElement([2242724082797924, 1373354730327868, 1006520110883049, 2147330369940688, 1151816104883620]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1745720200383796, 1911723143175317, 2056329390702074, 355227174309849, 879232794371100]), + y_minus_x: FieldElement([163723479936298, 115424889803150, 1156016391581227, 1894942220753364, 1970549419986329]), + xy2d: FieldElement([681981452362484, 267208874112496, 1374683991933094, 638600984916117, 646178654558546]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([13378654854251, 106237307029567, 1944412051589651, 1841976767925457, 230702819835573]), + y_minus_x: FieldElement([260683893467075, 854060306077237, 913639551980112, 4704576840123, 280254810808712]), + xy2d: FieldElement([715374893080287, 1173334812210491, 1806524662079626, 1894596008000979, 398905715033393]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([500026409727661, 1596431288195371, 1420380351989370, 985211561521489, 392444930785633]), + y_minus_x: FieldElement([2096421546958141, 1922523000950363, 789831022876840, 427295144688779, 320923973161730]), + xy2d: FieldElement([1927770723575450, 1485792977512719, 1850996108474547, 551696031508956, 2126047405475647]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2112099158080148, 742570803909715, 6484558077432, 1951119898618916, 93090382703416]), + y_minus_x: FieldElement([383905201636970, 859946997631870, 855623867637644, 1017125780577795, 794250831877809]), + xy2d: FieldElement([77571826285752, 999304298101753, 487841111777762, 1038031143212339, 339066367948762]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([674994775520533, 266035846330789, 826951213393478, 1405007746162285, 1781791018620876]), + y_minus_x: FieldElement([1001412661522686, 348196197067298, 1666614366723946, 888424995032760, 580747687801357]), + xy2d: FieldElement([1939560076207777, 1409892634407635, 552574736069277, 383854338280405, 190706709864139]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2177087163428741, 1439255351721944, 1208070840382793, 2230616362004769, 1396886392021913]), + y_minus_x: FieldElement([676962063230039, 1880275537148808, 2046721011602706, 888463247083003, 1318301552024067]), + xy2d: FieldElement([1466980508178206, 617045217998949, 652303580573628, 757303753529064, 207583137376902]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1511056752906902, 105403126891277, 493434892772846, 1091943425335976, 1802717338077427]), + y_minus_x: FieldElement([1853982405405128, 1878664056251147, 1528011020803992, 1019626468153565, 1128438412189035]), + xy2d: FieldElement([1963939888391106, 293456433791664, 697897559513649, 985882796904380, 796244541237972]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([416770998629779, 389655552427054, 1314476859406756, 1749382513022778, 1161905598739491]), + y_minus_x: FieldElement([1428358296490651, 1027115282420478, 304840698058337, 441410174026628, 1819358356278573]), + xy2d: FieldElement([204943430200135, 1554861433819175, 216426658514651, 264149070665950, 2047097371738319]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1934415182909034, 1393285083565062, 516409331772960, 1157690734993892, 121039666594268]), + y_minus_x: FieldElement([662035583584445, 286736105093098, 1131773000510616, 818494214211439, 472943792054479]), + xy2d: FieldElement([665784778135882, 1893179629898606, 808313193813106, 276797254706413, 1563426179676396]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([945205108984232, 526277562959295, 1324180513733566, 1666970227868664, 153547609289173]), + y_minus_x: FieldElement([2031433403516252, 203996615228162, 170487168837083, 981513604791390, 843573964916831]), + xy2d: FieldElement([1476570093962618, 838514669399805, 1857930577281364, 2017007352225784, 317085545220047]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1461557121912842, 1600674043318359, 2157134900399597, 1670641601940616, 127765583803283]), + y_minus_x: FieldElement([1293543509393474, 2143624609202546, 1058361566797508, 214097127393994, 946888515472729]), + xy2d: FieldElement([357067959932916, 1290876214345711, 521245575443703, 1494975468601005, 800942377643885]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([566116659100033, 820247422481740, 994464017954148, 327157611686365, 92591318111744]), + y_minus_x: FieldElement([617256647603209, 1652107761099439, 1857213046645471, 1085597175214970, 817432759830522]), + xy2d: FieldElement([771808161440705, 1323510426395069, 680497615846440, 851580615547985, 1320806384849017]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1219260086131915, 647169006596815, 79601124759706, 2161724213426748, 404861897060198]), + y_minus_x: FieldElement([1327968293887866, 1335500852943256, 1401587164534264, 558137311952440, 1551360549268902]), + xy2d: FieldElement([417621685193956, 1429953819744454, 396157358457099, 1940470778873255, 214000046234152]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1268047918491973, 2172375426948536, 1533916099229249, 1761293575457130, 1590622667026765]), + y_minus_x: FieldElement([1627072914981959, 2211603081280073, 1912369601616504, 1191770436221309, 2187309757525860]), + xy2d: FieldElement([1149147819689533, 378692712667677, 828475842424202, 2218619146419342, 70688125792186]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1299739417079761, 1438616663452759, 1536729078504412, 2053896748919838, 1008421032591246]), + y_minus_x: FieldElement([2040723824657366, 399555637875075, 632543375452995, 872649937008051, 1235394727030233]), + xy2d: FieldElement([2211311599327900, 2139787259888175, 938706616835350, 12609661139114, 2081897930719789]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1324994503390450, 336982330582631, 1183998925654177, 1091654665913274, 48727673971319]), + y_minus_x: FieldElement([1845522914617879, 1222198248335542, 150841072760134, 1927029069940982, 1189913404498011]), + xy2d: FieldElement([1079559557592645, 2215338383666441, 1903569501302605, 49033973033940, 305703433934152]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([94653405416909, 1386121349852999, 1062130477891762, 36553947479274, 833669648948846]), + y_minus_x: FieldElement([1432015813136298, 440364795295369, 1395647062821501, 1976874522764578, 934452372723352]), + xy2d: FieldElement([1296625309219774, 2068273464883862, 1858621048097805, 1492281814208508, 2235868981918946]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1490330266465570, 1858795661361448, 1436241134969763, 294573218899647, 1208140011028933]), + y_minus_x: FieldElement([1282462923712748, 741885683986255, 2027754642827561, 518989529541027, 1826610009555945]), + xy2d: FieldElement([1525827120027511, 723686461809551, 1597702369236987, 244802101764964, 1502833890372311]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([113622036244513, 1233740067745854, 674109952278496, 2114345180342965, 166764512856263]), + y_minus_x: FieldElement([2041668749310338, 2184405322203901, 1633400637611036, 2110682505536899, 2048144390084644]), + xy2d: FieldElement([503058759232932, 760293024620937, 2027152777219493, 666858468148475, 1539184379870952]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1916168475367211, 915626432541343, 883217071712575, 363427871374304, 1976029821251593]), + y_minus_x: FieldElement([678039535434506, 570587290189340, 1605302676614120, 2147762562875701, 1706063797091704]), + xy2d: FieldElement([1439489648586438, 2194580753290951, 832380563557396, 561521973970522, 584497280718389]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([187989455492609, 681223515948275, 1933493571072456, 1872921007304880, 488162364135671]), + y_minus_x: FieldElement([1413466089534451, 410844090765630, 1397263346404072, 408227143123410, 1594561803147811]), + xy2d: FieldElement([2102170800973153, 719462588665004, 1479649438510153, 1097529543970028, 1302363283777685]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([942065717847195, 1069313679352961, 2007341951411051, 70973416446291, 1419433790163706]), + y_minus_x: FieldElement([1146565545556377, 1661971299445212, 406681704748893, 564452436406089, 1109109865829139]), + xy2d: FieldElement([2214421081775077, 1165671861210569, 1890453018796184, 3556249878661, 442116172656317]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([753830546620811, 1666955059895019, 1530775289309243, 1119987029104146, 2164156153857580]), + y_minus_x: FieldElement([615171919212796, 1523849404854568, 854560460547503, 2067097370290715, 1765325848586042]), + xy2d: FieldElement([1094538949313667, 1796592198908825, 870221004284388, 2025558921863561, 1699010892802384]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1951351290725195, 1916457206844795, 198025184438026, 1909076887557595, 1938542290318919]), + y_minus_x: FieldElement([1014323197538413, 869150639940606, 1756009942696599, 1334952557375672, 1544945379082874]), + xy2d: FieldElement([764055910920305, 1603590757375439, 146805246592357, 1843313433854297, 954279890114939]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([80113526615750, 764536758732259, 1055139345100233, 469252651759390, 617897512431515]), + y_minus_x: FieldElement([74497112547268, 740094153192149, 1745254631717581, 727713886503130, 1283034364416928]), + xy2d: FieldElement([525892105991110, 1723776830270342, 1476444848991936, 573789489857760, 133864092632978]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([542611720192581, 1986812262899321, 1162535242465837, 481498966143464, 544600533583622]), + y_minus_x: FieldElement([64123227344372, 1239927720647794, 1360722983445904, 222610813654661, 62429487187991]), + xy2d: FieldElement([1793193323953132, 91096687857833, 70945970938921, 2158587638946380, 1537042406482111]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1895854577604609, 1394895708949416, 1728548428495944, 1140864900240149, 563645333603061]), + y_minus_x: FieldElement([141358280486863, 91435889572504, 1087208572552643, 1829599652522921, 1193307020643647]), + xy2d: FieldElement([1611230858525381, 950720175540785, 499589887488610, 2001656988495019, 88977313255908]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1189080501479658, 2184348804772597, 1040818725742319, 2018318290311834, 1712060030915354]), + y_minus_x: FieldElement([873966876953756, 1090638350350440, 1708559325189137, 672344594801910, 1320437969700239]), + xy2d: FieldElement([1508590048271766, 1131769479776094, 101550868699323, 428297785557897, 561791648661744]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([756417570499462, 237882279232602, 2136263418594016, 1701968045454886, 703713185137472]), + y_minus_x: FieldElement([1781187809325462, 1697624151492346, 1381393690939988, 175194132284669, 1483054666415238]), + xy2d: FieldElement([2175517777364616, 708781536456029, 955668231122942, 1967557500069555, 2021208005604118]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1115135966606887, 224217372950782, 915967306279222, 593866251291540, 561747094208006]), + y_minus_x: FieldElement([1443163092879439, 391875531646162, 2180847134654632, 464538543018753, 1594098196837178]), + xy2d: FieldElement([850858855888869, 319436476624586, 327807784938441, 740785849558761, 17128415486016]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2132756334090067, 536247820155645, 48907151276867, 608473197600695, 1261689545022784]), + y_minus_x: FieldElement([1525176236978354, 974205476721062, 293436255662638, 148269621098039, 137961998433963]), + xy2d: FieldElement([1121075518299410, 2071745529082111, 1265567917414828, 1648196578317805, 496232102750820]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([122321229299801, 1022922077493685, 2001275453369484, 2017441881607947, 993205880778002]), + y_minus_x: FieldElement([654925550560074, 1168810995576858, 575655959430926, 905758704861388, 496774564663534]), + xy2d: FieldElement([1954109525779738, 2117022646152485, 338102630417180, 1194140505732026, 107881734943492]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1714785840001267, 2036500018681589, 1876380234251966, 2056717182974196, 1645855254384642]), + y_minus_x: FieldElement([106431476499341, 62482972120563, 1513446655109411, 807258751769522, 538491469114]), + xy2d: FieldElement([2002850762893643, 1243624520538135, 1486040410574605, 2184752338181213, 378495998083531]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([922510868424903, 1089502620807680, 402544072617374, 1131446598479839, 1290278588136533]), + y_minus_x: FieldElement([1867998812076769, 715425053580701, 39968586461416, 2173068014586163, 653822651801304]), + xy2d: FieldElement([162892278589453, 182585796682149, 75093073137630, 497037941226502, 133871727117371]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1914596576579670, 1608999621851578, 1987629837704609, 1519655314857977, 1819193753409464]), + y_minus_x: FieldElement([1949315551096831, 1069003344994464, 1939165033499916, 1548227205730856, 1933767655861407]), + xy2d: FieldElement([1730519386931635, 1393284965610134, 1597143735726030, 416032382447158, 1429665248828629]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([360275475604565, 547835731063078, 215360904187529, 596646739879007, 332709650425085]), + y_minus_x: FieldElement([47602113726801, 1522314509708010, 437706261372925, 814035330438027, 335930650933545]), + xy2d: FieldElement([1291597595523886, 1058020588994081, 402837842324045, 1363323695882781, 2105763393033193]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([109521982566564, 1715257748585139, 1112231216891516, 2046641005101484, 134249157157013]), + y_minus_x: FieldElement([2156991030936798, 2227544497153325, 1869050094431622, 754875860479115, 1754242344267058]), + xy2d: FieldElement([1846089562873800, 98894784984326, 1412430299204844, 171351226625762, 1100604760929008]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([84172382130492, 499710970700046, 425749630620778, 1762872794206857, 612842602127960]), + y_minus_x: FieldElement([868309334532756, 1703010512741873, 1952690008738057, 4325269926064, 2071083554962116]), + xy2d: FieldElement([523094549451158, 401938899487815, 1407690589076010, 2022387426254453, 158660516411257]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([612867287630009, 448212612103814, 571629077419196, 1466796750919376, 1728478129663858]), + y_minus_x: FieldElement([1723848973783452, 2208822520534681, 1718748322776940, 1974268454121942, 1194212502258141]), + xy2d: FieldElement([1254114807944608, 977770684047110, 2010756238954993, 1783628927194099, 1525962994408256]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([232464058235826, 1948628555342434, 1835348780427694, 1031609499437291, 64472106918373]), + y_minus_x: FieldElement([767338676040683, 754089548318405, 1523192045639075, 435746025122062, 512692508440385]), + xy2d: FieldElement([1255955808701983, 1700487367990941, 1166401238800299, 1175121994891534, 1190934801395380]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([349144008168292, 1337012557669162, 1475912332999108, 1321618454900458, 47611291904320]), + y_minus_x: FieldElement([877519947135419, 2172838026132651, 272304391224129, 1655143327559984, 886229406429814]), + xy2d: FieldElement([375806028254706, 214463229793940, 572906353144089, 572168269875638, 697556386112979]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1168827102357844, 823864273033637, 2071538752104697, 788062026895924, 599578340743362]), + y_minus_x: FieldElement([1948116082078088, 2054898304487796, 2204939184983900, 210526805152138, 786593586607626]), + xy2d: FieldElement([1915320147894736, 156481169009469, 655050471180417, 592917090415421, 2165897438660879]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1726336468579724, 1119932070398949, 1929199510967666, 33918788322959, 1836837863503150]), + y_minus_x: FieldElement([829996854845988, 217061778005138, 1686565909803640, 1346948817219846, 1723823550730181]), + xy2d: FieldElement([384301494966394, 687038900403062, 2211195391021739, 254684538421383, 1245698430589680]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1247567493562688, 1978182094455847, 183871474792955, 806570235643435, 288461518067916]), + y_minus_x: FieldElement([1449077384734201, 38285445457996, 2136537659177832, 2146493000841573, 725161151123125]), + xy2d: FieldElement([1201928866368855, 800415690605445, 1703146756828343, 997278587541744, 1858284414104014]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([356468809648877, 782373916933152, 1718002439402870, 1392222252219254, 663171266061951]), + y_minus_x: FieldElement([759628738230460, 1012693474275852, 353780233086498, 246080061387552, 2030378857679162]), + xy2d: FieldElement([2040672435071076, 888593182036908, 1298443657189359, 1804780278521327, 354070726137060]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1894938527423184, 1463213041477277, 474410505497651, 247294963033299, 877975941029128]), + y_minus_x: FieldElement([207937160991127, 12966911039119, 820997788283092, 1010440472205286, 1701372890140810]), + xy2d: FieldElement([218882774543183, 533427444716285, 1233243976733245, 435054256891319, 1509568989549904]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1888838535711826, 1052177758340622, 1213553803324135, 169182009127332, 463374268115872]), + y_minus_x: FieldElement([299137589460312, 1594371588983567, 868058494039073, 257771590636681, 1805012993142921]), + xy2d: FieldElement([1806842755664364, 2098896946025095, 1356630998422878, 1458279806348064, 347755825962072]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1402334161391744, 1560083671046299, 1008585416617747, 1147797150908892, 1420416683642459]), + y_minus_x: FieldElement([665506704253369, 273770475169863, 799236974202630, 848328990077558, 1811448782807931]), + xy2d: FieldElement([1468412523962641, 771866649897997, 1931766110147832, 799561180078482, 524837559150077]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2223212657821850, 630416247363666, 2144451165500328, 816911130947791, 1024351058410032]), + y_minus_x: FieldElement([1266603897524861, 156378408858100, 1275649024228779, 447738405888420, 253186462063095]), + xy2d: FieldElement([2022215964509735, 136144366993649, 1800716593296582, 1193970603800203, 871675847064218]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1862751661970328, 851596246739884, 1519315554814041, 1542798466547449, 1417975335901520]), + y_minus_x: FieldElement([1228168094547481, 334133883362894, 587567568420081, 433612590281181, 603390400373205]), + xy2d: FieldElement([121893973206505, 1843345804916664, 1703118377384911, 497810164760654, 101150811654673]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([458346255946468, 290909935619344, 1452768413850679, 550922875254215, 1537286854336538]), + y_minus_x: FieldElement([584322311184395, 380661238802118, 114839394528060, 655082270500073, 2111856026034852]), + xy2d: FieldElement([996965581008991, 2148998626477022, 1012273164934654, 1073876063914522, 1688031788934939]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([923487018849600, 2085106799623355, 528082801620136, 1606206360876188, 735907091712524]), + y_minus_x: FieldElement([1697697887804317, 1335343703828273, 831288615207040, 949416685250051, 288760277392022]), + xy2d: FieldElement([1419122478109648, 1325574567803701, 602393874111094, 2107893372601700, 1314159682671307]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([2201150872731804, 2180241023425241, 97663456423163, 1633405770247824, 848945042443986]), + y_minus_x: FieldElement([1173339555550611, 818605084277583, 47521504364289, 924108720564965, 735423405754506]), + xy2d: FieldElement([830104860549448, 1886653193241086, 1600929509383773, 1475051275443631, 286679780900937]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1577111294832995, 1030899169768747, 144900916293530, 1964672592979567, 568390100955250]), + y_minus_x: FieldElement([278388655910247, 487143369099838, 927762205508727, 181017540174210, 1616886700741287]), + xy2d: FieldElement([1191033906638969, 940823957346562, 1606870843663445, 861684761499847, 658674867251089]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1875032594195546, 1427106132796197, 724736390962158, 901860512044740, 635268497268760]), + y_minus_x: FieldElement([622869792298357, 1903919278950367, 1922588621661629, 1520574711600434, 1087100760174640]), + xy2d: FieldElement([25465949416618, 1693639527318811, 1526153382657203, 125943137857169, 145276964043999]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([214739857969358, 920212862967915, 1939901550972269, 1211862791775221, 85097515720120]), + y_minus_x: FieldElement([2006245852772938, 734762734836159, 254642929763427, 1406213292755966, 239303749517686]), + xy2d: FieldElement([1619678837192149, 1919424032779215, 1357391272956794, 1525634040073113, 1310226789796241]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1040763709762123, 1704449869235352, 605263070456329, 1998838089036355, 1312142911487502]), + y_minus_x: FieldElement([1996723311435669, 1844342766567060, 985455700466044, 1165924681400960, 311508689870129]), + xy2d: FieldElement([43173156290518, 2202883069785309, 1137787467085917, 1733636061944606, 1394992037553852]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([670078326344559, 555655025059356, 471959386282438, 2141455487356409, 849015953823125]), + y_minus_x: FieldElement([2197214573372804, 794254097241315, 1030190060513737, 267632515541902, 2040478049202624]), + xy2d: FieldElement([1812516004670529, 1609256702920783, 1706897079364493, 258549904773295, 996051247540686]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1540374301420584, 1764656898914615, 1810104162020396, 923808779163088, 664390074196579]), + y_minus_x: FieldElement([1323460699404750, 1262690757880991, 871777133477900, 1060078894988977, 1712236889662886]), + xy2d: FieldElement([1696163952057966, 1391710137550823, 608793846867416, 1034391509472039, 1780770894075012]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1367603834210841, 2131988646583224, 890353773628144, 1908908219165595, 270836895252891]), + y_minus_x: FieldElement([597536315471731, 40375058742586, 1942256403956049, 1185484645495932, 312666282024145]), + xy2d: FieldElement([1919411405316294, 1234508526402192, 1066863051997083, 1008444703737597, 1348810787701552]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([2102881477513865, 1570274565945361, 1573617900503708, 18662635732583, 2232324307922098]), + y_minus_x: FieldElement([1853931367696942, 8107973870707, 350214504129299, 775206934582587, 1752317649166792]), + xy2d: FieldElement([1417148368003523, 721357181628282, 505725498207811, 373232277872983, 261634707184480]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2186733281493267, 2250694917008620, 1014829812957440, 479998161452389, 83566193876474]), + y_minus_x: FieldElement([1268116367301224, 560157088142809, 802626839600444, 2210189936605713, 1129993785579988]), + xy2d: FieldElement([615183387352312, 917611676109240, 878893615973325, 978940963313282, 938686890583575]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([522024729211672, 1045059315315808, 1892245413707790, 1907891107684253, 2059998109500714]), + y_minus_x: FieldElement([1799679152208884, 912132775900387, 25967768040979, 432130448590461, 274568990261996]), + xy2d: FieldElement([98698809797682, 2144627600856209, 1907959298569602, 811491302610148, 1262481774981493]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1791451399743152, 1713538728337276, 118349997257490, 1882306388849954, 158235232210248]), + y_minus_x: FieldElement([1217809823321928, 2173947284933160, 1986927836272325, 1388114931125539, 12686131160169]), + xy2d: FieldElement([1650875518872272, 1136263858253897, 1732115601395988, 734312880662190, 1252904681142109]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([372986456113865, 525430915458171, 2116279931702135, 501422713587815, 1907002872974925]), + y_minus_x: FieldElement([803147181835288, 868941437997146, 316299302989663, 943495589630550, 571224287904572]), + xy2d: FieldElement([227742695588364, 1776969298667369, 628602552821802, 457210915378118, 2041906378111140]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([815000523470260, 913085688728307, 1052060118271173, 1345536665214223, 541623413135555]), + y_minus_x: FieldElement([1580216071604333, 1877997504342444, 857147161260913, 703522726778478, 2182763974211603]), + xy2d: FieldElement([1870080310923419, 71988220958492, 1783225432016732, 615915287105016, 1035570475990230]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([730987750830150, 857613889540280, 1083813157271766, 1002817255970169, 1719228484436074]), + y_minus_x: FieldElement([377616581647602, 1581980403078513, 804044118130621, 2034382823044191, 643844048472185]), + xy2d: FieldElement([176957326463017, 1573744060478586, 528642225008045, 1816109618372371, 1515140189765006]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1888911448245718, 1387110895611080, 1924503794066429, 1731539523700949, 2230378382645454]), + y_minus_x: FieldElement([443392177002051, 233793396845137, 2199506622312416, 1011858706515937, 974676837063129]), + xy2d: FieldElement([1846351103143623, 1949984838808427, 671247021915253, 1946756846184401, 1929296930380217]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([849646212452002, 1410198775302919, 73767886183695, 1641663456615812, 762256272452411]), + y_minus_x: FieldElement([692017667358279, 723305578826727, 1638042139863265, 748219305990306, 334589200523901]), + xy2d: FieldElement([22893968530686, 2235758574399251, 1661465835630252, 925707319443452, 1203475116966621]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([801299035785166, 1733292596726131, 1664508947088596, 467749120991922, 1647498584535623]), + y_minus_x: FieldElement([903105258014366, 427141894933047, 561187017169777, 1884330244401954, 1914145708422219]), + xy2d: FieldElement([1344191060517578, 1960935031767890, 1518838929955259, 1781502350597190, 1564784025565682]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([673723351748086, 1979969272514923, 1175287312495508, 1187589090978666, 1881897672213940]), + y_minus_x: FieldElement([1917185587363432, 1098342571752737, 5935801044414, 2000527662351839, 1538640296181569]), + xy2d: FieldElement([2495540013192, 678856913479236, 224998292422872, 219635787698590, 1972465269000940]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([271413961212179, 1353052061471651, 344711291283483, 2014925838520662, 2006221033113941]), + y_minus_x: FieldElement([194583029968109, 514316781467765, 829677956235672, 1676415686873082, 810104584395840]), + xy2d: FieldElement([1980510813313589, 1948645276483975, 152063780665900, 129968026417582, 256984195613935]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1860190562533102, 1936576191345085, 461100292705964, 1811043097042830, 957486749306835]), + y_minus_x: FieldElement([796664815624365, 1543160838872951, 1500897791837765, 1667315977988401, 599303877030711]), + xy2d: FieldElement([1151480509533204, 2136010406720455, 738796060240027, 319298003765044, 1150614464349587]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1731069268103150, 735642447616087, 1364750481334268, 417232839982871, 927108269127661]), + y_minus_x: FieldElement([1017222050227968, 1987716148359, 2234319589635701, 621282683093392, 2132553131763026]), + xy2d: FieldElement([1567828528453324, 1017807205202360, 565295260895298, 829541698429100, 307243822276582]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([249079270936248, 1501514259790706, 947909724204848, 944551802437487, 552658763982480]), + y_minus_x: FieldElement([2089966982947227, 1854140343916181, 2151980759220007, 2139781292261749, 158070445864917]), + xy2d: FieldElement([1338766321464554, 1906702607371284, 1519569445519894, 115384726262267, 1393058953390992]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1364621558265400, 1512388234908357, 1926731583198686, 2041482526432505, 920401122333774]), + y_minus_x: FieldElement([1884844597333588, 601480070269079, 620203503079537, 1079527400117915, 1202076693132015]), + xy2d: FieldElement([840922919763324, 727955812569642, 1303406629750194, 522898432152867, 294161410441865]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([353760790835310, 1598361541848743, 1122905698202299, 1922533590158905, 419107700666580]), + y_minus_x: FieldElement([359856369838236, 180914355488683, 861726472646627, 218807937262986, 575626773232501]), + xy2d: FieldElement([755467689082474, 909202735047934, 730078068932500, 936309075711518, 2007798262842972]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1609384177904073, 362745185608627, 1335318541768201, 800965770436248, 547877979267412]), + y_minus_x: FieldElement([984339177776787, 815727786505884, 1645154585713747, 1659074964378553, 1686601651984156]), + xy2d: FieldElement([1697863093781930, 599794399429786, 1104556219769607, 830560774794755, 12812858601017]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1168737550514982, 897832437380552, 463140296333799, 302564600022547, 2008360505135501]), + y_minus_x: FieldElement([1856930662813910, 678090852002597, 1920179140755167, 1259527833759868, 55540971895511]), + xy2d: FieldElement([1158643631044921, 476554103621892, 178447851439725, 1305025542653569, 103433927680625]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2176793111709008, 1576725716350391, 2009350167273523, 2012390194631546, 2125297410909580]), + y_minus_x: FieldElement([825403285195098, 2144208587560784, 1925552004644643, 1915177840006985, 1015952128947864]), + xy2d: FieldElement([1807108316634472, 1534392066433717, 347342975407218, 1153820745616376, 7375003497471]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([983061001799725, 431211889901241, 2201903782961093, 817393911064341, 2214616493042167]), + y_minus_x: FieldElement([228567918409756, 865093958780220, 358083886450556, 159617889659320, 1360637926292598]), + xy2d: FieldElement([234147501399755, 2229469128637390, 2175289352258889, 1397401514549353, 1885288963089922]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1111762412951562, 252849572507389, 1048714233823341, 146111095601446, 1237505378776770]), + y_minus_x: FieldElement([1113790697840279, 1051167139966244, 1045930658550944, 2011366241542643, 1686166824620755]), + xy2d: FieldElement([1054097349305049, 1872495070333352, 182121071220717, 1064378906787311, 100273572924182]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1306410853171605, 1627717417672447, 50983221088417, 1109249951172250, 870201789081392]), + y_minus_x: FieldElement([104233794644221, 1548919791188248, 2224541913267306, 2054909377116478, 1043803389015153]), + xy2d: FieldElement([216762189468802, 707284285441622, 190678557969733, 973969342604308, 1403009538434867]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1279024291038477, 344776835218310, 273722096017199, 1834200436811442, 634517197663804]), + y_minus_x: FieldElement([343805853118335, 1302216857414201, 566872543223541, 2051138939539004, 321428858384280]), + xy2d: FieldElement([470067171324852, 1618629234173951, 2000092177515639, 7307679772789, 1117521120249968]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([278151578291475, 1810282338562947, 1771599529530998, 1383659409671631, 685373414471841]), + y_minus_x: FieldElement([577009397403102, 1791440261786291, 2177643735971638, 174546149911960, 1412505077782326]), + xy2d: FieldElement([893719721537457, 1201282458018197, 1522349501711173, 58011597740583, 1130406465887139]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([412607348255453, 1280455764199780, 2233277987330768, 14180080401665, 331584698417165]), + y_minus_x: FieldElement([262483770854550, 990511055108216, 526885552771698, 571664396646158, 354086190278723]), + xy2d: FieldElement([1820352417585487, 24495617171480, 1547899057533253, 10041836186225, 480457105094042]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2023310314989233, 637905337525881, 2106474638900687, 557820711084072, 1687858215057826]), + y_minus_x: FieldElement([1144168702609745, 604444390410187, 1544541121756138, 1925315550126027, 626401428894002]), + xy2d: FieldElement([1922168257351784, 2018674099908659, 1776454117494445, 956539191509034, 36031129147635]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([544644538748041, 1039872944430374, 876750409130610, 710657711326551, 1216952687484972]), + y_minus_x: FieldElement([58242421545916, 2035812695641843, 2118491866122923, 1191684463816273, 46921517454099]), + xy2d: FieldElement([272268252444639, 1374166457774292, 2230115177009552, 1053149803909880, 1354288411641016]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1857910905368338, 1754729879288912, 885945464109877, 1516096106802166, 1602902393369811]), + y_minus_x: FieldElement([1193437069800958, 901107149704790, 999672920611411, 477584824802207, 364239578697845]), + xy2d: FieldElement([886299989548838, 1538292895758047, 1590564179491896, 1944527126709657, 837344427345298]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([754558365378305, 1712186480903618, 1703656826337531, 750310918489786, 518996040250900]), + y_minus_x: FieldElement([1309847803895382, 1462151862813074, 211370866671570, 1544595152703681, 1027691798954090]), + xy2d: FieldElement([803217563745370, 1884799722343599, 1357706345069218, 2244955901722095, 730869460037413]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([689299471295966, 1831210565161071, 1375187341585438, 1106284977546171, 1893781834054269]), + y_minus_x: FieldElement([696351368613042, 1494385251239250, 738037133616932, 636385507851544, 927483222611406]), + xy2d: FieldElement([1949114198209333, 1104419699537997, 783495707664463, 1747473107602770, 2002634765788641]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1607325776830197, 530883941415333, 1451089452727895, 1581691157083423, 496100432831154]), + y_minus_x: FieldElement([1068900648804224, 2006891997072550, 1134049269345549, 1638760646180091, 2055396084625778]), + xy2d: FieldElement([2222475519314561, 1870703901472013, 1884051508440561, 1344072275216753, 1318025677799069]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([155711679280656, 681100400509288, 389811735211209, 2135723811340709, 408733211204125]), + y_minus_x: FieldElement([7813206966729, 194444201427550, 2071405409526507, 1065605076176312, 1645486789731291]), + xy2d: FieldElement([16625790644959, 1647648827778410, 1579910185572704, 436452271048548, 121070048451050]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1037263028552531, 568385780377829, 297953104144430, 1558584511931211, 2238221839292471]), + y_minus_x: FieldElement([190565267697443, 672855706028058, 338796554369226, 337687268493904, 853246848691734]), + xy2d: FieldElement([1763863028400139, 766498079432444, 1321118624818005, 69494294452268, 858786744165651]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1292056768563024, 1456632109855638, 1100631247050184, 1386133165675321, 1232898350193752]), + y_minus_x: FieldElement([366253102478259, 525676242508811, 1449610995265438, 1183300845322183, 185960306491545]), + xy2d: FieldElement([28315355815982, 460422265558930, 1799675876678724, 1969256312504498, 1051823843138725]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([156914999361983, 1606148405719949, 1665208410108430, 317643278692271, 1383783705665320]), + y_minus_x: FieldElement([54684536365732, 2210010038536222, 1194984798155308, 535239027773705, 1516355079301361]), + xy2d: FieldElement([1484387703771650, 198537510937949, 2186282186359116, 617687444857508, 647477376402122]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2147715541830533, 500032538445817, 646380016884826, 352227855331122, 1488268620408052]), + y_minus_x: FieldElement([159386186465542, 1877626593362941, 618737197060512, 1026674284330807, 1158121760792685]), + xy2d: FieldElement([1744544377739822, 1964054180355661, 1685781755873170, 2169740670377448, 1286112621104591]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([81977249784993, 1667943117713086, 1668983819634866, 1605016835177615, 1353960708075544]), + y_minus_x: FieldElement([1602253788689063, 439542044889886, 2220348297664483, 657877410752869, 157451572512238]), + xy2d: FieldElement([1029287186166717, 65860128430192, 525298368814832, 1491902500801986, 1461064796385400]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([408216988729246, 2121095722306989, 913562102267595, 1879708920318308, 241061448436731]), + y_minus_x: FieldElement([1185483484383269, 1356339572588553, 584932367316448, 102132779946470, 1792922621116791]), + xy2d: FieldElement([1966196870701923, 2230044620318636, 1425982460745905, 261167817826569, 46517743394330]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([107077591595359, 884959942172345, 27306869797400, 2224911448949390, 964352058245223]), + y_minus_x: FieldElement([1730194207717538, 431790042319772, 1831515233279467, 1372080552768581, 1074513929381760]), + xy2d: FieldElement([1450880638731607, 1019861580989005, 1229729455116861, 1174945729836143, 826083146840706]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1899935429242705, 1602068751520477, 940583196550370, 82431069053859, 1540863155745696]), + y_minus_x: FieldElement([2136688454840028, 2099509000964294, 1690800495246475, 1217643678575476, 828720645084218]), + xy2d: FieldElement([765548025667841, 462473984016099, 998061409979798, 546353034089527, 2212508972466858]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([46575283771160, 892570971573071, 1281983193144090, 1491520128287375, 75847005908304]), + y_minus_x: FieldElement([1801436127943107, 1734436817907890, 1268728090345068, 167003097070711, 2233597765834956]), + xy2d: FieldElement([1997562060465113, 1048700225534011, 7615603985628, 1855310849546841, 2242557647635213]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1161017320376250, 492624580169043, 2169815802355237, 976496781732542, 1770879511019629]), + y_minus_x: FieldElement([1357044908364776, 729130645262438, 1762469072918979, 1365633616878458, 181282906404941]), + xy2d: FieldElement([1080413443139865, 1155205815510486, 1848782073549786, 622566975152580, 124965574467971]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1184526762066993, 247622751762817, 692129017206356, 820018689412496, 2188697339828085]), + y_minus_x: FieldElement([2020536369003019, 202261491735136, 1053169669150884, 2056531979272544, 778165514694311]), + xy2d: FieldElement([237404399610207, 1308324858405118, 1229680749538400, 720131409105291, 1958958863624906]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([515583508038846, 17656978857189, 1717918437373989, 1568052070792483, 46975803123923]), + y_minus_x: FieldElement([281527309158085, 36970532401524, 866906920877543, 2222282602952734, 1289598729589882]), + xy2d: FieldElement([1278207464902042, 494742455008756, 1262082121427081, 1577236621659884, 1888786707293291]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([353042527954210, 1830056151907359, 1111731275799225, 174960955838824, 404312815582675]), + y_minus_x: FieldElement([2064251142068628, 1666421603389706, 1419271365315441, 468767774902855, 191535130366583]), + xy2d: FieldElement([1716987058588002, 1859366439773457, 1767194234188234, 64476199777924, 1117233614485261]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([984292135520292, 135138246951259, 2220652137473167, 1722843421165029, 190482558012909]), + y_minus_x: FieldElement([298845952651262, 1166086588952562, 1179896526238434, 1347812759398693, 1412945390096208]), + xy2d: FieldElement([1143239552672925, 906436640714209, 2177000572812152, 2075299936108548, 325186347798433]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([721024854374772, 684487861263316, 1373438744094159, 2193186935276995, 1387043709851261]), + y_minus_x: FieldElement([418098668140962, 715065997721283, 1471916138376055, 2168570337288357, 937812682637044]), + xy2d: FieldElement([1043584187226485, 2143395746619356, 2209558562919611, 482427979307092, 847556718384018]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1248731221520759, 1465200936117687, 540803492710140, 52978634680892, 261434490176109]), + y_minus_x: FieldElement([1057329623869501, 620334067429122, 461700859268034, 2012481616501857, 297268569108938]), + xy2d: FieldElement([1055352180870759, 1553151421852298, 1510903185371259, 1470458349428097, 1226259419062731]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1492988790301668, 790326625573331, 1190107028409745, 1389394752159193, 1620408196604194]), + y_minus_x: FieldElement([47000654413729, 1004754424173864, 1868044813557703, 173236934059409, 588771199737015]), + xy2d: FieldElement([30498470091663, 1082245510489825, 576771653181956, 806509986132686, 1317634017056939]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([420308055751555, 1493354863316002, 165206721528088, 1884845694919786, 2065456951573059]), + y_minus_x: FieldElement([1115636332012334, 1854340990964155, 83792697369514, 1972177451994021, 457455116057587]), + xy2d: FieldElement([1698968457310898, 1435137169051090, 1083661677032510, 938363267483709, 340103887207182]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1995325341336574, 911500251774648, 164010755403692, 855378419194762, 1573601397528842]), + y_minus_x: FieldElement([241719380661528, 310028521317150, 1215881323380194, 1408214976493624, 2141142156467363]), + xy2d: FieldElement([1315157046163473, 727368447885818, 1363466668108618, 1668921439990361, 1398483384337907]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([75029678299646, 1015388206460473, 1849729037055212, 1939814616452984, 444404230394954]), + y_minus_x: FieldElement([2053597130993710, 2024431685856332, 2233550957004860, 2012407275509545, 872546993104440]), + xy2d: FieldElement([1217269667678610, 599909351968693, 1390077048548598, 1471879360694802, 739586172317596]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1718318639380794, 1560510726633958, 904462881159922, 1418028351780052, 94404349451937]), + y_minus_x: FieldElement([2132502667405250, 214379346175414, 1502748313768060, 1960071701057800, 1353971822643138]), + xy2d: FieldElement([319394212043702, 2127459436033571, 717646691535162, 663366796076914, 318459064945314]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([405989424923593, 1960452633787083, 667349034401665, 1492674260767112, 1451061489880787]), + y_minus_x: FieldElement([947085906234007, 323284730494107, 1485778563977200, 728576821512394, 901584347702286]), + xy2d: FieldElement([1575783124125742, 2126210792434375, 1569430791264065, 1402582372904727, 1891780248341114]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([838432205560695, 1997703511451664, 1018791879907867, 1662001808174331, 78328132957753]), + y_minus_x: FieldElement([739152638255629, 2074935399403557, 505483666745895, 1611883356514088, 628654635394878]), + xy2d: FieldElement([1822054032121349, 643057948186973, 7306757352712, 577249257962099, 284735863382083]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1366558556363930, 1448606567552086, 1478881020944768, 165803179355898, 1115718458123498]), + y_minus_x: FieldElement([204146226972102, 1630511199034723, 2215235214174763, 174665910283542, 956127674017216]), + xy2d: FieldElement([1562934578796716, 1070893489712745, 11324610642270, 958989751581897, 2172552325473805]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1770564423056027, 735523631664565, 1326060113795289, 1509650369341127, 65892421582684]), + y_minus_x: FieldElement([623682558650637, 1337866509471512, 990313350206649, 1314236615762469, 1164772974270275]), + xy2d: FieldElement([223256821462517, 723690150104139, 1000261663630601, 933280913953265, 254872671543046]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1969087237026041, 624795725447124, 1335555107635969, 2069986355593023, 1712100149341902]), + y_minus_x: FieldElement([1236103475266979, 1837885883267218, 1026072585230455, 1025865513954973, 1801964901432134]), + xy2d: FieldElement([1115241013365517, 1712251818829143, 2148864332502771, 2096001471438138, 2235017246626125]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1299268198601632, 2047148477845621, 2165648650132450, 1612539282026145, 514197911628890]), + y_minus_x: FieldElement([118352772338543, 1067608711804704, 1434796676193498, 1683240170548391, 230866769907437]), + xy2d: FieldElement([1850689576796636, 1601590730430274, 1139674615958142, 1954384401440257, 76039205311]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1723387471374172, 997301467038410, 533927635123657, 20928644693965, 1756575222802513]), + y_minus_x: FieldElement([2146711623855116, 503278928021499, 625853062251406, 1109121378393107, 1033853809911861]), + xy2d: FieldElement([571005965509422, 2005213373292546, 1016697270349626, 56607856974274, 914438579435146]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1346698876211176, 2076651707527589, 1084761571110205, 265334478828406, 1068954492309671]), + y_minus_x: FieldElement([1769967932677654, 1695893319756416, 1151863389675920, 1781042784397689, 400287774418285]), + xy2d: FieldElement([1851867764003121, 403841933237558, 820549523771987, 761292590207581, 1743735048551143]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([410915148140008, 2107072311871739, 1004367461876503, 99684895396761, 1180818713503224]), + y_minus_x: FieldElement([285945406881439, 648174397347453, 1098403762631981, 1366547441102991, 1505876883139217]), + xy2d: FieldElement([672095903120153, 1675918957959872, 636236529315028, 1569297300327696, 2164144194785875]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1902708175321798, 1035343530915438, 1178560808893263, 301095684058146, 1280977479761118]), + y_minus_x: FieldElement([1615357281742403, 404257611616381, 2160201349780978, 1160947379188955, 1578038619549541]), + xy2d: FieldElement([2013087639791217, 822734930507457, 1785668418619014, 1668650702946164, 389450875221715]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([453918449698368, 106406819929001, 2072540975937135, 308588860670238, 1304394580755385]), + y_minus_x: FieldElement([1295082798350326, 2091844511495996, 1851348972587817, 3375039684596, 789440738712837]), + xy2d: FieldElement([2083069137186154, 848523102004566, 993982213589257, 1405313299916317, 1532824818698468]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1495961298852430, 1397203457344779, 1774950217066942, 139302743555696, 66603584342787]), + y_minus_x: FieldElement([1782411379088302, 1096724939964781, 27593390721418, 542241850291353, 1540337798439873]), + xy2d: FieldElement([693543956581437, 171507720360750, 1557908942697227, 1074697073443438, 1104093109037196]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([345288228393419, 1099643569747172, 134881908403743, 1740551994106740, 248212179299770]), + y_minus_x: FieldElement([231429562203065, 1526290236421172, 2021375064026423, 1520954495658041, 806337791525116]), + xy2d: FieldElement([1079623667189886, 872403650198613, 766894200588288, 2163700860774109, 2023464507911816]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([854645372543796, 1936406001954827, 151460662541253, 825325739271555, 1554306377287556]), + y_minus_x: FieldElement([1497138821904622, 1044820250515590, 1742593886423484, 1237204112746837, 849047450816987]), + xy2d: FieldElement([667962773375330, 1897271816877105, 1399712621683474, 1143302161683099, 2081798441209593]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([127147851567005, 1936114012888110, 1704424366552046, 856674880716312, 716603621335359]), + y_minus_x: FieldElement([1072409664800960, 2146937497077528, 1508780108920651, 935767602384853, 1112800433544068]), + xy2d: FieldElement([333549023751292, 280219272863308, 2104176666454852, 1036466864875785, 536135186520207]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([373666279883137, 146457241530109, 304116267127857, 416088749147715, 1258577131183391]), + y_minus_x: FieldElement([1186115062588401, 2251609796968486, 1098944457878953, 1153112761201374, 1791625503417267]), + xy2d: FieldElement([1870078460219737, 2129630962183380, 852283639691142, 292865602592851, 401904317342226]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1361070124828035, 815664541425524, 1026798897364671, 1951790935390647, 555874891834790]), + y_minus_x: FieldElement([1546301003424277, 459094500062839, 1097668518375311, 1780297770129643, 720763293687608]), + xy2d: FieldElement([1212405311403990, 1536693382542438, 61028431067459, 1863929423417129, 1223219538638038]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1294303766540260, 1183557465955093, 882271357233093, 63854569425375, 2213283684565087]), + y_minus_x: FieldElement([339050984211414, 601386726509773, 413735232134068, 966191255137228, 1839475899458159]), + xy2d: FieldElement([235605972169408, 2174055643032978, 1538335001838863, 1281866796917192, 1815940222628465]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1632352921721536, 1833328609514701, 2092779091951987, 1923956201873226, 2210068022482919]), + y_minus_x: FieldElement([35271216625062, 1712350667021807, 983664255668860, 98571260373038, 1232645608559836]), + xy2d: FieldElement([1998172393429622, 1798947921427073, 784387737563581, 1589352214827263, 1589861734168180]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1733739258725305, 31715717059538, 201969945218860, 992093044556990, 1194308773174556]), + y_minus_x: FieldElement([846415389605137, 746163495539180, 829658752826080, 592067705956946, 957242537821393]), + xy2d: FieldElement([1758148849754419, 619249044817679, 168089007997045, 1371497636330523, 1867101418880350]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([326633984209635, 261759506071016, 1700682323676193, 1577907266349064, 1217647663383016]), + y_minus_x: FieldElement([1714182387328607, 1477856482074168, 574895689942184, 2159118410227270, 1555532449716575]), + xy2d: FieldElement([853828206885131, 998498946036955, 1835887550391235, 207627336608048, 258363815956050]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([141141474651677, 1236728744905256, 643101419899887, 1646615130509173, 1208239602291765]), + y_minus_x: FieldElement([1501663228068911, 1354879465566912, 1444432675498247, 897812463852601, 855062598754348]), + xy2d: FieldElement([714380763546606, 1032824444965790, 1774073483745338, 1063840874947367, 1738680636537158]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1640635546696252, 633168953192112, 2212651044092396, 30590958583852, 368515260889378]), + y_minus_x: FieldElement([1171650314802029, 1567085444565577, 1453660792008405, 757914533009261, 1619511342778196]), + xy2d: FieldElement([420958967093237, 971103481109486, 2169549185607107, 1301191633558497, 1661514101014240]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([907123651818302, 1332556122804146, 1824055253424487, 1367614217442959, 1982558335973172]), + y_minus_x: FieldElement([1121533090144639, 1021251337022187, 110469995947421, 1511059774758394, 2110035908131662]), + xy2d: FieldElement([303213233384524, 2061932261128138, 352862124777736, 40828818670255, 249879468482660]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([856559257852200, 508517664949010, 1378193767894916, 1723459126947129, 1962275756614521]), + y_minus_x: FieldElement([1445691340537320, 40614383122127, 402104303144865, 485134269878232, 1659439323587426]), + xy2d: FieldElement([20057458979482, 1183363722525800, 2140003847237215, 2053873950687614, 2112017736174909]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2228654250927986, 1483591363415267, 1368661293910956, 1076511285177291, 526650682059608]), + y_minus_x: FieldElement([709481497028540, 531682216165724, 316963769431931, 1814315888453765, 258560242424104]), + xy2d: FieldElement([1053447823660455, 1955135194248683, 1010900954918985, 1182614026976701, 1240051576966610]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1957943897155497, 1788667368028035, 137692910029106, 1039519607062, 826404763313028]), + y_minus_x: FieldElement([1848942433095597, 1582009882530495, 1849292741020143, 1068498323302788, 2001402229799484]), + xy2d: FieldElement([1528282417624269, 2142492439828191, 2179662545816034, 362568973150328, 1591374675250271]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([160026679434388, 232341189218716, 2149181472355545, 598041771119831, 183859001910173]), + y_minus_x: FieldElement([2013278155187349, 662660471354454, 793981225706267, 411706605985744, 804490933124791]), + xy2d: FieldElement([2051892037280204, 488391251096321, 2230187337030708, 930221970662692, 679002758255210]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1530723630438670, 875873929577927, 341560134269988, 449903119530753, 1055551308214179]), + y_minus_x: FieldElement([1461835919309432, 1955256480136428, 180866187813063, 1551979252664528, 557743861963950]), + xy2d: FieldElement([359179641731115, 1324915145732949, 902828372691474, 294254275669987, 1887036027752957]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2043271609454323, 2038225437857464, 1317528426475850, 1398989128982787, 2027639881006861]), + y_minus_x: FieldElement([2072902725256516, 312132452743412, 309930885642209, 996244312618453, 1590501300352303]), + xy2d: FieldElement([1397254305160710, 695734355138021, 2233992044438756, 1776180593969996, 1085588199351115]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([440567051331029, 254894786356681, 493869224930222, 1556322069683366, 1567456540319218]), + y_minus_x: FieldElement([1950722461391320, 1907845598854797, 1822757481635527, 2121567704750244, 73811931471221]), + xy2d: FieldElement([387139307395758, 2058036430315676, 1220915649965325, 1794832055328951, 1230009312169328]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1765973779329517, 659344059446977, 19821901606666, 1301928341311214, 1116266004075885]), + y_minus_x: FieldElement([1127572801181483, 1224743760571696, 1276219889847274, 1529738721702581, 1589819666871853]), + xy2d: FieldElement([2181229378964934, 2190885205260020, 1511536077659137, 1246504208580490, 668883326494241]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([437866655573314, 669026411194768, 81896997980338, 523874406393178, 245052060935236]), + y_minus_x: FieldElement([1975438052228868, 1071801519999806, 594652299224319, 1877697652668809, 1489635366987285]), + xy2d: FieldElement([958592545673770, 233048016518599, 851568750216589, 567703851596087, 1740300006094761]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2014540178270324, 192672779514432, 213877182641530, 2194819933853411, 1716422829364835]), + y_minus_x: FieldElement([1540769606609725, 2148289943846077, 1597804156127445, 1230603716683868, 815423458809453]), + xy2d: FieldElement([1738560251245018, 1779576754536888, 1783765347671392, 1880170990446751, 1088225159617541]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([659303913929492, 1956447718227573, 1830568515922666, 841069049744408, 1669607124206368]), + y_minus_x: FieldElement([1143465490433355, 1532194726196059, 1093276745494697, 481041706116088, 2121405433561163]), + xy2d: FieldElement([1686424298744462, 1451806974487153, 266296068846582, 1834686947542675, 1720762336132256]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([889217026388959, 1043290623284660, 856125087551909, 1669272323124636, 1603340330827879]), + y_minus_x: FieldElement([1206396181488998, 333158148435054, 1402633492821422, 1120091191722026, 1945474114550509]), + xy2d: FieldElement([766720088232571, 1512222781191002, 1189719893490790, 2091302129467914, 2141418006894941]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([419663647306612, 1998875112167987, 1426599870253707, 1154928355379510, 486538532138187]), + y_minus_x: FieldElement([938160078005954, 1421776319053174, 1941643234741774, 180002183320818, 1414380336750546]), + xy2d: FieldElement([398001940109652, 1577721237663248, 1012748649830402, 1540516006905144, 1011684812884559]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1653276489969630, 6081825167624, 1921777941170836, 1604139841794531, 861211053640641]), + y_minus_x: FieldElement([996661541407379, 1455877387952927, 744312806857277, 139213896196746, 1000282908547789]), + xy2d: FieldElement([1450817495603008, 1476865707053229, 1030490562252053, 620966950353376, 1744760161539058]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([559728410002599, 37056661641185, 2038622963352006, 1637244893271723, 1026565352238948]), + y_minus_x: FieldElement([962165956135846, 1116599660248791, 182090178006815, 1455605467021751, 196053588803284]), + xy2d: FieldElement([796863823080135, 1897365583584155, 420466939481601, 2165972651724672, 932177357788289]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([877047233620632, 1375632631944375, 643773611882121, 660022738847877, 19353932331831]), + y_minus_x: FieldElement([2216943882299338, 394841323190322, 2222656898319671, 558186553950529, 1077236877025190]), + xy2d: FieldElement([801118384953213, 1914330175515892, 574541023311511, 1471123787903705, 1526158900256288]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([949617889087234, 2207116611267331, 912920039141287, 501158539198789, 62362560771472]), + y_minus_x: FieldElement([1474518386765335, 1760793622169197, 1157399790472736, 1622864308058898, 165428294422792]), + xy2d: FieldElement([1961673048027128, 102619413083113, 1051982726768458, 1603657989805485, 1941613251499678]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1401939116319266, 335306339903072, 72046196085786, 862423201496006, 850518754531384]), + y_minus_x: FieldElement([1234706593321979, 1083343891215917, 898273974314935, 1640859118399498, 157578398571149]), + xy2d: FieldElement([1143483057726416, 1992614991758919, 674268662140796, 1773370048077526, 674318359920189]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1835401379538542, 173900035308392, 818247630716732, 1762100412152786, 1021506399448291]), + y_minus_x: FieldElement([1506632088156630, 2127481795522179, 513812919490255, 140643715928370, 442476620300318]), + xy2d: FieldElement([2056683376856736, 219094741662735, 2193541883188309, 1841182310235800, 556477468664293]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1315019427910827, 1049075855992603, 2066573052986543, 266904467185534, 2040482348591520]), + y_minus_x: FieldElement([94096246544434, 922482381166992, 24517828745563, 2139430508542503, 2097139044231004]), + xy2d: FieldElement([537697207950515, 1399352016347350, 1563663552106345, 2148749520888918, 549922092988516]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1747985413252434, 680511052635695, 1809559829982725, 594274250930054, 201673170745982]), + y_minus_x: FieldElement([323583936109569, 1973572998577657, 1192219029966558, 79354804385273, 1374043025560347]), + xy2d: FieldElement([213277331329947, 416202017849623, 1950535221091783, 1313441578103244, 2171386783823658]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([189088804229831, 993969372859110, 895870121536987, 1547301535298256, 1477373024911350]), + y_minus_x: FieldElement([1620578418245010, 541035331188469, 2235785724453865, 2154865809088198, 1974627268751826]), + xy2d: FieldElement([1346805451740245, 1350981335690626, 942744349501813, 2155094562545502, 1012483751693409]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2107080134091762, 1132567062788208, 1824935377687210, 769194804343737, 1857941799971888]), + y_minus_x: FieldElement([1074666112436467, 249279386739593, 1174337926625354, 1559013532006480, 1472287775519121]), + xy2d: FieldElement([1872620123779532, 1892932666768992, 1921559078394978, 1270573311796160, 1438913646755037]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([837390187648199, 1012253300223599, 989780015893987, 1351393287739814, 328627746545550]), + y_minus_x: FieldElement([1028328827183114, 1711043289969857, 1350832470374933, 1923164689604327, 1495656368846911]), + xy2d: FieldElement([1900828492104143, 430212361082163, 687437570852799, 832514536673512, 1685641495940794]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([842632847936398, 605670026766216, 290836444839585, 163210774892356, 2213815011799645]), + y_minus_x: FieldElement([1176336383453996, 1725477294339771, 12700622672454, 678015708818208, 162724078519879]), + xy2d: FieldElement([1448049969043497, 1789411762943521, 385587766217753, 90201620913498, 832999441066823]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([516086333293313, 2240508292484616, 1351669528166508, 1223255565316488, 750235824427138]), + y_minus_x: FieldElement([1263624896582495, 1102602401673328, 526302183714372, 2152015839128799, 1483839308490010]), + xy2d: FieldElement([442991718646863, 1599275157036458, 1925389027579192, 899514691371390, 350263251085160]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([1689713572022143, 593854559254373, 978095044791970, 1985127338729499, 1676069120347625]), + y_minus_x: FieldElement([1557207018622683, 340631692799603, 1477725909476187, 614735951619419, 2033237123746766]), + xy2d: FieldElement([968764929340557, 1225534776710944, 662967304013036, 1155521416178595, 791142883466590]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1487081286167458, 993039441814934, 1792378982844640, 698652444999874, 2153908693179754]), + y_minus_x: FieldElement([1123181311102823, 685575944875442, 507605465509927, 1412590462117473, 568017325228626]), + xy2d: FieldElement([560258797465417, 2193971151466401, 1824086900849026, 579056363542056, 1690063960036441]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1918407319222416, 353767553059963, 1930426334528099, 1564816146005724, 1861342381708096]), + y_minus_x: FieldElement([2131325168777276, 1176636658428908, 1756922641512981, 1390243617176012, 1966325177038383]), + xy2d: FieldElement([2063958120364491, 2140267332393533, 699896251574968, 273268351312140, 375580724713232]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2024297515263178, 416959329722687, 1079014235017302, 171612225573183, 1031677520051053]), + y_minus_x: FieldElement([2033900009388450, 1744902869870788, 2190580087917640, 1949474984254121, 231049754293748]), + xy2d: FieldElement([343868674606581, 550155864008088, 1450580864229630, 481603765195050, 896972360018042]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2151139328380127, 314745882084928, 59756825775204, 1676664391494651, 2048348075599360]), + y_minus_x: FieldElement([1528930066340597, 1605003907059576, 1055061081337675, 1458319101947665, 1234195845213142]), + xy2d: FieldElement([830430507734812, 1780282976102377, 1425386760709037, 362399353095425, 2168861579799910]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1155762232730333, 980662895504006, 2053766700883521, 490966214077606, 510405877041357]), + y_minus_x: FieldElement([1683750316716132, 652278688286128, 1221798761193539, 1897360681476669, 319658166027343]), + xy2d: FieldElement([618808732869972, 72755186759744, 2060379135624181, 1730731526741822, 48862757828238]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1463171970593505, 1143040711767452, 614590986558883, 1409210575145591, 1882816996436803]), + y_minus_x: FieldElement([2230133264691131, 563950955091024, 2042915975426398, 827314356293472, 672028980152815]), + xy2d: FieldElement([264204366029760, 1654686424479449, 2185050199932931, 2207056159091748, 506015669043634]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1784446333136569, 1973746527984364, 334856327359575, 1156769775884610, 1023950124675478]), + y_minus_x: FieldElement([2065270940578383, 31477096270353, 306421879113491, 181958643936686, 1907105536686083]), + xy2d: FieldElement([1496516440779464, 1748485652986458, 872778352227340, 818358834654919, 97932669284220]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([471636015770351, 672455402793577, 1804995246884103, 1842309243470804, 1501862504981682]), + y_minus_x: FieldElement([1013216974933691, 538921919682598, 1915776722521558, 1742822441583877, 1886550687916656]), + xy2d: FieldElement([2094270000643336, 303971879192276, 40801275554748, 649448917027930, 1818544418535447]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2241737709499165, 549397817447461, 838180519319392, 1725686958520781, 1705639080897747]), + y_minus_x: FieldElement([1216074541925116, 50120933933509, 1565829004133810, 721728156134580, 349206064666188]), + xy2d: FieldElement([948617110470858, 346222547451945, 1126511960599975, 1759386906004538, 493053284802266]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1454933046815146, 874696014266362, 1467170975468588, 1432316382418897, 2111710746366763]), + y_minus_x: FieldElement([2105387117364450, 1996463405126433, 1303008614294500, 851908115948209, 1353742049788635]), + xy2d: FieldElement([750300956351719, 1487736556065813, 15158817002104, 1511998221598392, 971739901354129]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1874648163531693, 2124487685930551, 1810030029384882, 918400043048335, 586348627300650]), + y_minus_x: FieldElement([1235084464747900, 1166111146432082, 1745394857881591, 1405516473883040, 4463504151617]), + xy2d: FieldElement([1663810156463827, 327797390285791, 1341846161759410, 1964121122800605, 1747470312055380]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([660005247548233, 2071860029952887, 1358748199950107, 911703252219107, 1014379923023831]), + y_minus_x: FieldElement([2206641276178231, 1690587809721504, 1600173622825126, 2156096097634421, 1106822408548216]), + xy2d: FieldElement([1344788193552206, 1949552134239140, 1735915881729557, 675891104100469, 1834220014427292]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1920949492387964, 158885288387530, 70308263664033, 626038464897817, 1468081726101009]), + y_minus_x: FieldElement([622221042073383, 1210146474039168, 1742246422343683, 1403839361379025, 417189490895736]), + xy2d: FieldElement([22727256592983, 168471543384997, 1324340989803650, 1839310709638189, 504999476432775]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1313240518756327, 1721896294296942, 52263574587266, 2065069734239232, 804910473424630]), + y_minus_x: FieldElement([1337466662091884, 1287645354669772, 2018019646776184, 652181229374245, 898011753211715]), + xy2d: FieldElement([1969792547910734, 779969968247557, 2011350094423418, 1823964252907487, 1058949448296945]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([207343737062002, 1118176942430253, 758894594548164, 806764629546266, 1157700123092949]), + y_minus_x: FieldElement([1273565321399022, 1638509681964574, 759235866488935, 666015124346707, 897983460943405]), + xy2d: FieldElement([1717263794012298, 1059601762860786, 1837819172257618, 1054130665797229, 680893204263559]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([2237039662793603, 2249022333361206, 2058613546633703, 149454094845279, 2215176649164582]), + y_minus_x: FieldElement([79472182719605, 1851130257050174, 1825744808933107, 821667333481068, 781795293511946]), + xy2d: FieldElement([755822026485370, 152464789723500, 1178207602290608, 410307889503239, 156581253571278]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1418185496130297, 484520167728613, 1646737281442950, 1401487684670265, 1349185550126961]), + y_minus_x: FieldElement([1495380034400429, 325049476417173, 46346894893933, 1553408840354856, 828980101835683]), + xy2d: FieldElement([1280337889310282, 2070832742866672, 1640940617225222, 2098284908289951, 450929509534434]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([407703353998781, 126572141483652, 286039827513621, 1999255076709338, 2030511179441770]), + y_minus_x: FieldElement([1254958221100483, 1153235960999843, 942907704968834, 637105404087392, 1149293270147267]), + xy2d: FieldElement([894249020470196, 400291701616810, 406878712230981, 1599128793487393, 1145868722604026]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1497955250203334, 110116344653260, 1128535642171976, 1900106496009660, 129792717460909]), + y_minus_x: FieldElement([452487513298665, 1352120549024569, 1173495883910956, 1999111705922009, 367328130454226]), + xy2d: FieldElement([1717539401269642, 1475188995688487, 891921989653942, 836824441505699, 1885988485608364]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1241784121422547, 187337051947583, 1118481812236193, 428747751936362, 30358898927325]), + y_minus_x: FieldElement([2022432361201842, 1088816090685051, 1977843398539868, 1854834215890724, 564238862029357]), + xy2d: FieldElement([938868489100585, 1100285072929025, 1017806255688848, 1957262154788833, 152787950560442]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([867319417678923, 620471962942542, 226032203305716, 342001443957629, 1761675818237336]), + y_minus_x: FieldElement([1295072362439987, 931227904689414, 1355731432641687, 922235735834035, 892227229410209]), + xy2d: FieldElement([1680989767906154, 535362787031440, 2136691276706570, 1942228485381244, 1267350086882274]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([366018233770527, 432660629755596, 126409707644535, 1973842949591662, 645627343442376]), + y_minus_x: FieldElement([535509430575217, 546885533737322, 1524675609547799, 2138095752851703, 1260738089896827]), + xy2d: FieldElement([1159906385590467, 2198530004321610, 714559485023225, 81880727882151, 1484020820037082]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1377485731340769, 2046328105512000, 1802058637158797, 62146136768173, 1356993908853901]), + y_minus_x: FieldElement([2013612215646735, 1830770575920375, 536135310219832, 609272325580394, 270684344495013]), + xy2d: FieldElement([1237542585982777, 2228682050256790, 1385281931622824, 593183794882890, 493654978552689]), + }, + ] + , + [ + AffineNielsPoint { + y_plus_x: FieldElement([47341488007760, 1891414891220257, 983894663308928, 176161768286818, 1126261115179708]), + y_minus_x: FieldElement([1694030170963455, 502038567066200, 1691160065225467, 949628319562187, 275110186693066]), + xy2d: FieldElement([1124515748676336, 1661673816593408, 1499640319059718, 1584929449166988, 558148594103306]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1784525599998356, 1619698033617383, 2097300287550715, 258265458103756, 1905684794832758]), + y_minus_x: FieldElement([1288941072872766, 931787902039402, 190731008859042, 2006859954667190, 1005931482221702]), + xy2d: FieldElement([1465551264822703, 152905080555927, 680334307368453, 173227184634745, 666407097159852]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2111017076203943, 1378760485794347, 1248583954016456, 1352289194864422, 1895180776543896]), + y_minus_x: FieldElement([171348223915638, 662766099800389, 462338943760497, 466917763340314, 656911292869115]), + xy2d: FieldElement([488623681976577, 866497561541722, 1708105560937768, 1673781214218839, 1506146329818807]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([160425464456957, 950394373239689, 430497123340934, 711676555398832, 320964687779005]), + y_minus_x: FieldElement([988979367990485, 1359729327576302, 1301834257246029, 294141160829308, 29348272277475]), + xy2d: FieldElement([1434382743317910, 100082049942065, 221102347892623, 186982837860588, 1305765053501834]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([2205916462268190, 499863829790820, 961960554686616, 158062762756985, 1841471168298305]), + y_minus_x: FieldElement([1191737341426592, 1847042034978363, 1382213545049056, 1039952395710448, 788812858896859]), + xy2d: FieldElement([1346965964571152, 1291881610839830, 2142916164336056, 786821641205979, 1571709146321039]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([787164375951248, 202869205373189, 1356590421032140, 1431233331032510, 786341368775957]), + y_minus_x: FieldElement([492448143532951, 304105152670757, 1761767168301056, 233782684697790, 1981295323106089]), + xy2d: FieldElement([665807507761866, 1343384868355425, 895831046139653, 439338948736892, 1986828765695105]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([756096210874553, 1721699973539149, 258765301727885, 1390588532210645, 1212530909934781]), + y_minus_x: FieldElement([852891097972275, 1816988871354562, 1543772755726524, 1174710635522444, 202129090724628]), + xy2d: FieldElement([1205281565824323, 22430498399418, 992947814485516, 1392458699738672, 688441466734558]), + }, + AffineNielsPoint { + y_plus_x: FieldElement([1050627428414972, 1955849529137135, 2171162376368357, 91745868298214, 447733118757826]), + y_minus_x: FieldElement([1287181461435438, 622722465530711, 880952150571872, 741035693459198, 311565274989772]), + xy2d: FieldElement([1003649078149734, 545233927396469, 1849786171789880, 1318943684880434, 280345687170552]), + }, + ] +]); #[cfg(test)] mod test { From 3eab4acbd8d3fb2fea1be36af154f84b0f4a0b61 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:31 -0700 Subject: [PATCH 063/101] Add p constant for subtraction --- src/constants.rs | 3 +++ src/field.rs | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 1dd931f..487d557 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -26,6 +26,9 @@ use curve::CompressedEdwardsY; use curve::EdwardsBasepointTable; use scalar::Scalar; +#[cfg(feature="radix_51")] +pub const p: FieldElement = FieldElement([2251799813685229, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]); + #[cfg(feature="radix_25_5")] pub const d: FieldElement = FieldElement([ -10913610, 13857413, -15372611, 6949391, 114729, diff --git a/src/field.rs b/src/field.rs index b2bde0c..8b448c9 100644 --- a/src/field.rs +++ b/src/field.rs @@ -244,11 +244,11 @@ impl<'b> SubAssign<&'b FieldElement> for FieldElement { fn sub_assign(&mut self, _rhs: &'b FieldElement) { // To avoid underflow, first add p // XXX how many copies should we add to preserve headroom? - self.0[0] += 2251799813685229; - self.0[1] += 2251799813685247; - self.0[2] += 2251799813685247; - self.0[3] += 2251799813685247; - self.0[4] += 2251799813685247; + self.0[0] += constants::p.0[0]; + self.0[1] += constants::p.0[1]; + self.0[2] += constants::p.0[2]; + self.0[3] += constants::p.0[3]; + self.0[4] += constants::p.0[4]; // then subtract _rhs self.0[0] -= _rhs.0[0]; self.0[1] -= _rhs.0[1]; @@ -338,6 +338,15 @@ impl FieldElement { self[i] = -self[i]; } } + #[cfg(feature="radix_51")] + pub fn negate(&mut self) { + // XXX how many copies of p + self.0[0] = constants::p.0[0] - self.0[0]; + self.0[1] = constants::p.0[1] - self.0[1]; + self.0[2] = constants::p.0[2] - self.0[2]; + self.0[3] = constants::p.0[3] - self.0[3]; + self.0[4] = constants::p.0[4] - self.0[4]; + } /// Construct the additive identity #[cfg(feature="radix_25_5")] From f16f5d1e739b4759b4073df21deeb0df3ebb3039 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:33 -0700 Subject: [PATCH 064/101] Add minus_one for radix51 --- src/field.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/field.rs b/src/field.rs index 8b448c9..0933d5c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -373,6 +373,10 @@ impl FieldElement { pub fn minus_one() -> FieldElement { FieldElement([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + #[cfg(feature="radix_51")] + pub fn minus_one() -> FieldElement { + FieldElement([2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]) + } #[cfg(feature="radix_25_5")] fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine From 7f8b3fe594bbb46d529680aaf6e5ea12a689bcc0 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:34 -0700 Subject: [PATCH 065/101] Rename combine_coeffs to reduce --- src/field.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/field.rs b/src/field.rs index 0933d5c..22a9b97 100644 --- a/src/field.rs +++ b/src/field.rs @@ -379,7 +379,7 @@ impl FieldElement { } #[cfg(feature="radix_25_5")] - fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine + fn reduce(input: &[i64;10]) -> FieldElement { //FeCombine let mut c = [0i64;10]; let mut h = input.clone(); @@ -505,7 +505,7 @@ impl FieldElement { h[8] = load3(&data[26..]) << 4; h[9] = (load3(&data[29..]) & 8388607) << 2; - FieldElement::combine_coeffs(&h) + FieldElement::reduce(&h) } /// Marshal this FieldElement into a 32-byte array. @@ -828,7 +828,7 @@ impl FieldElement { let h8 = f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19; let h9 = f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0; - FieldElement::combine_coeffs(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) + FieldElement::reduce(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) } #[cfg(feature="radix_25_5")] @@ -885,7 +885,7 @@ impl FieldElement { /// * |h[i]| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. #[cfg(feature="radix_25_5")] pub fn square(&self) -> FieldElement { - FieldElement::combine_coeffs(&self.square_inner()) + FieldElement::reduce(&self.square_inner()) } /// Square this field element and multiply the result by 2. @@ -910,7 +910,7 @@ impl FieldElement { for i in 0..self.0.len() { coeffs[i] += coeffs[i]; } - FieldElement::combine_coeffs(&coeffs) + FieldElement::reduce(&coeffs) } #[inline] From 08ac5a906859018aac377ac077a1f2fd1b934d83 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:35 -0700 Subject: [PATCH 066/101] Add radix51 impl of from_bytes --- src/field.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/field.rs b/src/field.rs index 22a9b97..a4e3832 100644 --- a/src/field.rs +++ b/src/field.rs @@ -75,21 +75,6 @@ pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { [c0,c1,c2,c3,c4] } -fn from_bytes_64(bytes: &[u8;32]) -> [u64; 5] { - let low_51_bit_mask = (1u64 << 51) - 1; - // load bits [ 0, 64), no shift - [ load8(&bytes[ 0..]) & low_51_bit_mask - // load bits [ 48,112), shift to [ 51,112) - , (load8(&bytes[ 6..]) >> 3) & low_51_bit_mask - // load bits [ 96,160), shift to [102,160) - , (load8(&bytes[12..]) >> 6) & low_51_bit_mask - // load bits [152,216), shift to [153,216) - , (load8(&bytes[19..]) >> 1) & low_51_bit_mask - // load bits [192,256), shift to [204,112) - , (load8(&bytes[24..]) >> 12) & low_51_bit_mask - ] -} - fn to_bytes_64(limbs: &[u64;5]) -> [u8;32] { let mut s = [0u8;32]; s[ 0] = limbs[0] as u8; @@ -507,6 +492,22 @@ impl FieldElement { FieldElement::reduce(&h) } + #[cfg(feature="radix_51")] + pub fn from_bytes(bytes: &[u8;32]) -> FieldElement { + let low_51_bit_mask = (1u64 << 51) - 1; + FieldElement( + // load bits [ 0, 64), no shift + [ load8(&bytes[ 0..]) & low_51_bit_mask + // load bits [ 48,112), shift to [ 51,112) + , (load8(&bytes[ 6..]) >> 3) & low_51_bit_mask + // load bits [ 96,160), shift to [102,160) + , (load8(&bytes[12..]) >> 6) & low_51_bit_mask + // load bits [152,216), shift to [153,216) + , (load8(&bytes[19..]) >> 1) & low_51_bit_mask + // load bits [192,256), shift to [204,112) + , (load8(&bytes[24..]) >> 12) & low_51_bit_mask + ]) + } /// Marshal this FieldElement into a 32-byte array. /// From 7591c740183a2212477edd17a848fdef0e276949 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:36 -0700 Subject: [PATCH 067/101] Add radix51 impl of reduce --- src/field.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/field.rs b/src/field.rs index a4e3832..37d7ba5 100644 --- a/src/field.rs +++ b/src/field.rs @@ -455,6 +455,40 @@ impl FieldElement { output[9] = h[9] as i32; output } + #[cfg(feature="radix_51")] + fn reduce(input: &[u128; 5]) -> FieldElement { + // After multiplication, + // c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) + // where b is the bitlength of the input limbs. + + // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. + // After the first carry pass, all c[i] fit into u64. + + let low_51_bit_mask = (1u64 << 51) - 1; + c1 += (c0 >> 51) as u128; + let mut c0: u64 = (c0 as u64) & low_51_bit_mask; + c2 += (c1 >> 51) as u128; + let mut c1: u64 = (c1 as u64) & low_51_bit_mask; + c3 += (c2 >> 51) as u128; + let mut c2: u64 = (c2 as u64) & low_51_bit_mask; + c4 += (c3 >> 51) as u128; + let mut c3: u64 = (c3 as u64) & low_51_bit_mask; + c0 += ((c4 >> 51) as u64) * 19; + let mut c4: u64 = (c4 as u64) & low_51_bit_mask; + + c1 += c0 >> 51; + c0 = c0 & low_51_bit_mask; + c2 += c1 >> 51; + c1 = c1 & low_51_bit_mask; + c3 += c2 >> 51; + c2 = c2 & low_51_bit_mask; + c4 += c3 >> 51; + c3 = c3 & low_51_bit_mask; + c0 += (c4 >> 51) * 19; + c4 = c4 & low_51_bit_mask; + + FieldElement([c0,c1,c2,c3,c4]) + } /// Create a FieldElement by demarshalling an array of 32 bytes. /// From b515e43dfd09b8efce0a44da755fded662ac331b Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:37 -0700 Subject: [PATCH 068/101] Move to_bytes_64 to to_bytes for radix51 --- src/field.rs | 84 +++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/src/field.rs b/src/field.rs index 37d7ba5..e0fbbe3 100644 --- a/src/field.rs +++ b/src/field.rs @@ -75,46 +75,6 @@ pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { [c0,c1,c2,c3,c4] } -fn to_bytes_64(limbs: &[u64;5]) -> [u8;32] { - let mut s = [0u8;32]; - s[ 0] = limbs[0] as u8; - s[ 1] = (limbs[0] >> 8) as u8; - s[ 2] = (limbs[0] >> 16) as u8; - s[ 3] = (limbs[0] >> 24) as u8; - s[ 4] = (limbs[0] >> 32) as u8; - s[ 5] = (limbs[0] >> 40) as u8; - s[ 6] = ((limbs[0] >> 48) | (limbs[1] << 3)) as u8; - s[ 7] = (limbs[1] >> 5) as u8; - s[ 8] = (limbs[1] >> 13) as u8; - s[ 9] = (limbs[1] >> 21) as u8; - s[10] = (limbs[1] >> 29) as u8; - s[11] = (limbs[1] >> 37) as u8; - s[12] = ((limbs[1] >> 45) | (limbs[2] << 6)) as u8; - s[13] = (limbs[2] >> 2) as u8; - s[14] = (limbs[2] >> 10) as u8; - s[15] = (limbs[2] >> 18) as u8; - s[16] = (limbs[2] >> 26) as u8; - s[17] = (limbs[2] >> 34) as u8; - s[18] = (limbs[2] >> 42) as u8; - s[19] = ((limbs[2] >> 50) | (limbs[3] << 1)) as u8; - s[20] = (limbs[3] >> 7) as u8; - s[21] = (limbs[3] >> 15) as u8; - s[22] = (limbs[3] >> 23) as u8; - s[23] = (limbs[3] >> 31) as u8; - s[24] = (limbs[3] >> 39) as u8; - s[25] = ((limbs[3] >> 47) | (limbs[4] << 4)) as u8; - s[26] = (limbs[4] >> 4) as u8; - s[27] = (limbs[4] >> 12) as u8; - s[28] = (limbs[4] >> 20) as u8; - s[29] = (limbs[4] >> 28) as u8; - s[30] = (limbs[4] >> 36) as u8; - s[31] = (limbs[4] >> 44) as u8; - - //Clear high bit - s[31] &= 127u8; - - return s -} /// With the `radix51` feature enabled, `FieldElements` are represented /// in radix 2^51 as five `u64`s. @@ -685,10 +645,54 @@ impl FieldElement { s[31] = (h[9] >> 18) as u8; //Clear high bit + debug_assert!((s[31] & 0b1000_0000u8) == 0u8); s[31] &= 127u8; s } + #[cfg(feature="radix_51")] + pub fn to_bytes(&self) -> [u8;32] { + // XXX need to do reduction first + let mut s = [0u8;32]; + s[ 0] = self.0[0] as u8; + s[ 1] = (self.0[0] >> 8) as u8; + s[ 2] = (self.0[0] >> 16) as u8; + s[ 3] = (self.0[0] >> 24) as u8; + s[ 4] = (self.0[0] >> 32) as u8; + s[ 5] = (self.0[0] >> 40) as u8; + s[ 6] = ((self.0[0] >> 48) | (self.0[1] << 3)) as u8; + s[ 7] = (self.0[1] >> 5) as u8; + s[ 8] = (self.0[1] >> 13) as u8; + s[ 9] = (self.0[1] >> 21) as u8; + s[10] = (self.0[1] >> 29) as u8; + s[11] = (self.0[1] >> 37) as u8; + s[12] = ((self.0[1] >> 45) | (self.0[2] << 6)) as u8; + s[13] = (self.0[2] >> 2) as u8; + s[14] = (self.0[2] >> 10) as u8; + s[15] = (self.0[2] >> 18) as u8; + s[16] = (self.0[2] >> 26) as u8; + s[17] = (self.0[2] >> 34) as u8; + s[18] = (self.0[2] >> 42) as u8; + s[19] = ((self.0[2] >> 50) | (self.0[3] << 1)) as u8; + s[20] = (self.0[3] >> 7) as u8; + s[21] = (self.0[3] >> 15) as u8; + s[22] = (self.0[3] >> 23) as u8; + s[23] = (self.0[3] >> 31) as u8; + s[24] = (self.0[3] >> 39) as u8; + s[25] = ((self.0[3] >> 47) | (self.0[4] << 4)) as u8; + s[26] = (self.0[4] >> 4) as u8; + s[27] = (self.0[4] >> 12) as u8; + s[28] = (self.0[4] >> 20) as u8; + s[29] = (self.0[4] >> 28) as u8; + s[30] = (self.0[4] >> 36) as u8; + s[31] = (self.0[4] >> 44) as u8; + + //Clear high bit + debug_assert!((s[31] & 0b1000_0000u8) == 0u8); + s[31] &= 127u8; + + return s + } /// XXX clarify documentation /// Determine if this field element, represented as a byte array, From 75baefabebe858e938797b437245c751af100192 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:38 -0700 Subject: [PATCH 069/101] Stub remaining radix_51 functions with unimplemented!() --- src/field.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/field.rs b/src/field.rs index e0fbbe3..cb729b8 100644 --- a/src/field.rs +++ b/src/field.rs @@ -869,6 +869,10 @@ impl FieldElement { FieldElement::reduce(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) } + #[cfg(feature="radix_51")] + pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement { + unimplemented!(); + } #[cfg(feature="radix_25_5")] fn square_inner(&self) -> [i64;10] { @@ -910,6 +914,10 @@ impl FieldElement { h } + #[cfg(feature="radix_51")] + fn square_inner(&self) -> [u128;5] { + unimplemented!(); + } /// Calculates h = f*f. Can overlap h with f. /// @@ -926,6 +934,10 @@ impl FieldElement { pub fn square(&self) -> FieldElement { FieldElement::reduce(&self.square_inner()) } + #[cfg(feature="radix_51")] + pub fn square(&self) -> FieldElement { + unimplemented!(); + } /// Square this field element and multiply the result by 2. /// @@ -951,6 +963,10 @@ impl FieldElement { } FieldElement::reduce(&coeffs) } + #[cfg(feature="radix_51")] + pub fn square2(&self) -> FieldElement { + unimplemented!(); + } #[inline] #[allow(dead_code)] From 147b9d90b8849862cc70c913eb9022c07a74a571 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:40 -0700 Subject: [PATCH 070/101] Revert "Add radix51 impl of reduce" This reverts commit 488e886d1e1b11400dedc6c41e7108e34c6747cc. --- src/field.rs | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/field.rs b/src/field.rs index cb729b8..166d604 100644 --- a/src/field.rs +++ b/src/field.rs @@ -415,40 +415,6 @@ impl FieldElement { output[9] = h[9] as i32; output } - #[cfg(feature="radix_51")] - fn reduce(input: &[u128; 5]) -> FieldElement { - // After multiplication, - // c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) - // where b is the bitlength of the input limbs. - - // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. - // After the first carry pass, all c[i] fit into u64. - - let low_51_bit_mask = (1u64 << 51) - 1; - c1 += (c0 >> 51) as u128; - let mut c0: u64 = (c0 as u64) & low_51_bit_mask; - c2 += (c1 >> 51) as u128; - let mut c1: u64 = (c1 as u64) & low_51_bit_mask; - c3 += (c2 >> 51) as u128; - let mut c2: u64 = (c2 as u64) & low_51_bit_mask; - c4 += (c3 >> 51) as u128; - let mut c3: u64 = (c3 as u64) & low_51_bit_mask; - c0 += ((c4 >> 51) as u64) * 19; - let mut c4: u64 = (c4 as u64) & low_51_bit_mask; - - c1 += c0 >> 51; - c0 = c0 & low_51_bit_mask; - c2 += c1 >> 51; - c1 = c1 & low_51_bit_mask; - c3 += c2 >> 51; - c2 = c2 & low_51_bit_mask; - c4 += c3 >> 51; - c3 = c3 & low_51_bit_mask; - c0 += (c4 >> 51) * 19; - c4 = c4 & low_51_bit_mask; - - FieldElement([c0,c1,c2,c3,c4]) - } /// Create a FieldElement by demarshalling an array of 32 bytes. /// From d6465ccd5e9f527993677bcdb5f55badffec2052 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:41 -0700 Subject: [PATCH 071/101] Fix remaining compile errors for radix_51 --- src/constants.rs | 41 +++++++++++++++++++++++++++++++++-------- src/curve.rs | 7 +++---- src/field.rs | 27 ++++++++++++++++++++++++--- 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 487d557..1913b8a 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -3141,14 +3141,26 @@ mod test { #[test] fn test_half() { - let one = FieldElement([1,0,0,0,0,0,0,0,0,0]); - let two = FieldElement([2,0,0,0,0,0,0,0,0,0]); + let one = FieldElement::one(); + let two = &one + &one; assert_eq!(one, &two * &constants::HALF); } - #[test] /// Test that the constant for sqrt(-486664) really is a square /// root of -486664. + #[test] + #[cfg(feature="radix_51")] + fn sqrt_minus_aplus2() { + let minus_aplus2 = -&FieldElement([486664,0,0,0,0]); + let sqrt = constants::SQRT_MINUS_APLUS2; + let sq = &sqrt * &sqrt; + assert_eq!(sq, minus_aplus2); + } + + /// Test that the constant for sqrt(-486664) really is a square + /// root of -486664. + #[test] + #[cfg(feature="radix_25_5")] fn sqrt_minus_aplus2() { let minus_aplus2 = FieldElement([-486664,0,0,0,0,0,0,0,0,0]); let sqrt = constants::SQRT_MINUS_APLUS2; @@ -3159,7 +3171,7 @@ mod test { #[test] /// Test that SQRT_M1 and MSQRT_M1 are square roots of -1 fn test_sqrt_minus_one() { - let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); + let minus_one = FieldElement::minus_one(); let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1; let msqrt_m1_sq = &constants::MSQRT_M1 * &constants::MSQRT_M1; assert_eq!(minus_one, sqrt_m1_sq); @@ -3168,8 +3180,8 @@ mod test { #[test] fn test_sqrt_constants_sign() { - let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); - let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); + let one = FieldElement::one(); + let minus_one = FieldElement::minus_one(); let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt(); assert_eq!(was_nonzero_square, 1u8); let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1; @@ -3180,8 +3192,9 @@ mod test { assert_eq!(sign_test_msqrt, one); } - #[test] /// Test that d = -121665/121666 + #[cfg(feature="radix_25_5")] + #[test] fn test_d_vs_ratio() { let a = FieldElement([-121665,0,0,0,0,0,0,0,0,0]); let b = FieldElement([ 121666,0,0,0,0,0,0,0,0,0]); @@ -3191,6 +3204,18 @@ mod test { assert_eq!(d2, constants::d2); } + /// Test that d = -121665/121666 + #[cfg(feature="radix_51")] + #[test] + fn test_d_vs_ratio() { + let a = -&FieldElement([121665,0,0,0,0]); + let b = FieldElement([121666,0,0,0,0]); + let d = &a * &b.invert(); + let d2 = &d + &d; + assert_eq!(d, constants::d); + assert_eq!(d2, constants::d2); + } + #[test] fn test_d4() { let mut four = FieldElement::zero(); @@ -3200,7 +3225,7 @@ mod test { #[test] fn test_a_minus_d() { - let a = FieldElement([-1,0,0,0,0,0,0,0,0,0]); + let a = FieldElement::minus_one(); let a_minus_d = &a - &constants::d; assert_eq!(a_minus_d, constants::a_minus_d); } diff --git a/src/curve.rs b/src/curve.rs index 054b164..6bb964a 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1192,10 +1192,9 @@ mod test { /// XXX what does Signal do here? #[test] fn u_minus_one_monty() { - let mut m1 = FieldElement::zero(); - m1[0] = -1; - let m1_bytes = m1.to_bytes(); - let div_by_zero_u = CompressedMontgomeryU(m1_bytes); + let minus_one = FieldElement::minus_one(); + let minus_one_bytes = minus_one.to_bytes(); + let div_by_zero_u = CompressedMontgomeryU(minus_one_bytes); assert!(div_by_zero_u.decompress().is_none()); } diff --git a/src/field.rs b/src/field.rs index 166d604..8bd65ed 100644 --- a/src/field.rs +++ b/src/field.rs @@ -267,12 +267,20 @@ impl CTAssignable for FieldElement { /// # Preconditions /// /// * `choice` in {0,1} + #[cfg(feature="radix_25_5")] fn conditional_assign(&mut self, f: &FieldElement, choice: u8) { let mask = -(choice as Limb); for i in 0..10 { self[i] ^= mask & (self[i] ^ f[i]); } } + #[cfg(feature="radix_51")] + fn conditional_assign(&mut self, f: &FieldElement, choice: u8) { + let mask = (-(choice as i64)) as u64; + for i in 0..5 { + self.0[i] ^= mask & (self.0[i] ^ f.0[i]); + } + } } impl FieldElement { @@ -283,6 +291,7 @@ impl FieldElement { self[i] = -self[i]; } } + /// Invert the sign of this field element #[cfg(feature="radix_51")] pub fn negate(&mut self) { // XXX how many copies of p @@ -293,21 +302,23 @@ impl FieldElement { self.0[4] = constants::p.0[4] - self.0[4]; } - /// Construct the additive identity + /// Construct zero. #[cfg(feature="radix_25_5")] pub fn zero() -> FieldElement { FieldElement([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + /// Construct zero. #[cfg(feature="radix_51")] pub fn zero() -> FieldElement { FieldElement([ 0, 0, 0, 0, 0 ]) } - /// Construct the multiplicative identity + /// Construct one. #[cfg(feature="radix_25_5")] pub fn one() -> FieldElement { FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + /// Construct one. #[cfg(feature="radix_51")] pub fn one() -> FieldElement { FieldElement([ 1, 0, 0, 0, 0 ]) @@ -318,6 +329,7 @@ impl FieldElement { pub fn minus_one() -> FieldElement { FieldElement([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + /// Construct -1. #[cfg(feature="radix_51")] pub fn minus_one() -> FieldElement { FieldElement([2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]) @@ -452,6 +464,7 @@ impl FieldElement { FieldElement::reduce(&h) } + /// Parse a `FieldElement` from 32 bytes. #[cfg(feature="radix_51")] pub fn from_bytes(bytes: &[u8;32]) -> FieldElement { let low_51_bit_mask = (1u64 << 51) - 1; @@ -616,6 +629,7 @@ impl FieldElement { s } + /// Serialize this `FieldElement` to bytes. #[cfg(feature="radix_51")] pub fn to_bytes(&self) -> [u8;32] { // XXX need to do reduction first @@ -835,6 +849,7 @@ impl FieldElement { FieldElement::reduce(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) } + /// Compute `self * _rhs`. #[cfg(feature="radix_51")] pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement { unimplemented!(); @@ -900,6 +915,7 @@ impl FieldElement { pub fn square(&self) -> FieldElement { FieldElement::reduce(&self.square_inner()) } + /// Compute `self^2`. #[cfg(feature="radix_51")] pub fn square(&self) -> FieldElement { unimplemented!(); @@ -929,6 +945,7 @@ impl FieldElement { } FieldElement::reduce(&coeffs) } + /// Compute `2 * self^2`. #[cfg(feature="radix_51")] pub fn square2(&self) -> FieldElement { unimplemented!(); @@ -1148,6 +1165,7 @@ mod test { use field::*; use subtle::CTNegatable; + /* #[test] fn print_constants() { use curve::*; @@ -1215,8 +1233,9 @@ mod test { } } - panic!(); + //panic!(); } + */ /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\ @@ -1263,6 +1282,7 @@ mod test { assert_eq!(asq, asq_constant_from_sage); } + /* #[test] fn from_bytes_64_on_a() { let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; @@ -1271,6 +1291,7 @@ mod test { let should_be_a_bytes = to_bytes_64(&a); assert_eq!(&A_BYTES, &should_be_a_bytes); } + */ #[test] fn a_square_vs_a_squared_constant() { From df080411e0e28115f5485b04042d4f3a4edb3389 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:42 -0700 Subject: [PATCH 072/101] Implement multiply() for radix51 --- src/field.rs | 92 +++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/field.rs b/src/field.rs index 8bd65ed..87b5c4c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -33,49 +33,6 @@ use utils::{load3, load4, load8}; use constants; -/// doc -pub fn mul64(a: &[u64;5], b: &[u64;5]) -> [u64;5] { - #[inline(always)] - fn m(a: u64, b: u64) -> u128 { (a as u128) * (b as u128) } - // Multiply to get 128-bit coefficients of output - let mut c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; - let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + ( m(a[4],b[2]) + m(a[3],b[3]) + m(a[2],b[4]) )*19; - let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + ( m(a[4],b[3]) + m(a[3],b[4]) )*19; - let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + ( m(a[4],b[4]) )*19; - let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); - // Now c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) - // where b is the bitlength of the input limbs. - - // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. - // After the first carry pass, all c[i] fit into u64. - - let low_51_bit_mask = (1u64 << 51) - 1; - c1 += (c0 >> 51) as u128; - let mut c0: u64 = (c0 as u64) & low_51_bit_mask; - c2 += (c1 >> 51) as u128; - let mut c1: u64 = (c1 as u64) & low_51_bit_mask; - c3 += (c2 >> 51) as u128; - let mut c2: u64 = (c2 as u64) & low_51_bit_mask; - c4 += (c3 >> 51) as u128; - let mut c3: u64 = (c3 as u64) & low_51_bit_mask; - c0 += ((c4 >> 51) as u64) * 19; - let mut c4: u64 = (c4 as u64) & low_51_bit_mask; - - c1 += c0 >> 51; - c0 = c0 & low_51_bit_mask; - c2 += c1 >> 51; - c1 = c1 & low_51_bit_mask; - c3 += c2 >> 51; - c2 = c2 & low_51_bit_mask; - c4 += c3 >> 51; - c3 = c3 & low_51_bit_mask; - c0 += (c4 >> 51) * 19; - c4 = c4 & low_51_bit_mask; - - [c0,c1,c2,c3,c4] -} - - /// With the `radix51` feature enabled, `FieldElements` are represented /// in radix 2^51 as five `u64`s. #[cfg(feature="radix_51")] @@ -852,7 +809,54 @@ impl FieldElement { /// Compute `self * _rhs`. #[cfg(feature="radix_51")] pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement { - unimplemented!(); + /// Multiply two 64-bit integers with 128 bits of output. + #[inline(always)] + fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } + + // Alias self, _rhs for more readable formulas + let a: &[u64; 5] = &self.0; + let b: &[u64; 5] = &_rhs.0; + + // Multiply to get 128-bit coefficients of output + let mut c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; + let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + ( m(a[4],b[2]) + m(a[3],b[3]) + m(a[2],b[4]) )*19; + let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + ( m(a[4],b[3]) + m(a[3],b[4]) )*19; + let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + ( m(a[4],b[4]) )*19; + let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); + + // Now c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) + // where b is the bitlength of the input limbs. + + // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. + // After the first carry pass, all c[i] fit into u64. + + // The 128-bit output limbs are stored in two 64-bit registers (low/high part). + // By rebinding the names after carrying, we free the upper registers for reuse. + let low_51_bit_mask = (1u64 << 51) - 1; + c1 += (c0 >> 51) as u128; + let mut c0: u64 = (c0 as u64) & low_51_bit_mask; + c2 += (c1 >> 51) as u128; + let mut c1: u64 = (c1 as u64) & low_51_bit_mask; + c3 += (c2 >> 51) as u128; + let mut c2: u64 = (c2 as u64) & low_51_bit_mask; + c4 += (c3 >> 51) as u128; + let mut c3: u64 = (c3 as u64) & low_51_bit_mask; + c0 += ((c4 >> 51) as u64) * 19; + let mut c4: u64 = (c4 as u64) & low_51_bit_mask; + + // Second carry pass to enforce 2^51 bound + c1 += c0 >> 51; + c0 = c0 & low_51_bit_mask; + c2 += c1 >> 51; + c1 = c1 & low_51_bit_mask; + c3 += c2 >> 51; + c2 = c2 & low_51_bit_mask; + c4 += c3 >> 51; + c3 = c3 & low_51_bit_mask; + c0 += (c4 >> 51) * 19; + c4 = c4 & low_51_bit_mask; + + FieldElement([c0,c1,c2,c3,c4]) } #[cfg(feature="radix_25_5")] From a9cbca668ba1a84664fd1ddd25d949123ad56694 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:44 -0700 Subject: [PATCH 073/101] Implement squaring for radix51 --- src/field.rs | 108 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 30 deletions(-) diff --git a/src/field.rs b/src/field.rs index 87b5c4c..d4cdb72 100644 --- a/src/field.rs +++ b/src/field.rs @@ -292,6 +292,24 @@ impl FieldElement { FieldElement([2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]) } + /// Given 64-bit limbs, reduce to enforce the bound c_i < 2^51. + #[cfg(feature="radix_51")] + #[inline(always)] + fn reduce(mut limbs: [u64; 5]) -> FieldElement { + let low_51_bit_mask = (1u64 << 51) - 1; + limbs[1] += limbs[0] >> 51; + limbs[0] = limbs[0] & low_51_bit_mask; + limbs[2] += limbs[1] >> 51; + limbs[1] = limbs[1] & low_51_bit_mask; + limbs[3] += limbs[2] >> 51; + limbs[2] = limbs[2] & low_51_bit_mask; + limbs[4] += limbs[3] >> 51; + limbs[3] = limbs[3] & low_51_bit_mask; + limbs[0] += (limbs[4] >> 51) * 19; + limbs[4] = limbs[4] & low_51_bit_mask; + + FieldElement(limbs) + } #[cfg(feature="radix_25_5")] fn reduce(input: &[i64;10]) -> FieldElement { //FeCombine let mut c = [0i64;10]; @@ -818,7 +836,7 @@ impl FieldElement { let b: &[u64; 5] = &_rhs.0; // Multiply to get 128-bit coefficients of output - let mut c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; + let c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + ( m(a[4],b[2]) + m(a[3],b[3]) + m(a[2],b[4]) )*19; let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + ( m(a[4],b[3]) + m(a[3],b[4]) )*19; let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + ( m(a[4],b[4]) )*19; @@ -836,27 +854,15 @@ impl FieldElement { c1 += (c0 >> 51) as u128; let mut c0: u64 = (c0 as u64) & low_51_bit_mask; c2 += (c1 >> 51) as u128; - let mut c1: u64 = (c1 as u64) & low_51_bit_mask; + let c1: u64 = (c1 as u64) & low_51_bit_mask; c3 += (c2 >> 51) as u128; - let mut c2: u64 = (c2 as u64) & low_51_bit_mask; + let c2: u64 = (c2 as u64) & low_51_bit_mask; c4 += (c3 >> 51) as u128; - let mut c3: u64 = (c3 as u64) & low_51_bit_mask; + let c3: u64 = (c3 as u64) & low_51_bit_mask; c0 += ((c4 >> 51) as u64) * 19; - let mut c4: u64 = (c4 as u64) & low_51_bit_mask; + let c4: u64 = (c4 as u64) & low_51_bit_mask; - // Second carry pass to enforce 2^51 bound - c1 += c0 >> 51; - c0 = c0 & low_51_bit_mask; - c2 += c1 >> 51; - c1 = c1 & low_51_bit_mask; - c3 += c2 >> 51; - c2 = c2 & low_51_bit_mask; - c4 += c3 >> 51; - c3 = c3 & low_51_bit_mask; - c0 += (c4 >> 51) * 19; - c4 = c4 & low_51_bit_mask; - - FieldElement([c0,c1,c2,c3,c4]) + FieldElement::reduce([c0,c1,c2,c3,c4]) } #[cfg(feature="radix_25_5")] @@ -900,8 +906,49 @@ impl FieldElement { h } #[cfg(feature="radix_51")] - fn square_inner(&self) -> [u128;5] { - unimplemented!(); + #[inline(always)] + fn square_inner(&self) -> [u64; 5] { + /// Multiply two 64-bit integers with 128 bits of output. + #[inline(always)] + fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } + + // Alias self, _rhs for more readable formulas + let a: &[u64; 5] = &self.0; + + // Precomputation: 64-bit multiply by 19 + let a3_19 = 19 * a[3]; + let a4_19 = 19 * a[4]; + + // Multiply to get 128-bit coefficients of output + let c0: u128 = m(a[0], a[0]) + 2*( m(a[1], a4_19) + m(a[2], a3_19) ); + let mut c1: u128 = m(a[3], a3_19) + 2*( m(a[0], a[1]) + m(a[2], a4_19) ); + let mut c2: u128 = m(a[1], a[1]) + 2*( m(a[0], a[2]) + m(a[4], a3_19) ); + let mut c3: u128 = m(a[4], a4_19) + 2*( m(a[0], a[3]) + m(a[1], a[2]) ); + let mut c4: u128 = m(a[2], a[2]) + 2*( m(a[0], a[4]) + m(a[1], a[3]) ); + + // Same bound as in multiply: + // c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) + // where b is the bitlength of the input limbs. + // + // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. + // After the first carry pass, all c[i] fit into u64. + + // The 128-bit output limbs are stored in two 64-bit registers (low/high part). + // By rebinding the names after carrying, we free the upper registers for reuse. + let low_51_bit_mask = (1u64 << 51) - 1; + c1 += (c0 >> 51) as u128; + let mut c0: u64 = (c0 as u64) & low_51_bit_mask; + c2 += (c1 >> 51) as u128; + let c1: u64 = (c1 as u64) & low_51_bit_mask; + c3 += (c2 >> 51) as u128; + let c2: u64 = (c2 as u64) & low_51_bit_mask; + c4 += (c3 >> 51) as u128; + let c3: u64 = (c3 as u64) & low_51_bit_mask; + c0 += ((c4 >> 51) as u64) * 19; + let c4: u64 = (c4 as u64) & low_51_bit_mask; + + // Now c_i all fit into u64, but are not yet bounded by 2^51. + [c0,c1,c2,c3,c4] } /// Calculates h = f*f. Can overlap h with f. @@ -922,7 +969,7 @@ impl FieldElement { /// Compute `self^2`. #[cfg(feature="radix_51")] pub fn square(&self) -> FieldElement { - unimplemented!(); + FieldElement::reduce( self.square_inner()) } /// Square this field element and multiply the result by 2. @@ -952,7 +999,15 @@ impl FieldElement { /// Compute `2 * self^2`. #[cfg(feature="radix_51")] pub fn square2(&self) -> FieldElement { - unimplemented!(); + let mut limbs = self.square_inner(); + // For this to work, need to have 1 extra bit of headroom after carry + // --> max 53 bit inputs, not 54 + limbs[0] *= 2; + limbs[1] *= 2; + limbs[2] *= 2; + limbs[3] *= 2; + limbs[4] *= 2; + FieldElement::reduce(limbs) } #[inline] @@ -1138,13 +1193,6 @@ mod bench { use field; use test::Bencher; - #[bench] - fn bench_mul64(b: &mut Bencher) { - let x = [1u64; 5]; - let y = [1u64; 5]; - b.iter(|| mul64(&x, &y)); - } - #[bench] fn mul_operator(b: &mut Bencher) { let a = FieldElement::from_bytes(&field::test::A_BYTES); @@ -1278,6 +1326,7 @@ mod test { assert_eq!(asq, &a*&a); } + /* #[test] fn mul64_on_a() { let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; @@ -1286,7 +1335,6 @@ mod test { assert_eq!(asq, asq_constant_from_sage); } - /* #[test] fn from_bytes_64_on_a() { let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; From 24f11427a16cc0070a9f91424f57019a22da17de Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:45 -0700 Subject: [PATCH 074/101] Add 2p to avoid underflows --- src/field.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/field.rs b/src/field.rs index d4cdb72..0d8cc1c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -146,11 +146,11 @@ impl<'b> SubAssign<&'b FieldElement> for FieldElement { fn sub_assign(&mut self, _rhs: &'b FieldElement) { // To avoid underflow, first add p // XXX how many copies should we add to preserve headroom? - self.0[0] += constants::p.0[0]; - self.0[1] += constants::p.0[1]; - self.0[2] += constants::p.0[2]; - self.0[3] += constants::p.0[3]; - self.0[4] += constants::p.0[4]; + self.0[0] += 2*constants::p.0[0]; + self.0[1] += 2*constants::p.0[1]; + self.0[2] += 2*constants::p.0[2]; + self.0[3] += 2*constants::p.0[3]; + self.0[4] += 2*constants::p.0[4]; // then subtract _rhs self.0[0] -= _rhs.0[0]; self.0[1] -= _rhs.0[1]; From 0fa8d8f4a7892da70cb9eae188f4ccb46005da19 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:46 -0700 Subject: [PATCH 075/101] Reduce to narrower range before to_bytes --- src/field.rs | 66 +++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/field.rs b/src/field.rs index 0d8cc1c..984c3c1 100644 --- a/src/field.rs +++ b/src/field.rs @@ -608,39 +608,41 @@ impl FieldElement { #[cfg(feature="radix_51")] pub fn to_bytes(&self) -> [u8;32] { // XXX need to do reduction first + // This reduces to the range [0,2^255), but we need [0,2^255-19) + let limbs = FieldElement::reduce(self.0).0; let mut s = [0u8;32]; - s[ 0] = self.0[0] as u8; - s[ 1] = (self.0[0] >> 8) as u8; - s[ 2] = (self.0[0] >> 16) as u8; - s[ 3] = (self.0[0] >> 24) as u8; - s[ 4] = (self.0[0] >> 32) as u8; - s[ 5] = (self.0[0] >> 40) as u8; - s[ 6] = ((self.0[0] >> 48) | (self.0[1] << 3)) as u8; - s[ 7] = (self.0[1] >> 5) as u8; - s[ 8] = (self.0[1] >> 13) as u8; - s[ 9] = (self.0[1] >> 21) as u8; - s[10] = (self.0[1] >> 29) as u8; - s[11] = (self.0[1] >> 37) as u8; - s[12] = ((self.0[1] >> 45) | (self.0[2] << 6)) as u8; - s[13] = (self.0[2] >> 2) as u8; - s[14] = (self.0[2] >> 10) as u8; - s[15] = (self.0[2] >> 18) as u8; - s[16] = (self.0[2] >> 26) as u8; - s[17] = (self.0[2] >> 34) as u8; - s[18] = (self.0[2] >> 42) as u8; - s[19] = ((self.0[2] >> 50) | (self.0[3] << 1)) as u8; - s[20] = (self.0[3] >> 7) as u8; - s[21] = (self.0[3] >> 15) as u8; - s[22] = (self.0[3] >> 23) as u8; - s[23] = (self.0[3] >> 31) as u8; - s[24] = (self.0[3] >> 39) as u8; - s[25] = ((self.0[3] >> 47) | (self.0[4] << 4)) as u8; - s[26] = (self.0[4] >> 4) as u8; - s[27] = (self.0[4] >> 12) as u8; - s[28] = (self.0[4] >> 20) as u8; - s[29] = (self.0[4] >> 28) as u8; - s[30] = (self.0[4] >> 36) as u8; - s[31] = (self.0[4] >> 44) as u8; + s[ 0] = limbs[0] as u8; + s[ 1] = (limbs[0] >> 8) as u8; + s[ 2] = (limbs[0] >> 16) as u8; + s[ 3] = (limbs[0] >> 24) as u8; + s[ 4] = (limbs[0] >> 32) as u8; + s[ 5] = (limbs[0] >> 40) as u8; + s[ 6] = ((limbs[0] >> 48) | (limbs[1] << 3)) as u8; + s[ 7] = (limbs[1] >> 5) as u8; + s[ 8] = (limbs[1] >> 13) as u8; + s[ 9] = (limbs[1] >> 21) as u8; + s[10] = (limbs[1] >> 29) as u8; + s[11] = (limbs[1] >> 37) as u8; + s[12] = ((limbs[1] >> 45) | (limbs[2] << 6)) as u8; + s[13] = (limbs[2] >> 2) as u8; + s[14] = (limbs[2] >> 10) as u8; + s[15] = (limbs[2] >> 18) as u8; + s[16] = (limbs[2] >> 26) as u8; + s[17] = (limbs[2] >> 34) as u8; + s[18] = (limbs[2] >> 42) as u8; + s[19] = ((limbs[2] >> 50) | (limbs[3] << 1)) as u8; + s[20] = (limbs[3] >> 7) as u8; + s[21] = (limbs[3] >> 15) as u8; + s[22] = (limbs[3] >> 23) as u8; + s[23] = (limbs[3] >> 31) as u8; + s[24] = (limbs[3] >> 39) as u8; + s[25] = ((limbs[3] >> 47) | (limbs[4] << 4)) as u8; + s[26] = (limbs[4] >> 4) as u8; + s[27] = (limbs[4] >> 12) as u8; + s[28] = (limbs[4] >> 20) as u8; + s[29] = (limbs[4] >> 28) as u8; + s[30] = (limbs[4] >> 36) as u8; + s[31] = (limbs[4] >> 44) as u8; //Clear high bit debug_assert!((s[31] & 0b1000_0000u8) == 0u8); From 9524c079ee9abba786f513abec63ca0783746c72 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:47 -0700 Subject: [PATCH 076/101] Reduce mod p in radix51 to_bytes --- src/field.rs | 101 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/src/field.rs b/src/field.rs index 984c3c1..d74f270 100644 --- a/src/field.rs +++ b/src/field.rs @@ -461,37 +461,6 @@ impl FieldElement { /// /// XXX eliminate limbs /// - /// # Preconditions - /// - /// * `|h[i]|` bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. - /// - /// # Lemma - /// - /// Write p = 2^255 - 19 and q = floor(h/p). - /// - /// Basic claim: q = floor(2^(-255)(h + 19 * 2^-25 h9 + 2^-1)). - /// - /// # Proof - /// - /// Have |h|<=p so |q|<=1 so |19^2 * 2^-255 * q| < 1/4. - /// - /// Also have |h-2^230 * h9| < 2^230 so |19 * 2^-255 * (h-2^230 * h9)| < 1/4. - /// - /// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9), then 0 [u8;32] { //FeToBytes + // Comment preserved from ed25519.go (presumably originally from ref10): + // + // # Preconditions + // + // * `|h[i]|` bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. + // + // # Lemma + // + // Write p = 2^255 - 19 and q = floor(h/p). + // + // Basic claim: q = floor(2^(-255)(h + 19 * 2^-25 h9 + 2^-1)). + // + // # Proof + // + // Have |h|<=p so |q|<=1 so |19^2 * 2^-255 * q| < 1/4. + // + // Also have |h-2^230 * h9| < 2^230 so |19 * 2^-255 * (h-2^230 * h9)| < 1/4. + // + // Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9), then 0 [u8;32] { - // XXX need to do reduction first // This reduces to the range [0,2^255), but we need [0,2^255-19) - let limbs = FieldElement::reduce(self.0).0; + let mut limbs = FieldElement::reduce(self.0).0; + // Let h = limbs[0] + limbs[1]*2^51 + ... + limbs[4]*2^204. + // + // Write h = pq + r with 0 <= r < p. We want to compute r = h mod p. + // + // Since h < 2^255, q = 0 or 1, with q = 0 when h < p and q = 1 when h >= p. + // + // Notice that h >= p <==> h + 19 >= p + 19 <==> h + 19 >= 2^255. + // Therefore q can be computed as the carry bit of h + 19. + + let mut q = (limbs[0] + 19) >> 51; + q = (limbs[1] + q) >> 51; + q = (limbs[2] + q) >> 51; + q = (limbs[3] + q) >> 51; + q = (limbs[4] + q) >> 51; + + // Now we can compute r as r = h - pq = r - (2^255-19)q = r + 19q - 2^255q + + limbs[0] += 19*q; + + // Now carry the result to compute r + 19q ... + let low_51_bit_mask = (1u64 << 51) - 1; + limbs[1] += limbs[0] >> 51; + limbs[0] = limbs[0] & low_51_bit_mask; + limbs[2] += limbs[1] >> 51; + limbs[1] = limbs[1] & low_51_bit_mask; + limbs[3] += limbs[2] >> 51; + limbs[2] = limbs[2] & low_51_bit_mask; + limbs[4] += limbs[3] >> 51; + limbs[3] = limbs[3] & low_51_bit_mask; + // ... but instead of carrying (limbs[4] >> 51) = 2^255q + // into another limb, discard it, subtracting the value + limbs[4] = limbs[4] & low_51_bit_mask; + + // Now arrange the bits of the limbs. let mut s = [0u8;32]; s[ 0] = limbs[0] as u8; s[ 1] = (limbs[0] >> 8) as u8; From e1d3281c2d23bffbb56c3eaa1a17c82d4fa20cd6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:48 -0700 Subject: [PATCH 077/101] Add debug asserts for multiplication preconditions. --- src/field.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/field.rs b/src/field.rs index d74f270..7f922cf 100644 --- a/src/field.rs +++ b/src/field.rs @@ -884,6 +884,11 @@ impl FieldElement { // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. // After the first carry pass, all c[i] fit into u64. + debug_assert!(a[0] < (1 << 54)); debug_assert!(b[0] < (1 << 54)); + debug_assert!(a[1] < (1 << 54)); debug_assert!(b[1] < (1 << 54)); + debug_assert!(a[2] < (1 << 54)); debug_assert!(b[2] < (1 << 54)); + debug_assert!(a[3] < (1 << 54)); debug_assert!(b[3] < (1 << 54)); + debug_assert!(a[4] < (1 << 54)); debug_assert!(b[4] < (1 << 54)); // The 128-bit output limbs are stored in two 64-bit registers (low/high part). // By rebinding the names after carrying, we free the upper registers for reuse. @@ -969,6 +974,11 @@ impl FieldElement { // // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. // After the first carry pass, all c[i] fit into u64. + debug_assert!(a[0] < (1 << 54)); + debug_assert!(a[1] < (1 << 54)); + debug_assert!(a[2] < (1 << 54)); + debug_assert!(a[3] < (1 << 54)); + debug_assert!(a[4] < (1 << 54)); // The 128-bit output limbs are stored in two 64-bit registers (low/high part). // By rebinding the names after carrying, we free the upper registers for reuse. From b75a88458a61947fbb28e621346ac004a98eb633 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:50 -0700 Subject: [PATCH 078/101] Add monte carlo test for FieldElements --- src/curve.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/curve.rs b/src/curve.rs index 6bb964a..b2c0caa 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1399,6 +1399,26 @@ mod test { assert!( ExtendedPoint::identity().is_identity() == true); assert!(constants::ED25519_BASEPOINT.is_identity() == false); } + + /// Rust's debug builds have overflow and underflow trapping, + /// and enable `debug_assert!()`. This performs many scalar + /// multiplications to attempt to trigger possible overflows etc. + /// + /// For instance, the `radix_51` `Mul` implementation for + /// `FieldElements` requires the input `Limb`s to be bounded by + /// 2^54, but we cannot enforce this dynamically at runtime, or + /// statically at compile time (until Rust gets type-level + /// integers, at which point we can encode "bits of headroom" into + /// the type system and prove correctness). + #[test] + fn monte_carlo_overflow_underflow_debug_assert_test() { + let mut P = ExtendedPoint::basepoint(); + // N.B. each scalar_mult does 1407 field mults, 1024 field squarings, + // so this does ~ 1M of each operation. + for _ in 0..1_000 { + P = P.scalar_mult(&A_SCALAR); + } + } } // ------------------------------------------------------------------------ From d2a51197d780f82f3c046dedf7140040c4c926ce Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:18:51 -0700 Subject: [PATCH 079/101] Add a carry-reduction during subtraction. --- src/field.rs | 53 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/field.rs b/src/field.rs index 7f922cf..75b5d06 100644 --- a/src/field.rs +++ b/src/field.rs @@ -144,29 +144,41 @@ impl<'b> SubAssign<&'b FieldElement> for FieldElement { } #[cfg(feature="radix_51")] fn sub_assign(&mut self, _rhs: &'b FieldElement) { - // To avoid underflow, first add p - // XXX how many copies should we add to preserve headroom? - self.0[0] += 2*constants::p.0[0]; - self.0[1] += 2*constants::p.0[1]; - self.0[2] += 2*constants::p.0[2]; - self.0[3] += 2*constants::p.0[3]; - self.0[4] += 2*constants::p.0[4]; - // then subtract _rhs - self.0[0] -= _rhs.0[0]; - self.0[1] -= _rhs.0[1]; - self.0[2] -= _rhs.0[2]; - self.0[3] -= _rhs.0[3]; - self.0[4] -= _rhs.0[4]; + let result = (self as &FieldElement) - _rhs; + for i in 0..5 { + self.0[i] = result.0[i]; + } } } impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement { type Output = FieldElement; + #[cfg(feature="radix_25_5")] fn sub(self, _rhs: &'b FieldElement) -> FieldElement { let mut output = self.clone(); output -= _rhs; output } + #[cfg(feature="radix_51")] + fn sub(self, _rhs: &'b FieldElement) -> FieldElement { + // To avoid underflow, first add a multiple of p. + // Choose 16*p = p << 4 to be larger than 54-bit _rhs. + // + // If we could statically track the bitlengths of the limbs + // of every FieldElement, we could choose a multiple of p + // just bigger than _rhs and avoid having to do a reduction. + // + // Since we don't yet have type-level integers to do this, we + // have to add an explicit reduction call here, which is a + // significant cost. + FieldElement::reduce([ + (self.0[0] + 36028797018963664u64) - _rhs.0[0], + (self.0[1] + 36028797018963952u64) - _rhs.0[1], + (self.0[2] + 36028797018963952u64) - _rhs.0[2], + (self.0[3] + 36028797018963952u64) - _rhs.0[3], + (self.0[4] + 36028797018963952u64) - _rhs.0[4], + ]) + } } impl<'b> MulAssign<&'b FieldElement> for FieldElement { @@ -251,12 +263,15 @@ impl FieldElement { /// Invert the sign of this field element #[cfg(feature="radix_51")] pub fn negate(&mut self) { - // XXX how many copies of p - self.0[0] = constants::p.0[0] - self.0[0]; - self.0[1] = constants::p.0[1] - self.0[1]; - self.0[2] = constants::p.0[2] - self.0[2]; - self.0[3] = constants::p.0[3] - self.0[3]; - self.0[4] = constants::p.0[4] - self.0[4]; + // See commentary in the Sub impl + let neg = FieldElement::reduce([ + 36028797018963664u64 - self.0[0], + 36028797018963952u64 - self.0[1], + 36028797018963952u64 - self.0[2], + 36028797018963952u64 - self.0[3], + 36028797018963952u64 - self.0[4], + ]); + self.0 = neg.0; } /// Construct zero. From f11c97e75cc326a665a247f7fd4ff31a57acaf21 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:23:14 -0700 Subject: [PATCH 080/101] Remove obsolete test code --- src/field.rs | 91 ---------------------------------------------------- 1 file changed, 91 deletions(-) diff --git a/src/field.rs b/src/field.rs index 75b5d06..d6eb646 100644 --- a/src/field.rs +++ b/src/field.rs @@ -1279,78 +1279,6 @@ mod test { use field::*; use subtle::CTNegatable; - /* - #[test] - fn print_constants() { - use curve::*; - println!(""); - fn repr_fe(s: &str, fe: &FieldElement, t: &'static str) { - let f = from_bytes_64(&fe.to_bytes()); - println!("{}FieldElement([{}, {}, {}, {}, {}]){}", s, f[0], f[1], f[2], f[3], f[4], t); - } - fn repr_ext(s: &'static str, P: &ExtendedPoint) { - println!("{}ExtendedPoint {{", s); - repr_fe(" X: ", &P.X, ","); - repr_fe(" Y: ", &P.Y, ","); - repr_fe(" Z: ", &P.Z, ","); - repr_fe(" T: ", &P.T, ","); - println!("}};"); - } - fn repr_aff(s: &'static str, P: &AffineNielsPoint) { - println!("{}AffineNielsPoint {{", s); - repr_fe(" y_plus_x: ", &P.y_plus_x, ","); - repr_fe(" y_minus_x: ", &P.y_minus_x, ","); - repr_fe(" xy2d: ", &P.xy2d, ","); - println!("}};"); - } - fn print(name: &'static str, f: &FieldElement) { - repr_fe(format!("pub const {}: FieldElement = ", name).as_str(), f, ";"); - } - - print("d", &constants::d); - print("d2", &constants::d2); - print("d4", &constants::d4); - print("a_minus_d", &constants::a_minus_d); - - print("SQRT_M1", &constants::SQRT_M1); - print("MSQRT_M1", &constants::MSQRT_M1); - - print("HALF", &constants::HALF); - print("A", &constants::A); - print("SQRT_MINUS_A", &constants::SQRT_MINUS_A); - print("SQRT_MINUS_APLUS2", &constants::SQRT_MINUS_APLUS2); - print("SQRT_MINUS_HALF", &constants::SQRT_MINUS_HALF); - - repr_ext("pub const ED25519_BASEPOINT: ExtendedPoint = ", &constants::ED25519_BASEPOINT); - - println!("pub const EIGHT_TORSION: [ExtendedPoint; 8] ="); - - for i in 0..8 { - repr_ext("", &constants::EIGHT_TORSION[i]); - println!(","); - } - - println!("pub const bi: [AffineNielsPoint; 8] ="); - - for i in 0..8 { - repr_aff("", &constants::bi[i]); - println!(","); - } - - println!("pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable(["); - - let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT); - for i in 0..32 { - println!("\n\n"); - for j in 0..8 { - repr_aff("", &table.0[i][j]); - } - } - - //panic!(); - } - */ - /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\ /// 2228051251926706380353716438957572 @@ -1388,25 +1316,6 @@ mod test { assert_eq!(asq, &a*&a); } - /* - #[test] - fn mul64_on_a() { - let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; - let asq_constant_from_sage: [u64; 5] = [1696437425706869, 260630435370367, 277335390860868, 1743763050813710, 1739636627710249]; - let asq = mul64(&a, &a.clone()); - assert_eq!(asq, asq_constant_from_sage); - } - - #[test] - fn from_bytes_64_on_a() { - let a: [u64;5] = [838547684720132, 293808819440897, 1085520638549020, 231251532116217, 416286470530165]; - let should_be_a = from_bytes_64(&A_BYTES); - assert_eq!(a, should_be_a); - let should_be_a_bytes = to_bytes_64(&a); - assert_eq!(&A_BYTES, &should_be_a_bytes); - } - */ - #[test] fn a_square_vs_a_squared_constant() { let a = FieldElement::from_bytes(&A_BYTES); From 45cc82d25897fa942bd866f1cea07f8b6976f522 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 12 Mar 2017 23:37:25 -0700 Subject: [PATCH 081/101] Move multiply() into the Mul impl --- src/field.rs | 257 +++++++++++++++++++++++++-------------------------- 1 file changed, 128 insertions(+), 129 deletions(-) diff --git a/src/field.rs b/src/field.rs index d6eb646..79f25da 100644 --- a/src/field.rs +++ b/src/field.rs @@ -183,14 +183,140 @@ impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement { impl<'b> MulAssign<&'b FieldElement> for FieldElement { fn mul_assign(&mut self, _rhs: &'b FieldElement) { - self.0 = self.multiply(_rhs).0; + let result = (self as &FieldElement) * _rhs; + self.0 = result.0; } } impl<'a, 'b> Mul<&'b FieldElement> for &'a FieldElement { type Output = FieldElement; + #[cfg(feature="radix_51")] fn mul(self, _rhs: &'b FieldElement) -> FieldElement { - self.multiply(_rhs) + /// Multiply two 64-bit integers with 128 bits of output. + #[inline(always)] + fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } + + // Alias self, _rhs for more readable formulas + let a: &[u64; 5] = &self.0; + let b: &[u64; 5] = &_rhs.0; + + // Multiply to get 128-bit coefficients of output + let c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; + let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + ( m(a[4],b[2]) + m(a[3],b[3]) + m(a[2],b[4]) )*19; + let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + ( m(a[4],b[3]) + m(a[3],b[4]) )*19; + let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + ( m(a[4],b[4]) )*19; + let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); + + // Now c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) + // where b is the bitlength of the input limbs. + + // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. + // After the first carry pass, all c[i] fit into u64. + debug_assert!(a[0] < (1 << 54)); debug_assert!(b[0] < (1 << 54)); + debug_assert!(a[1] < (1 << 54)); debug_assert!(b[1] < (1 << 54)); + debug_assert!(a[2] < (1 << 54)); debug_assert!(b[2] < (1 << 54)); + debug_assert!(a[3] < (1 << 54)); debug_assert!(b[3] < (1 << 54)); + debug_assert!(a[4] < (1 << 54)); debug_assert!(b[4] < (1 << 54)); + + // The 128-bit output limbs are stored in two 64-bit registers (low/high part). + // By rebinding the names after carrying, we free the upper registers for reuse. + let low_51_bit_mask = (1u64 << 51) - 1; + c1 += (c0 >> 51) as u128; + let mut c0: u64 = (c0 as u64) & low_51_bit_mask; + c2 += (c1 >> 51) as u128; + let c1: u64 = (c1 as u64) & low_51_bit_mask; + c3 += (c2 >> 51) as u128; + let c2: u64 = (c2 as u64) & low_51_bit_mask; + c4 += (c3 >> 51) as u128; + let c3: u64 = (c3 as u64) & low_51_bit_mask; + c0 += ((c4 >> 51) as u64) * 19; + let c4: u64 = (c4 as u64) & low_51_bit_mask; + + FieldElement::reduce([c0,c1,c2,c3,c4]) + } + + #[cfg(feature="radix_25_5")] + fn mul(self, _rhs: &'b FieldElement) -> FieldElement { + // Notes preserved from ed25519.go (presumably originally from ref10): + // + // Calculates h = f * g. Can overlap h with f or g. + // + // # Preconditions + // + // * |f[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc. + // * |g[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc. + // + // # Postconditions + // + // * |h| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. + // + // ## Notes on implementation strategy + // + // * Using schoolbook multiplication. + // * Karatsuba would save a little in some cost models. + // + // * Most multiplications by 2 and 19 are 32-bit precomputations; + // cheaper than 64-bit postcomputations. + // + // * There is one remaining multiplication by 19 in the carry chain; + // one *19 precomputation can be merged into this, + // but the resulting data flow is considerably less clean. + // + // * There are 12 carries below. + // 10 of them are 2-way parallelizable and vectorizable. + // Can get away with 11 carries, but then data flow is much deeper. + // + // * With tighter constraints on inputs can squeeze carries into int32. + let f0 = self[0] as i64; + let f1 = self[1] as i64; + let f2 = self[2] as i64; + let f3 = self[3] as i64; + let f4 = self[4] as i64; + let f5 = self[5] as i64; + let f6 = self[6] as i64; + let f7 = self[7] as i64; + let f8 = self[8] as i64; + let f9 = self[9] as i64; + + let f1_2 = (2 * self[1]) as i64; + let f3_2 = (2 * self[3]) as i64; + let f5_2 = (2 * self[5]) as i64; + let f7_2 = (2 * self[7]) as i64; + let f9_2 = (2 * self[9]) as i64; + + let g0 = _rhs[0] as i64; + let g1 = _rhs[1] as i64; + let g2 = _rhs[2] as i64; + let g3 = _rhs[3] as i64; + let g4 = _rhs[4] as i64; + let g5 = _rhs[5] as i64; + let g6 = _rhs[6] as i64; + let g7 = _rhs[7] as i64; + let g8 = _rhs[8] as i64; + let g9 = _rhs[9] as i64; + + let g1_19 = (19 * _rhs[1]) as i64; /* 1.4*2^29 */ + let g2_19 = (19 * _rhs[2]) as i64; /* 1.4*2^30; still ok */ + let g3_19 = (19 * _rhs[3]) as i64; + let g4_19 = (19 * _rhs[4]) as i64; + let g5_19 = (19 * _rhs[5]) as i64; + let g6_19 = (19 * _rhs[6]) as i64; + let g7_19 = (19 * _rhs[7]) as i64; + let g8_19 = (19 * _rhs[8]) as i64; + let g9_19 = (19 * _rhs[9]) as i64; + + let h0 = f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19; + let h1 = f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19; + let h2 = f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19; + let h3 = f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19; + let h4 = f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19; + let h5 = f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19; + let h6 = f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19; + let h7 = f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19; + let h8 = f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19; + let h9 = f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0; + + FieldElement::reduce(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) } } @@ -795,133 +921,6 @@ impl FieldElement { return byte_is_nonzero(x); } - /// Calculates h = f * g. Can overlap h with f or g. - /// - /// # Preconditions - /// - /// * |f[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc. - /// * |g[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc. - /// - /// # Postconditions - /// - /// * |h| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. - /// - /// ## Notes on implementation strategy - /// - /// * Using schoolbook multiplication. - /// * Karatsuba would save a little in some cost models. - /// - /// * Most multiplications by 2 and 19 are 32-bit precomputations; - /// cheaper than 64-bit postcomputations. - /// - /// * There is one remaining multiplication by 19 in the carry chain; - /// one *19 precomputation can be merged into this, - /// but the resulting data flow is considerably less clean. - /// - /// * There are 12 carries below. - /// 10 of them are 2-way parallelizable and vectorizable. - /// Can get away with 11 carries, but then data flow is much deeper. - /// - /// * With tighter constraints on inputs can squeeze carries into int32. - #[cfg(feature="radix_25_5")] - pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement { - let f0 = self[0] as i64; - let f1 = self[1] as i64; - let f2 = self[2] as i64; - let f3 = self[3] as i64; - let f4 = self[4] as i64; - let f5 = self[5] as i64; - let f6 = self[6] as i64; - let f7 = self[7] as i64; - let f8 = self[8] as i64; - let f9 = self[9] as i64; - - let f1_2 = (2 * self[1]) as i64; - let f3_2 = (2 * self[3]) as i64; - let f5_2 = (2 * self[5]) as i64; - let f7_2 = (2 * self[7]) as i64; - let f9_2 = (2 * self[9]) as i64; - - let g0 = _rhs[0] as i64; - let g1 = _rhs[1] as i64; - let g2 = _rhs[2] as i64; - let g3 = _rhs[3] as i64; - let g4 = _rhs[4] as i64; - let g5 = _rhs[5] as i64; - let g6 = _rhs[6] as i64; - let g7 = _rhs[7] as i64; - let g8 = _rhs[8] as i64; - let g9 = _rhs[9] as i64; - - let g1_19 = (19 * _rhs[1]) as i64; /* 1.4*2^29 */ - let g2_19 = (19 * _rhs[2]) as i64; /* 1.4*2^30; still ok */ - let g3_19 = (19 * _rhs[3]) as i64; - let g4_19 = (19 * _rhs[4]) as i64; - let g5_19 = (19 * _rhs[5]) as i64; - let g6_19 = (19 * _rhs[6]) as i64; - let g7_19 = (19 * _rhs[7]) as i64; - let g8_19 = (19 * _rhs[8]) as i64; - let g9_19 = (19 * _rhs[9]) as i64; - - let h0 = f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19; - let h1 = f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19; - let h2 = f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19; - let h3 = f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19; - let h4 = f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19; - let h5 = f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19; - let h6 = f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19; - let h7 = f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19; - let h8 = f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19; - let h9 = f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0; - - FieldElement::reduce(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) - } - /// Compute `self * _rhs`. - #[cfg(feature="radix_51")] - pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement { - /// Multiply two 64-bit integers with 128 bits of output. - #[inline(always)] - fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } - - // Alias self, _rhs for more readable formulas - let a: &[u64; 5] = &self.0; - let b: &[u64; 5] = &_rhs.0; - - // Multiply to get 128-bit coefficients of output - let c0: u128 = m(a[0],b[0]) + ( m(a[4],b[1]) + m(a[3],b[2]) + m(a[2],b[3]) + m(a[1],b[4]) )*19; - let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + ( m(a[4],b[2]) + m(a[3],b[3]) + m(a[2],b[4]) )*19; - let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + ( m(a[4],b[3]) + m(a[3],b[4]) )*19; - let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + ( m(a[4],b[4]) )*19; - let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); - - // Now c[i] < 2^2b * (1+i + (4-i)*19) < 2^(2b + lg(1+4*19)) < 2^(2b + 6.27) - // where b is the bitlength of the input limbs. - - // The carry (c[i] >> 51) fits into a u64 iff 2b+6.27 < 64+51 iff b <= 54. - // After the first carry pass, all c[i] fit into u64. - debug_assert!(a[0] < (1 << 54)); debug_assert!(b[0] < (1 << 54)); - debug_assert!(a[1] < (1 << 54)); debug_assert!(b[1] < (1 << 54)); - debug_assert!(a[2] < (1 << 54)); debug_assert!(b[2] < (1 << 54)); - debug_assert!(a[3] < (1 << 54)); debug_assert!(b[3] < (1 << 54)); - debug_assert!(a[4] < (1 << 54)); debug_assert!(b[4] < (1 << 54)); - - // The 128-bit output limbs are stored in two 64-bit registers (low/high part). - // By rebinding the names after carrying, we free the upper registers for reuse. - let low_51_bit_mask = (1u64 << 51) - 1; - c1 += (c0 >> 51) as u128; - let mut c0: u64 = (c0 as u64) & low_51_bit_mask; - c2 += (c1 >> 51) as u128; - let c1: u64 = (c1 as u64) & low_51_bit_mask; - c3 += (c2 >> 51) as u128; - let c2: u64 = (c2 as u64) & low_51_bit_mask; - c4 += (c3 >> 51) as u128; - let c3: u64 = (c3 as u64) & low_51_bit_mask; - c0 += ((c4 >> 51) as u64) * 19; - let c4: u64 = (c4 as u64) & low_51_bit_mask; - - FieldElement::reduce([c0,c1,c2,c3,c4]) - } - #[cfg(feature="radix_25_5")] fn square_inner(&self) -> [i64;10] { let f0 = self[0] as i64; From f80754a95489220ee57861e96acd244c61caafdb Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 14:42:45 -0700 Subject: [PATCH 082/101] Further rename fixups in benchmark test names --- src/curve.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index b2c0caa..5795ffe 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1455,7 +1455,7 @@ mod bench { } #[bench] - fn add_extended_and_cached_output_completed(b: &mut Bencher) { + fn add_extended_and_projective_niels_output_completed(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT; let p2 = constants::ED25519_BASEPOINT.to_projective_niels(); @@ -1463,7 +1463,7 @@ mod bench { } #[bench] - fn add_extended_and_cached_output_extended(b: &mut Bencher) { + fn add_extended_and_projective_niels_output_extended(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT; let p2 = constants::ED25519_BASEPOINT.to_projective_niels(); @@ -1471,7 +1471,7 @@ mod bench { } #[bench] - fn add_extended_and_precomputed_output_completed(b: &mut Bencher) { + fn add_extended_and_affine_niels_output_completed(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT; let p2 = constants::ED25519_BASEPOINT.to_affine_niels(); @@ -1479,7 +1479,7 @@ mod bench { } #[bench] - fn add_extended_and_precomputed_output_extended(b: &mut Bencher) { + fn add_extended_and_affine_niels_output_extended(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT; let p2 = constants::ED25519_BASEPOINT.to_affine_niels(); From cf9f9aa402e88362431ab424ea69c15cece6f00f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 17:04:37 -0700 Subject: [PATCH 083/101] Enable radix_51 on nightly --- Cargo.toml | 6 ++---- src/constants.rs | 34 +++++++++++++++++----------------- src/field.rs | 38 +++++++++++++++++++------------------- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 48160a2..af71dfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,16 +33,14 @@ version = "^0.6" version = "0.4" [features] -nightly = ["basepoint_table_creation"] -default = ["std", "radix_25_5"] +nightly = ["basepoint_table_creation", "radix_51"] +default = ["std"] std = ["rand"] yolocrypto = [] # Needs nightly for placement new basepoint_table_creation = [] # Radix-51 arithmetic using u128 radix_51 = [] -# Radix-25.5 arithmetic using i64 -radix_25_5 = [] # The development profile, used for `cargo build`. [profile.dev] diff --git a/src/constants.rs b/src/constants.rs index 1913b8a..9ff4d4d 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -29,25 +29,25 @@ use scalar::Scalar; #[cfg(feature="radix_51")] pub const p: FieldElement = FieldElement([2251799813685229, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]); -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const d: FieldElement = FieldElement([ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, ]); #[cfg(feature="radix_51")] pub const d: FieldElement = FieldElement([929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575]); -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const d2: FieldElement = FieldElement([ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, ]); #[cfg(feature="radix_51")] pub const d2: FieldElement = FieldElement([1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903]); -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const d4: FieldElement = FieldElement([ 23454405, -11679213, 5618422, -5756869, 458917, -1596832, -25103633, -12990876, -7676928, -14666033 ]); #[cfg(feature="radix_51")] pub const d4: FieldElement = FieldElement([1468021120295602, 1865462880516853, 2144638232625316, 1379996857856750, 1267578991991807]); -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const a_minus_d: FieldElement = FieldElement([ 10913609, -13857413, 15372611, -6949391, -114729, 8787816, 6275908, 3247719, 18696448, 12055116, ]); @@ -62,7 +62,7 @@ pub const HALF_P_MINUS_1_BYTES: [u8; 32] = 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f]; /// Precomputed value of one of the square roots of -1 (mod p) -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const SQRT_M1: FieldElement = FieldElement([ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, ]); @@ -71,7 +71,7 @@ pub const SQRT_M1: FieldElement = FieldElement([1718705420411056, 23490888355650 /// Precomputed value of the other square root of -1 (mod p), /// i.e., MSQRT_M1 = -SQRT_M1. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const MSQRT_M1: FieldElement = FieldElement([ 32595792, 7943725, -9377950, -3500415, -12389472, 272473, 25146209, 2005654, -326686, -11406482, ]); @@ -79,14 +79,14 @@ pub const MSQRT_M1: FieldElement = FieldElement([ pub const MSQRT_M1: FieldElement = FieldElement([533094393274173, 2016890930128738, 18285341111199, 134597186663265, 1486323764102114]); /// Precomputed value of 1/2 (mod p). -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const HALF: FieldElement = FieldElement([ 10, 0, 0, 0, 0, 0, 0, 0, 0, -16777216, ]); #[cfg(feature="radix_51")] pub const HALF: FieldElement = FieldElement([2251799813685239, 2251799813685247, 2251799813685247, 2251799813685247, 1125899906842623]); /// In Montgomery form y² = x³+Ax²+x, Curve25519 has A=486662. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const A: FieldElement = FieldElement([ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]); #[cfg(feature="radix_51")] @@ -96,7 +96,7 @@ pub const A: FieldElement = FieldElement([486662, 0, 0, 0, 0]); // XXX I think that this was used in Adam's code for his elligator // implementation, but that should maybe be using sqrt(-486664) // instead...? - hdevalence -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const SQRT_MINUS_A: FieldElement = FieldElement([ // sqrtMinusA 12222970, 8312128, 11511410, -9067497, 15300785, 241793, -25456130, -14121551, 12187136, -3972024, ]); @@ -104,7 +104,7 @@ pub const SQRT_MINUS_A: FieldElement = FieldElement([ // sqrtMinusA pub const SQRT_MINUS_A: FieldElement = FieldElement([557817479725543, 1643290402203250, 16226468853936, 1304118542701054, 1985241807451647]); /// SQRT_MINUS_APLUS2 is sqrt(-486664) -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ -12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024]); @@ -112,7 +112,7 @@ pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([1693982333959686, 608509411481997, 2235573344831311, 947681270984193, 266558006233600]); /// SQRT_MINUS_HALF is sqrt(-1/2) -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const SQRT_MINUS_HALF: FieldElement = FieldElement([ // sqrtMinusHalf -17256545, 3971863, 28865457, -1750208, 27359696, -16640980, 12573105, 1002827, -163343, 11073975, ]); @@ -137,7 +137,7 @@ pub const BASE_CMPRSSD: CompressedEdwardsY = 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); /// Basepoint has y = 4/5. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{ X: FieldElement([-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491]), Y: FieldElement([-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886]), @@ -172,7 +172,7 @@ pub const lminus1: Scalar = Scalar([ 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0 /// /// Thus Ɛ[4] is the points indexed by 0,2,4,6 and Ɛ[2] is the points /// indexed by 0,4. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ ExtendedPoint{ X: FieldElement([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), @@ -282,7 +282,7 @@ pub const EIGHT_TORSION: [ExtendedPoint; 8] = [ } ]; -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const bi: [AffineNielsPoint; 8] = [ AffineNielsPoint{ y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), @@ -380,7 +380,7 @@ pub const bi: [AffineNielsPoint; 8] = [ /// /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`, /// for `0 ≤ i < 32`, `1 ≤ j < 9`. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable([ [ AffineNielsPoint{ @@ -3160,7 +3160,7 @@ mod test { /// Test that the constant for sqrt(-486664) really is a square /// root of -486664. #[test] - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn sqrt_minus_aplus2() { let minus_aplus2 = FieldElement([-486664,0,0,0,0,0,0,0,0,0]); let sqrt = constants::SQRT_MINUS_APLUS2; @@ -3193,7 +3193,7 @@ mod test { } /// Test that d = -121665/121666 - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] #[test] fn test_d_vs_ratio() { let a = FieldElement([-121665,0,0,0,0,0,0,0,0,0]); diff --git a/src/field.rs b/src/field.rs index 79f25da..e37def3 100644 --- a/src/field.rs +++ b/src/field.rs @@ -50,14 +50,14 @@ pub struct FieldElement(pub [u64; 5]); /// 25.5, that is, each Limb of a FieldElement alternates between being /// represented as a factor of 2^25 or 2^26 more than the last corresponding /// integer. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] pub type Limb = i32; /// FieldElement represents an element of the field GF(2^255 - 19). An element /// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 /// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on /// context. -#[cfg(feature="radix_25_5")] +#[cfg(not(feature="radix_51"))] #[derive(Copy, Clone)] pub struct FieldElement(pub [i32; 10]); @@ -136,7 +136,7 @@ impl<'a, 'b> Add<&'b FieldElement> for &'a FieldElement { } impl<'b> SubAssign<&'b FieldElement> for FieldElement { - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn sub_assign(&mut self, _rhs: &'b FieldElement) { // fdifference() for i in 0..10 { self[i] -= _rhs[i]; @@ -153,7 +153,7 @@ impl<'b> SubAssign<&'b FieldElement> for FieldElement { impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement { type Output = FieldElement; - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn sub(self, _rhs: &'b FieldElement) -> FieldElement { let mut output = self.clone(); output -= _rhs; @@ -235,7 +235,7 @@ impl<'a, 'b> Mul<&'b FieldElement> for &'a FieldElement { FieldElement::reduce([c0,c1,c2,c3,c4]) } - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn mul(self, _rhs: &'b FieldElement) -> FieldElement { // Notes preserved from ed25519.go (presumably originally from ref10): // @@ -362,7 +362,7 @@ impl CTAssignable for FieldElement { /// # Preconditions /// /// * `choice` in {0,1} - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn conditional_assign(&mut self, f: &FieldElement, choice: u8) { let mask = -(choice as Limb); for i in 0..10 { @@ -380,7 +380,7 @@ impl CTAssignable for FieldElement { impl FieldElement { /// Invert the sign of this field element - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn negate(&mut self) { for i in 0..10 { self[i] = -self[i]; @@ -401,7 +401,7 @@ impl FieldElement { } /// Construct zero. - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn zero() -> FieldElement { FieldElement([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } @@ -412,7 +412,7 @@ impl FieldElement { } /// Construct one. - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn one() -> FieldElement { FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } @@ -423,7 +423,7 @@ impl FieldElement { } /// Construct -1. - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn minus_one() -> FieldElement { FieldElement([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } @@ -451,7 +451,7 @@ impl FieldElement { FieldElement(limbs) } - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn reduce(input: &[i64;10]) -> FieldElement { //FeCombine let mut c = [0i64;10]; let mut h = input.clone(); @@ -564,7 +564,7 @@ impl FieldElement { /// # Return /// /// Returns a new FieldElement. - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn from_bytes(data: &[u8; 32]) -> FieldElement { //FeFromBytes let mut h = [0i64;10]; h[0] = load4(&data[ 0..]); @@ -617,7 +617,7 @@ impl FieldElement { /// let bytes: [u8; 32] = fe.to_bytes(); /// assert!(data == bytes); /// ``` - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn to_bytes(&self) -> [u8;32] { //FeToBytes // Comment preserved from ed25519.go (presumably originally from ref10): // @@ -921,7 +921,7 @@ impl FieldElement { return byte_is_nonzero(x); } - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] fn square_inner(&self) -> [i64;10] { let f0 = self[0] as i64; let f1 = self[1] as i64; @@ -1023,7 +1023,7 @@ impl FieldElement { /// # Postconditions /// /// * |h[i]| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn square(&self) -> FieldElement { FieldElement::reduce(&self.square_inner()) } @@ -1049,7 +1049,7 @@ impl FieldElement { /// /// See fe_mul.c in ref10 implementation for discussion of implementation /// strategy. - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] pub fn square2(&self) -> FieldElement { let mut coeffs = self.square_inner(); for i in 0..self.0.len() { @@ -1381,12 +1381,12 @@ mod test { assert_eq!(without_highbit_set, with_highbit_set); } - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] static B_LIMBS_RADIX_25_5: FieldElement = FieldElement( [-5652623, 8034020, 8266223, -13556020, -5672552, -5582839, -12603138, 15161929, -16418207, 13296296]); - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] #[test] fn from_bytes_vs_radix_25_5_limb_constants() { let test_elt = FieldElement::from_bytes(&B_BYTES); @@ -1395,7 +1395,7 @@ mod test { } } - #[cfg(feature="radix_25_5")] + #[cfg(not(feature="radix_51"))] #[test] fn radix_25_5_limb_constants_to_bytes_vs_byte_constants() { let test_bytes = B_LIMBS_RADIX_25_5.to_bytes(); From 4f319873d088b49f008df6eff8b30a680d348caf Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Mon, 13 Mar 2017 23:56:44 +0000 Subject: [PATCH 084/101] Add a .travis.yml file. --- .travis.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b8031d0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: rust + +rust: + - stable + - beta + - nightly + +env: + - TEST_COMMAND=test + - TEST_COMMAND=bench + +matrix: + # We can probably remove this, as we reasonably expect dalek to work on + # stable and beta, but currently we require "test" feature in order to + # run benchmarks, which causes dalek not to build on stable. See + # https://github.com/isislovecruft/curve25519-dalek/pull/38#issuecomment-286027562 + allow_failures: + - rust: stable + - rust: beta + +script: + - cargo $TEST_COMMAND --features "yolocrypto" From 904911e2b82432798b7027b1edb905d20ab01a5c Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 01:10:09 +0000 Subject: [PATCH 085/101] Move field module benchmarks to separate module. --- src/field.rs | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/field.rs b/src/field.rs index 3094b0f..f18fdfd 100644 --- a/src/field.rs +++ b/src/field.rs @@ -921,31 +921,12 @@ impl FieldElement { #[cfg(test)] mod test { use field::*; - use test::Bencher; use subtle::CTNegatable; - #[bench] - fn bench_fieldelement_a_mul_a(b: &mut Bencher) { - let a = FieldElement::from_bytes(&A_BYTES); - b.iter(|| &a*&a); - } - - #[bench] - fn bench_fieldelement_a_sq(b: &mut Bencher) { - let a = FieldElement::from_bytes(&A_BYTES); - b.iter(|| a.square()); - } - - #[bench] - fn bench_fieldelement_a_inv(b: &mut Bencher) { - let a = FieldElement::from_bytes(&A_BYTES); - b.iter(|| a.invert()); - } - /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\ /// 2228051251926706380353716438957572 - static A_BYTES: [u8;32] = + pub static A_BYTES: [u8;32] = [ 0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68, 0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7, 0x03, 0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4, @@ -1066,3 +1047,29 @@ mod test { assert_eq!(x, one); } } + +#[cfg(test)] +mod bench { + use test::Bencher; + + use super::*; + use super::test::A_BYTES; + + #[bench] + fn fieldelement_a_mul_a(b: &mut Bencher) { + let a = FieldElement::from_bytes(&A_BYTES); + b.iter(|| &a*&a); + } + + #[bench] + fn fieldelement_a_sq(b: &mut Bencher) { + let a = FieldElement::from_bytes(&A_BYTES); + b.iter(|| a.square()); + } + + #[bench] + fn fieldelement_a_inv(b: &mut Bencher) { + let a = FieldElement::from_bytes(&A_BYTES); + b.iter(|| a.invert()); + } +} From cb3b3144be9dc25ef3f68740f1341dc9bb9c99b4 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 01:11:54 +0000 Subject: [PATCH 086/101] Remove prefix from field tests. --- src/field.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/field.rs b/src/field.rs index f18fdfd..2cfe7cd 100644 --- a/src/field.rs +++ b/src/field.rs @@ -954,7 +954,7 @@ mod test { 0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61, 0x21, 0x55]; #[test] - fn test_fieldelement_a_mul_a() { + fn fieldelement_a_mul_a() { let a = FieldElement::from_bytes(&A_BYTES); let asq = FieldElement::from_bytes(&ASQ_BYTES); assert_eq!(asq, &a*&a); @@ -962,35 +962,35 @@ mod test { } #[test] - fn test_fieldelement_a_square2() { + fn fieldelement_a_square2() { let a = FieldElement::from_bytes(&A_BYTES); let asq = FieldElement::from_bytes(&ASQ_BYTES); assert_eq!(a.square2(), &asq+&asq); } #[test] - fn test_fieldelement_a_inv() { + fn fieldelement_a_inv() { let a = FieldElement::from_bytes(&A_BYTES); let ainv = FieldElement::from_bytes(&AINV_BYTES); assert_eq!(ainv, a.invert()); } #[test] - fn test_fieldelement_a_p58() { + fn fieldelement_a_p58() { let a = FieldElement::from_bytes(&A_BYTES); let ap58 = FieldElement::from_bytes(&AP58_BYTES); assert_eq!(ap58, a.pow_p58()); } #[test] - fn test_fieldelement_a_chi() { + fn fieldelement_a_chi() { let a = FieldElement::from_bytes(&A_BYTES); // a is square assert_eq!(a.chi(), FieldElement::one()); } #[test] - fn test_fieldelement_eq() { + fn fieldelement_eq() { let a = FieldElement::from_bytes(&A_BYTES); let ainv = FieldElement::from_bytes(&AINV_BYTES); assert!(a == a); @@ -1006,7 +1006,7 @@ mod test { [-5652623, 8034020, 8266223, -13556020, -5672552, -5582839, -12603138, 15161929, -16418207, 13296296]); #[test] - fn test_fieldelement_frombytes_highbit_is_ignored() { + fn fieldelement_frombytes_highbit_is_ignored() { let mut cleared_bytes = B_BYTES.clone(); cleared_bytes[31] &= 127u8; let orig_elt = FieldElement::from_bytes(&B_BYTES); @@ -1017,7 +1017,7 @@ mod test { } #[test] - fn test_fieldelement_to_bytes() { + fn fieldelement_to_bytes() { let test_elt = FieldElement::from_bytes(&B_BYTES); for i in 0..10 { assert!(test_elt[i] == B_LIMBS[i]); @@ -1025,7 +1025,7 @@ mod test { } #[test] - fn test_fieldelement_from_bytes() { + fn fieldelement_from_bytes() { let test_bytes = B_LIMBS.to_bytes(); for i in 0..31 { assert!(test_bytes[i] == B_BYTES[i]); @@ -1035,7 +1035,7 @@ mod test { } #[test] - fn test_conditional_negate() { + fn conditional_negate() { let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); let mut x = one; From 4afe4ae37f3afcbe92e2697c6abcbad0a606a70d Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 01:52:42 +0000 Subject: [PATCH 087/101] Move scalar module benchmarks to separate module. --- src/scalar.rs | 59 ++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/scalar.rs b/src/scalar.rs index 0f70a19..5354d9b 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -592,44 +592,22 @@ impl UnpackedScalar { #[cfg(test)] mod test { - use rand::OsRng; use super::*; - use test::Bencher; - - #[bench] - fn bench_scalar_random(b: &mut Bencher) { - let mut csprng: OsRng = OsRng::new().unwrap(); - - b.iter(|| Scalar::random(&mut csprng)); - } - - #[bench] - fn bench_scalar_multiply_add(b: &mut Bencher) { - b.iter(|| Scalar::multiply_add(&X, &Y, &Z) ); - } - - #[bench] - fn bench_scalar_unpacked_multiply_add(b: &mut Bencher) { - let x = X.unpack(); - let y = Y.unpack(); - let z = Z.unpack(); - b.iter(|| UnpackedScalar::multiply_add(&x, &y, &z) ); - } /// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 - static X: Scalar = Scalar( + pub static X: Scalar = Scalar( [0x4e, 0x5a, 0xb4, 0x34, 0x5d, 0x47, 0x08, 0x84, 0x59, 0x13, 0xb4, 0x64, 0x1b, 0xc2, 0x7d, 0x52, 0x52, 0xa5, 0x85, 0x10, 0x1b, 0xcc, 0x42, 0x44, 0xd4, 0x49, 0xf4, 0xa8, 0x79, 0xd9, 0xf2, 0x04]); /// y = 2592331292931086675770238855846338635550719849568364935475441891787804997264 - static Y: Scalar = Scalar( + pub static Y: Scalar = Scalar( [0x90, 0x76, 0x33, 0xfe, 0x1c, 0x4b, 0x66, 0xa4, 0xa2, 0x8d, 0x2d, 0xd7, 0x67, 0x83, 0x86, 0xc3, 0x53, 0xd0, 0xde, 0x54, 0x55, 0xd4, 0xfc, 0x9d, 0xe8, 0xef, 0x7a, 0xc3, 0x1f, 0x35, 0xbb, 0x05]); /// z = 5033871415930814945849241457262266927579821285980625165479289807629491019013 - static Z: Scalar = Scalar( + pub static Z: Scalar = Scalar( [0x05, 0x9d, 0x3e, 0x0b, 0x09, 0x26, 0x50, 0x3d, 0xa3, 0x84, 0xa1, 0x3c, 0x92, 0x7a, 0xc2, 0x06, 0x41, 0x98, 0xcf, 0x34, 0x3a, 0x24, 0xd5, 0xb7, @@ -721,10 +699,39 @@ mod test { // Negating a scalar twice should result in the original scalar. #[test] - fn test_scalar_neg() { + fn scalar_neg() { let negative_x: Scalar = -X; let orig: Scalar = -negative_x; assert!(orig == X); } } + +#[cfg(test)] +mod bench { + use rand::OsRng; + use test::Bencher; + + use super::*; + use super::test::{X, Y, Z}; + + #[bench] + fn scalar_random(b: &mut Bencher) { + let mut csprng: OsRng = OsRng::new().unwrap(); + + b.iter(|| Scalar::random(&mut csprng)); + } + + #[bench] + fn scalar_multiply_add(b: &mut Bencher) { + b.iter(|| Scalar::multiply_add(&X, &Y, &Z) ); + } + + #[bench] + fn scalar_unpacked_multiply_add(b: &mut Bencher) { + let x = X.unpack(); + let y = Y.unpack(); + let z = Z.unpack(); + b.iter(|| UnpackedScalar::multiply_add(&x, &y, &z) ); + } +} From 3882a41d27f42290649badabb577d11741d256c7 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 01:58:39 +0000 Subject: [PATCH 088/101] Remove `test_` prefix from tests in scalar module. --- src/scalar.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/scalar.rs b/src/scalar.rs index 5354d9b..71f73cd 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -643,7 +643,7 @@ mod test { 0,0,0,0,0,-15,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,15,0,0,0,0,0,1,0,0,0,0]; #[test] - fn test_non_adjacent_form() { + fn non_adjacent_form() { let naf = A_SCALAR.non_adjacent_form(); for i in 0..256 { assert_eq!(naf[i], A_NAF[i]); @@ -651,7 +651,7 @@ mod test { } #[test] - fn test_scalar_multiply_by_one() { + fn scalar_multiply_by_one() { let one = Scalar::one(); let zero = Scalar::zero(); let test_scalar = Scalar::multiply_add(&X, &one, &zero); @@ -661,7 +661,7 @@ mod test { } #[test] - fn test_scalar_multiply_only() { + fn scalar_multiply_only() { let zero = Scalar::zero(); let test_scalar = Scalar::multiply_add(&X, &Y, &zero); for i in 0..32 { @@ -670,7 +670,7 @@ mod test { } #[test] - fn test_scalar_multiply_add() { + fn scalar_multiply_add() { let test_scalar = Scalar::multiply_add(&X, &Y, &Z); for i in 0..32 { assert!(test_scalar[i] == W[i]); @@ -678,7 +678,7 @@ mod test { } #[test] - fn test_scalar_reduce() { + fn scalar_reduce() { let mut bignum = [0u8;64]; // set bignum = x + 2^256x for i in 0..32 { From f6930997d2ab48ea44b282497995aff3e26aa126 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 01:59:08 +0000 Subject: [PATCH 089/101] Make #[feature(test)] depend on #[cfg(all(test, feature = "bench"))]. * FIXES Issue #38: https://github.com/isislovecruft/curve25519-dalek/pull/38 --- Cargo.toml | 1 + src/curve.rs | 2 +- src/decaf.rs | 2 +- src/field.rs | 2 +- src/lib.rs | 5 +++-- src/scalar.rs | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 691f464..242b13f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ version = "0.4" default = ["std"] std = ["rand"] yolocrypto = [] +bench = [] # The development profile, used for `cargo build`. [profile.dev] diff --git a/src/curve.rs b/src/curve.rs index a9cddf4..93ce31e 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1354,7 +1354,7 @@ mod test { // Benchmarks // ------------------------------------------------------------------------ -#[cfg(test)] +#[cfg(all(test, feature = "bench"))] mod bench { use test::Bencher; use constants; diff --git a/src/decaf.rs b/src/decaf.rs index db12cde..775186a 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -358,7 +358,7 @@ mod test { } } -#[cfg(test)] +#[cfg(all(test, feature = "bench"))] mod bench { use rand::OsRng; use test::Bencher; diff --git a/src/field.rs b/src/field.rs index 2cfe7cd..d83db26 100644 --- a/src/field.rs +++ b/src/field.rs @@ -1048,7 +1048,7 @@ mod test { } } -#[cfg(test)] +#[cfg(all(test, feature = "bench"))] mod bench { use test::Bencher; diff --git a/src/lib.rs b/src/lib.rs index 947a531..8903710 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(collections))] #![allow(unused_features)] -#![feature(test)] +#![cfg_attr(feature = "bench", feature(test))] #![deny(missing_docs)] // refuse to compile if documentation is missing //! # curve25519-dalek @@ -33,8 +33,9 @@ //! hatred of the Daleks. Rusty destroys the other Daleks and departs the //! ship, determined to track down and bring an end to the Dalek race. -#[cfg(test)] +#[cfg(all(test, feature = "bench"))] extern crate test; + #[cfg(test)] extern crate sha2; diff --git a/src/scalar.rs b/src/scalar.rs index 71f73cd..f7808e3 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -707,7 +707,7 @@ mod test { } } -#[cfg(test)] +#[cfg(all(test, feature = "bench"))] mod bench { use rand::OsRng; use test::Bencher; From bad1f259b9fdaa59a7af60ac692c6112f9b6393f Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 02:12:05 +0000 Subject: [PATCH 090/101] We expect tests to pass on stable and beta, but benches to fail. --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b8031d0..b2b782c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ rust: - nightly env: - - TEST_COMMAND=test - - TEST_COMMAND=bench + - TEST_COMMAND=test FEATURES='yolocrypto' + - TEST_COMMAND=bench FEATURES='yolocrypto bench' matrix: # We can probably remove this, as we reasonably expect dalek to work on @@ -16,7 +16,9 @@ matrix: # https://github.com/isislovecruft/curve25519-dalek/pull/38#issuecomment-286027562 allow_failures: - rust: stable + env: TEST_COMMAND=bench FEATURES='yolocrypto bench' - rust: beta + env: TEST_COMMAND=bench FEATURES='yolocrypto bench' script: - - cargo $TEST_COMMAND --features "yolocrypto" + - cargo $TEST_COMMAND --features="$FEATURES" From 26a77cd7f3a6dc325b2ddb77261f85f45a9968d4 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 03:21:32 +0000 Subject: [PATCH 091/101] Feature-gate box syntax on both std and basepoint_table_creation. --- src/curve.rs | 4 ++-- src/decaf.rs | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 054b164..4fad323 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -90,9 +90,9 @@ use subtle::CTAssignable; use subtle::CTEq; use subtle::CTNegatable; -#[cfg(not(feature = "std"))] +#[cfg(all(not(feature = "std"), feature = "basepoint_table_creation"))] use collections::boxed::Box; -#[cfg(feature = "std")] +#[cfg(all(feature = "std", feature = "basepoint_table_creation"))] use std::boxed::Box; // ------------------------------------------------------------------------ diff --git a/src/decaf.rs b/src/decaf.rs index 71a8d1c..0bee7de 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -31,7 +31,9 @@ use subtle::CTNegatable; use core::ops::{Add, Sub, Neg}; -#[cfg(feature = "std")] +#[cfg(all(not(feature = "std"), feature = "basepoint_table_creation"))] +use collections::boxed::Box; +#[cfg(all(feature = "std", feature = "basepoint_table_creation"))] use std::boxed::Box; use curve::ExtendedPoint; @@ -272,6 +274,7 @@ pub struct DecafBasepointTable(EdwardsBasepointTable); impl DecafBasepointTable { /// Create a precomputed table of multiples of the given `basepoint`. + #[cfg(feature = "basepoint_table_creation")] pub fn create(basepoint: &DecafPoint) -> Box { let edwards_table = EdwardsBasepointTable::create(&basepoint.0); box DecafBasepointTable(*edwards_table) @@ -381,6 +384,7 @@ mod test { /// Test basepoint_mult versus a newly-generated DecafBasepointTable #[test] + #[cfg(feature = "basepoint_table_creation")] fn basepoint_mult_vs_decafbasepointtable() { let table = DecafBasepointTable::create(&DecafPoint::basepoint()); let mut rng = OsRng::new().unwrap(); From b8b5af24b642d8e2e08a7515a8a5efc93362debe Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 20:24:59 -0700 Subject: [PATCH 092/101] fixup! Enable radix_51 on nightly --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index af82b41..e29a4fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,9 +12,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(collections))] #![cfg_attr(feature = "nightly", feature(box_syntax))] +#![cfg_attr(feature = "nightly", feature(i128_type))] #![allow(unused_features)] #![feature(test)] -#![feature(i128_type)] #![deny(missing_docs)] // refuse to compile if documentation is missing //! # curve25519-dalek From 5d48526be76be686094caa2db519a88b44788884 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 03:32:17 +0000 Subject: [PATCH 093/101] Add a Travis badge to the README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 529b724..430b8b3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# curve25519-dalek ![](https://img.shields.io/crates/v/curve25519-dalek.svg) ![](https://docs.rs/curve25519-dalek/badge.svg) +# curve25519-dalek ![](https://img.shields.io/crates/v/curve25519-dalek.svg) ![](https://docs.rs/curve25519-dalek/badge.svg) ![](https://travis-ci.org/isislovecruft/curve25519-dalek.svg?branch=master) **A low-level cryptographic library for point, group, field, and scalar operations on a curve isomorphic to the twisted Edwards curve defined by -x²+y² From 58c60526dadf2e21f13436a4b5516681b26a5fb3 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Tue, 14 Mar 2017 03:38:13 +0000 Subject: [PATCH 094/101] Add a Travis badge to the Cargo.toml package. --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 0c90b01..3f232e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,9 @@ exclude = [ ".gitignore" ] +[badges] +travis-ci = { repository = "isislovecruft/curve25519-dalek", branch = "master"} + [dependencies.arrayref] version = "0.3.3" From d0980b6c8a8abca81cbfe04793b88055a9fb00ff Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 21:59:42 -0700 Subject: [PATCH 095/101] Test radix_51, but exclude bench and radix_51 from stable/beta builds. --- .travis.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2b782c..082ae3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,18 +7,24 @@ rust: env: - TEST_COMMAND=test FEATURES='yolocrypto' + - TEST_COMMAND=test FEATURES='yolocrypto radix_51' - TEST_COMMAND=bench FEATURES='yolocrypto bench' matrix: - # We can probably remove this, as we reasonably expect dalek to work on - # stable and beta, but currently we require "test" feature in order to - # run benchmarks, which causes dalek not to build on stable. See - # https://github.com/isislovecruft/curve25519-dalek/pull/38#issuecomment-286027562 - allow_failures: + exclude: + # We can probably remove this, as we reasonably expect dalek to work on + # stable and beta, but currently we require "test" feature in order to + # run benchmarks, which causes dalek not to build on stable. See + # https://github.com/isislovecruft/curve25519-dalek/pull/38#issuecomment-286027562 - rust: stable env: TEST_COMMAND=bench FEATURES='yolocrypto bench' - rust: beta env: TEST_COMMAND=bench FEATURES='yolocrypto bench' + # radix_51 requires nightly for u128 + - rust: stable + env: TEST_COMMAND=test FEATURES='yolocrypto radix_51' + - rust: beta + env: TEST_COMMAND=test FEATURES='yolocrypto radix_51' script: - cargo $TEST_COMMAND --features="$FEATURES" From 5d03c2a3ba29f400b297549dbbe7f978585fcdc0 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 22:07:56 -0700 Subject: [PATCH 096/101] 2nd attempt at fixing Travis config Test nightly features on nightly channel. --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 082ae3b..38c6fd3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ rust: env: - TEST_COMMAND=test FEATURES='yolocrypto' - - TEST_COMMAND=test FEATURES='yolocrypto radix_51' + - TEST_COMMAND=test FEATURES='yolocrypto nightly' - TEST_COMMAND=bench FEATURES='yolocrypto bench' matrix: @@ -20,11 +20,11 @@ matrix: env: TEST_COMMAND=bench FEATURES='yolocrypto bench' - rust: beta env: TEST_COMMAND=bench FEATURES='yolocrypto bench' - # radix_51 requires nightly for u128 + # Test nightly features, such as radix_51, only on nightly. - rust: stable - env: TEST_COMMAND=test FEATURES='yolocrypto radix_51' + env: TEST_COMMAND=test FEATURES='yolocrypto nightly' - rust: beta - env: TEST_COMMAND=test FEATURES='yolocrypto radix_51' + env: TEST_COMMAND=test FEATURES='yolocrypto nightly' script: - cargo $TEST_COMMAND --features="$FEATURES" From 383750119b2c30ee5cd1b689bdc31852ab025dd0 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 22:21:57 -0700 Subject: [PATCH 097/101] Benchmark with nightly features --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 38c6fd3..9e49f62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ rust: env: - TEST_COMMAND=test FEATURES='yolocrypto' - TEST_COMMAND=test FEATURES='yolocrypto nightly' - - TEST_COMMAND=bench FEATURES='yolocrypto bench' + - TEST_COMMAND=bench FEATURES='yolocrypto nightly bench' matrix: exclude: @@ -17,9 +17,9 @@ matrix: # run benchmarks, which causes dalek not to build on stable. See # https://github.com/isislovecruft/curve25519-dalek/pull/38#issuecomment-286027562 - rust: stable - env: TEST_COMMAND=bench FEATURES='yolocrypto bench' + env: TEST_COMMAND=bench FEATURES='yolocrypto nightly bench' - rust: beta - env: TEST_COMMAND=bench FEATURES='yolocrypto bench' + env: TEST_COMMAND=bench FEATURES='yolocrypto nightly bench' # Test nightly features, such as radix_51, only on nightly. - rust: stable env: TEST_COMMAND=test FEATURES='yolocrypto nightly' From 35db90c4f3226d22800968f254930f6b185c1663 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 13 Mar 2017 22:29:39 -0700 Subject: [PATCH 098/101] Benchmark both implementations --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9e49f62..526648e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ rust: env: - TEST_COMMAND=test FEATURES='yolocrypto' - TEST_COMMAND=test FEATURES='yolocrypto nightly' + - TEST_COMMAND=bench FEATURES='yolocrypto bench' - TEST_COMMAND=bench FEATURES='yolocrypto nightly bench' matrix: @@ -16,6 +17,10 @@ matrix: # stable and beta, but currently we require "test" feature in order to # run benchmarks, which causes dalek not to build on stable. See # https://github.com/isislovecruft/curve25519-dalek/pull/38#issuecomment-286027562 + - rust: stable + env: TEST_COMMAND=bench FEATURES='yolocrypto bench' + - rust: beta + env: TEST_COMMAND=bench FEATURES='yolocrypto bench' - rust: stable env: TEST_COMMAND=bench FEATURES='yolocrypto nightly bench' - rust: beta From 2f5b9e198cb9cc1749319bd32d4b951f9e099146 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 14 Mar 2017 01:05:31 -0700 Subject: [PATCH 099/101] Remove warnings from load3/load4 and load8 functions --- src/field.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/field.rs b/src/field.rs index b365979..78dcc9b 100644 --- a/src/field.rs +++ b/src/field.rs @@ -29,7 +29,10 @@ use subtle::byte_is_nonzero; use subtle::CTAssignable; use subtle::CTEq; -use utils::{load3, load4, load8}; +#[cfg(not(feature="radix_51"))] +use utils::{load3, load4}; +#[cfg(feature="radix_51")] +use utils::load8; use constants; From b6a71304c8d0ad46d829b1a9762d61eac236fa65 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 14 Mar 2017 01:53:05 -0700 Subject: [PATCH 100/101] Bump version --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f06374a..c164472 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "curve25519-dalek" -version = "0.5.0" +version = "0.6.0" authors = ["Isis Lovecruft ", "Henry de Valence "] readme = "README.md" diff --git a/README.md b/README.md index 430b8b3..e070e9c 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Extensive documentation is available [here](https://docs.rs/curve25519-dalek). To install, add the following to the dependencies section of your project's `Cargo.toml`: - curve25519-dalek = "^0.5" + curve25519-dalek = "^0.6" Then, in your library or executable source, add: From a6618351f0eb2abb73ede97fc844a5522d486e13 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 14 Mar 2017 01:53:26 -0700 Subject: [PATCH 101/101] Add note about nightly feature --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e070e9c..ef10f59 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ Then, in your library or executable source, add: extern crate curve25519_dalek +On nightly Rust, using the `nightly` feature enables a radix-51 field +arithmetic implementation using `u128`s, which is approximately twice as +fast. + ## TODO * Implement hashing to a point on the curve (Elligator).