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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions ed448-goldilocks/src/curve/scalar_mul/double_and_add.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::curve::twedwards::extended::ExtendedPoint;
use crate::curve::twedwards::extensible::ExtensiblePoint;
use subtle::{Choice, ConditionallySelectable};

/// Traditional double and add algorithm
pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> ExtendedPoint {
let mut result = ExtendedPoint::IDENTITY;
pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> ExtensiblePoint {
let mut result = ExtensiblePoint::IDENTITY;

// NB, we reverse here, so we are going from MSB to LSB
// XXX: Would be great if subtle had a From<u32> for Choice. But maybe that is not it's purpose?
Expand All @@ -12,7 +13,7 @@ pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> Exte

let mut p = ExtendedPoint::IDENTITY;
p.conditional_assign(point, Choice::from(bit as u8));
result = result.add(&p);
result = result.to_extended().add_extended(&p);
}

result
Expand Down
13 changes: 6 additions & 7 deletions ed448-goldilocks/src/curve/scalar_mul/variable_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::EdwardsScalar;
use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
use subtle::{Choice, ConditionallyNegatable};

pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtendedPoint {
pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtensiblePoint {
let mut result = ExtensiblePoint::IDENTITY;

// Recode Scalar
Expand All @@ -28,10 +28,10 @@ pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtendedPoint
let mut neg_P = lookup.select(abs_value);
neg_P.conditional_negate(Choice::from((sign) as u8));

result = result.add_projective_niels(&neg_P);
result = result.to_extended().add_projective_niels(&neg_P);
}

result.to_extended()
result
}

#[cfg(test)]
Expand All @@ -57,7 +57,7 @@ mod test {
// Lets see if this is conserved over the isogenies
let edwards_point = twisted_point.to_untwisted();
let got_untwisted_point = edwards_point.scalar_mul(&scalar);
let expected_untwisted_point = got.to_untwisted();
let expected_untwisted_point = got.to_extended().to_untwisted();
assert_eq!(got_untwisted_point, expected_untwisted_point);
}

Expand All @@ -69,9 +69,8 @@ mod test {
let exp = variable_base(&x, &EdwardsScalar::from(1u8));
assert!(x == exp);
// Test that 2 * (P + P) = 4 * P
let x_ext = x.to_extensible();
let expected_two_x = x_ext.add_extensible(&x_ext).double();
let expected_two_x = x.add_extended(&x).double();
let got = variable_base(&x, &EdwardsScalar::from(4u8));
assert!(expected_two_x.to_extended() == got);
assert!(expected_two_x == got);
}
}
16 changes: 7 additions & 9 deletions ed448-goldilocks/src/curve/scalar_mul/window/wnaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ pub struct LookupTable([ProjectiveNielsPoint; 8]);

/// Precomputes odd multiples of the point passed in
impl From<&ExtendedPoint> for LookupTable {
fn from(point: &ExtendedPoint) -> LookupTable {
let P = point.to_extensible();

fn from(P: &ExtendedPoint) -> LookupTable {
let mut table = [P.to_projective_niels(); 8];

for i in 1..8 {
table[i] = P.add_projective_niels(&table[i - 1]).to_projective_niels();
table[i] = P
.add_projective_niels(&table[i - 1])
.to_extended()
.to_projective_niels();
}

LookupTable(table)
Expand Down Expand Up @@ -42,11 +43,8 @@ fn test_lookup() {
let mut expected_point = ExtendedPoint::IDENTITY;
for i in 0..8 {
let selected_point = points.select(i);
assert_eq!(selected_point.to_extended(), expected_point);
assert_eq!(selected_point.to_extensible(), expected_point);

expected_point = expected_point
.to_extensible()
.add_extended(&p)
.to_extended();
expected_point = expected_point.add_extended(&p).to_extended();
}
}
15 changes: 12 additions & 3 deletions ed448-goldilocks/src/curve/twedwards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@ use crate::field::FieldElement;
pub(crate) struct IsogenyMap {
pub(crate) X: FieldElement,
pub(crate) Y: FieldElement,
pub(crate) Z: FieldElement,
pub(crate) T: FieldElement,
}

pub(crate) struct IsogenyMapResult {
pub(crate) X: FieldElement,
pub(crate) Y: FieldElement,
pub(crate) Z: FieldElement,
pub(crate) T1: FieldElement,
pub(crate) T2: FieldElement,
}

impl IsogenyMap {
// (1.) https://eprint.iacr.org/2014/027.pdf
pub(crate) fn map(&self, scale: impl FnOnce(FieldElement) -> FieldElement) -> Self {
pub(crate) fn map(&self, scale: impl FnOnce(FieldElement) -> FieldElement) -> IsogenyMapResult {
// x = 2xy / (y^2 - a*x^2)
// y = (y^2 + a*x^2) / (2 - y^2 - a*x^2)

Expand Down Expand Up @@ -53,9 +61,10 @@ impl IsogenyMap {

let X = x_numerator * y_denom;
let Y = y_numerator * x_denom;
let T = x_numerator * y_numerator;
let Z = x_denom * y_denom;
let T1 = x_numerator;
let T2 = y_numerator;

Self { X, Y, T, Z }
IsogenyMapResult { X, Y, Z, T1, T2 }
}
}
11 changes: 6 additions & 5 deletions ed448-goldilocks/src/curve/twedwards/affine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,14 @@ impl AffineNielsPoint {
&& (self.td == other.td)
}

/// Converts an AffineNielsPoint to an ExtendedPoint
pub(crate) fn to_extended(self) -> ExtendedPoint {
ExtendedPoint {
/// Converts an AffineNielsPoint to an ExtensiblePoint
pub(crate) fn to_extensible(self) -> ExtensiblePoint {
ExtensiblePoint {
X: self.y_plus_x - self.y_minus_x,
Y: self.y_minus_x + self.y_plus_x,
Z: FieldElement::ONE,
T: self.y_plus_x * self.y_minus_x,
T1: self.y_plus_x,
T2: self.y_minus_x,
}
}
}
Expand All @@ -140,7 +141,7 @@ mod tests {
#[test]
fn test_negation() {
use crate::TWISTED_EDWARDS_BASE_POINT;
let a = TWISTED_EDWARDS_BASE_POINT.to_affine();
let a = TWISTED_EDWARDS_BASE_POINT.to_extensible().to_affine();
assert!(a.is_on_curve());

let neg_a = a.negate();
Expand Down
154 changes: 119 additions & 35 deletions ed448-goldilocks/src/curve/twedwards/extended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#![allow(dead_code)]

use super::IsogenyMap;
use super::affine::AffinePoint;
use super::extensible::ExtensiblePoint;
use super::projective::ProjectiveNielsPoint;
use super::{IsogenyMapResult, affine::AffineNielsPoint};
use crate::edwards::EdwardsPoint as EdwardsExtendedPoint;
use crate::field::FieldElement;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
Expand Down Expand Up @@ -44,6 +45,11 @@ impl PartialEq for ExtendedPoint {
self.ct_eq(other).into()
}
}
impl PartialEq<ExtensiblePoint> for ExtendedPoint {
fn eq(&self, other: &ExtensiblePoint) -> bool {
self.to_extensible().ct_eq(other).into()
}
}
impl Eq for ExtendedPoint {}

impl Default for ExtendedPoint {
Expand All @@ -70,14 +76,90 @@ impl ExtendedPoint {
T: FieldElement::ZERO,
};

/// Doubles an extended point
pub(crate) fn double(&self) -> ExtendedPoint {
self.to_extensible().double().to_extended()
/// Adds an extensible point to an extended point
/// Returns an extensible point
/// (3.1) https://iacr.org/archive/asiacrypt2008/53500329/53500329.pdf
pub fn add_extended(&self, other: &ExtendedPoint) -> ExtensiblePoint {
let A = self.X * other.X;
let B = self.Y * other.Y;
let C = self.T * other.T * FieldElement::TWISTED_D;
let D = self.Z * other.Z;
let E = (self.X + self.Y) * (other.X + other.Y) - A - B;
let F = D - C;
let G = D + C;
let H = B + A;
ExtensiblePoint {
X: E * F,
Y: G * H,
T1: E,
T2: H,
Z: F * G,
}
}

/// Adds an extended point to itself
pub(crate) fn add(&self, other: &ExtendedPoint) -> ExtendedPoint {
self.to_extensible().add_extended(other).to_extended()
/// Subtracts an extensible point from an extended point
/// Returns an extensible point
/// This is a direct modification of the addition formula to the negation of `other`
pub fn sub_extended(&self, other: &ExtendedPoint) -> ExtensiblePoint {
let A = self.X * other.X;
let B = self.Y * other.Y;
let C = self.T * other.T * FieldElement::TWISTED_D;
let D = self.Z * other.Z;
let E = (self.X + self.Y) * (other.Y - other.X) + A - B;
let F = D + C;
let G = D - C;
let H = B - A;
ExtensiblePoint {
X: E * F,
Y: G * H,
T1: E,
T2: H,
Z: F * G,
}
}

/// Adds an extensible point to an AffineNiels point
/// Returns an Extensible point
pub fn add_affine_niels(&self, other: AffineNielsPoint) -> ExtensiblePoint {
let A = other.y_minus_x * (self.Y - self.X);
let B = other.y_plus_x * (self.X + self.Y);
let C = other.td * self.T;
let D = B + A;
let E = B - A;
let F = self.Z - C;
let G = self.Z + C;
ExtensiblePoint {
X: E * F,
Y: G * D,
Z: F * G,
T1: E,
T2: D,
}
}

/// Adds an extensible point to a ProjectiveNiels point
/// Returns an extensible point
/// (3.1)[Last set of formulas] https://iacr.org/archive/asiacrypt2008/53500329/53500329.pdf
/// This differs from the formula above by a factor of 2. Saving 1 Double
/// Cost 8M
pub fn add_projective_niels(&self, other: &ProjectiveNielsPoint) -> ExtensiblePoint {
// This is the only step which makes it different than adding an AffineNielsPoint
let Z = self.Z * other.Z;

let A = (self.Y - self.X) * other.Y_minus_X;
let B = (self.Y + self.X) * other.Y_plus_X;
let C = other.Td * self.T;
let D = B + A;
let E = B - A;
let F = Z - C;
let G = Z + C;
ExtensiblePoint {
X: E * F,
Y: G * D,
Z: F * G,
T1: E,
T2: D,
}
}

/// Converts an ExtendedPoint to an ExtensiblePoint
Expand All @@ -91,31 +173,32 @@ impl ExtendedPoint {
}
}

/// Converts an extended point to Affine co-ordinates
pub(crate) fn to_affine(self) -> AffinePoint {
// Points to consider:
// - All points where Z=0, translate to (0,0)
// - The identity point has z=1, so it is not a problem

let INV_Z = self.Z.invert();

let x = self.X * INV_Z;
let y = self.Y * INV_Z;

AffinePoint { x, y }
}

/// Uses a 2-isogeny to map the point to the Ed448-Goldilocks
pub fn to_untwisted(self) -> EdwardsExtendedPoint {
let IsogenyMap { X, Y, T, Z } = IsogenyMap {
let IsogenyMapResult { X, Y, Z, T1, T2 } = IsogenyMap {
X: self.X,
Y: self.Y,
T: self.T,
Z: self.Z,
T: self.T,
}
.map(|f| -f);

EdwardsExtendedPoint { X, Y, Z, T }
EdwardsExtendedPoint {
X,
Y,
Z,
T: T1 * T2,
}
}

/// Converts an Extensible point to a ProjectiveNiels Point
pub fn to_projective_niels(self) -> ProjectiveNielsPoint {
ProjectiveNielsPoint {
Y_plus_X: self.X + self.Y,
Y_minus_X: self.Y - self.X,
Z: self.Z.double(),
Td: self.T * FieldElement::TWO_TIMES_TWISTED_D,
}
}

/// Checks if the point is on the curve
Expand Down Expand Up @@ -159,6 +242,7 @@ impl ExtendedPoint {
#[cfg(test)]
mod tests {
use super::*;
use crate::curve::twedwards::affine::AffinePoint;
use crate::{GOLDILOCKS_BASE_POINT, TWISTED_EDWARDS_BASE_POINT};

fn hex_to_field(hex: &'static str) -> FieldElement {
Expand All @@ -177,8 +261,8 @@ mod tests {
let y = hex_to_field(
"ae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed",
);
let a = AffinePoint { x, y }.to_extended();
let twist_a = a.to_untwisted().to_twisted();
let a = AffinePoint { x, y }.to_extensible();
let twist_a = a.to_extended().to_untwisted().to_twisted();
assert_eq!(twist_a, a.double().double())
}

Expand All @@ -201,28 +285,28 @@ mod tests {
#[test]
fn test_point_add() {
let a = TWISTED_EDWARDS_BASE_POINT;
let b = a.double();
let b = a.to_extensible().double().to_extended();

// A + B = B + A = C
let c_1 = a.to_extensible().add_extended(&b).to_extended();
let c_2 = b.to_extensible().add_extended(&a).to_extended();
let c_1 = a.add_extended(&b).to_extended();
let c_2 = b.add_extended(&a).to_extended();
assert!(c_1 == c_2);

// Adding identity point should not change result
let c = c_1.to_extensible().add_extended(&ExtendedPoint::IDENTITY);
assert!(c.to_extended() == c_1);
let c = c_1.add_extended(&ExtendedPoint::IDENTITY);
assert!(c == c_1);
}

#[test]
fn test_point_sub() {
let a = TWISTED_EDWARDS_BASE_POINT;
let b = a.double();
let b = a.to_extensible().double().to_extended();

// A - B = C
let c_1 = a.to_extensible().sub_extended(&b).to_extended();
let c_1 = a.sub_extended(&b).to_extended();

// -B + A = C
let c_2 = b.negate().to_extensible().add_extended(&a).to_extended();
let c_2 = b.negate().add_extended(&a).to_extended();
assert!(c_1 == c_2);
}

Expand All @@ -231,6 +315,6 @@ mod tests {
let a = TWISTED_EDWARDS_BASE_POINT;
let neg_a = a.negate();

assert!(a.to_extensible().add_extended(&neg_a) == ExtensiblePoint::IDENTITY);
assert!(a.add_extended(&neg_a) == ExtensiblePoint::IDENTITY);
}
}
Loading