From ac3a8fefc1a5a654ecde483e95ba8961faa3a2ae Mon Sep 17 00:00:00 2001 From: Cathie Yun Date: Mon, 8 Apr 2019 23:13:54 -0700 Subject: [PATCH 1/4] skeleton for group operations --- src/edwards.rs | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ src/field.rs | 14 ++++++- src/lib.rs | 1 + 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/edwards.rs diff --git a/src/edwards.rs b/src/edwards.rs new file mode 100644 index 0000000..3738662 --- /dev/null +++ b/src/edwards.rs @@ -0,0 +1,101 @@ +#![allow(non_snake_case)] + +use crate::field::{FieldElement, EDWARDS_D}; +use core::ops::{Add, Neg, Sub}; + +// ------------------------------------------------------------------------ +// Internal point representations +// ------------------------------------------------------------------------ + +/// An `EdwardsPoint` represents a point on the Edwards form of the Doppio curve. +#[derive(Copy, Clone)] +#[allow(missing_docs)] +pub struct EdwardsPoint { + pub(crate) X: FieldElement, + pub(crate) Y: FieldElement, + pub(crate) Z: FieldElement, + pub(crate) T: FieldElement, +} + +// ------------------------------------------------------------------------ +// Constructors +// ------------------------------------------------------------------------ + +impl Default for EdwardsPoint { + fn default() -> EdwardsPoint { + EdwardsPoint { + X: FieldElement::zero(), + Y: FieldElement::one(), + Z: FieldElement::one(), + T: FieldElement::zero(), + } + } +} + +// ------------------------------------------------------------------------ +// Doubling +// ------------------------------------------------------------------------ + +impl EdwardsPoint { + /// Add this point to itself. + pub(crate) fn double(&self) -> EdwardsPoint { + self + self + } +} + +// ------------------------------------------------------------------------ +// Addition and Subtraction +// ------------------------------------------------------------------------ + +impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { + type Output = EdwardsPoint; + fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint { + let A = self.X * other.X; + let B = self.Y * other.Y; + let C = EDWARDS_D * self.T * other.T; + 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; + + EdwardsPoint { + X: E * F, + Y: G * H, + Z: F * G, + T: E * H, + } + } +} + +impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint { + type Output = EdwardsPoint; + fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint { + self + &-other + } +} + +// ------------------------------------------------------------------------ +// Negation +// ------------------------------------------------------------------------ + +impl<'a> Neg for &'a EdwardsPoint { + type Output = EdwardsPoint; + + fn neg(self) -> EdwardsPoint { + EdwardsPoint { + X: -self.X, + Y: self.Y, + Z: self.Z, + T: -self.T, + } + } +} + +impl Neg for EdwardsPoint { + type Output = EdwardsPoint; + + fn neg(self) -> EdwardsPoint { + -&self + } +} diff --git a/src/field.rs b/src/field.rs index efc1d1b..ebc67af 100644 --- a/src/field.rs +++ b/src/field.rs @@ -8,10 +8,14 @@ //! implementation contributed to `curve25519-dalek` by Andrew Moon. use std::default::Default; -use std::ops::{Add, Mul, Sub}; +use std::ops::{Add, Mul, Neg, Sub}; use crate::Ristretto255Scalar; +/// Edwards `d` value, equal to `-86649/86650 mod p`. +/// TODO: actually generate the right value here +pub(crate) const EDWARDS_D: FieldElement = FieldElement([0; 5]); + /// A field element modulo \\(2\^{252} + /// 27742317777372353535851937790883648493\\), the ground field for /// the doppio curve and the scalar field for the ristretto255 group. @@ -57,6 +61,14 @@ impl Into for FieldElement { } } +impl Neg for FieldElement { + type Output = Self; + + fn neg(self) -> Self { + unimplemented!() + } +} + impl FieldElement { pub fn zero() -> FieldElement { FieldElement([0; 5]) diff --git a/src/lib.rs b/src/lib.rs index 937ea92..76567a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ pub type Ristretto255Scalar = curve25519_dalek::scalar::Scalar; +mod edwards; mod field; #[cfg(test)] From 8260245bd61753958b7a8029b97075f6c0afe83b Mon Sep 17 00:00:00 2001 From: Cathie Yun Date: Mon, 8 Apr 2019 23:31:20 -0700 Subject: [PATCH 2/4] update addition formula for a=-1 special case --- src/edwards.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/edwards.rs b/src/edwards.rs index 3738662..60345fd 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -1,8 +1,10 @@ #![allow(non_snake_case)] -use crate::field::{FieldElement, EDWARDS_D}; use core::ops::{Add, Neg, Sub}; +use crate::field::{FieldElement, EDWARDS_D}; +use crate::Ristretto255Scalar; + // ------------------------------------------------------------------------ // Internal point representations // ------------------------------------------------------------------------ @@ -50,11 +52,15 @@ impl EdwardsPoint { impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { type Output = EdwardsPoint; fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint { - let A = self.X * other.X; - let B = self.Y * other.Y; - let C = EDWARDS_D * self.T * other.T; - let D = self.Z * other.Z; - let E = (self.X + self.Y) * (other.X + other.Y) - A - B; + // k = 2d'. d' = -d/a and a = -1, so k = 2d. + let two = Ristretto255Scalar::from(2u8).into(); + let k = EDWARDS_D * two; + + let A = (self.Y - self.X) * (other.Y - other.X); + let B = (self.Y + self.X) * (other.Y + other.X); + let C = k * self.T * other.T; + let D = two * self.Z * other.Z; + let E = B - A; let F = D - C; let G = D + C; let H = B + A; From 5bad4dab4007acb6da6e7f71539c8e2c45b0b48b Mon Sep 17 00:00:00 2001 From: Cathie Yun Date: Sun, 21 Apr 2019 09:56:37 -0700 Subject: [PATCH 3/4] add equation for subtraction --- src/edwards.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/edwards.rs b/src/edwards.rs index 60345fd..be390ed 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -76,8 +76,29 @@ impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint { type Output = EdwardsPoint; + + // TODO: add a test that A - B = A + -B fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint { - self + &-other + // The same equation as addition, except other.X and other.T are negated. + // k = 2d'. d' = -d/a and a = -1, so k = 2d. + let two = Ristretto255Scalar::from(2u8).into(); + let k = EDWARDS_D * two; + + let A = (self.Y - self.X) * (other.Y + other.X); + let B = (self.Y + self.X) * (other.Y - other.X); + let C = k * self.T * other.T; + let D = two * self.Z * other.Z; + let E = B - A; + let F = D + C; + let G = D - C; + let H = B + A; + + EdwardsPoint { + X: E * F, + Y: G * H, + Z: F * G, + T: E * H, + } } } From 8da73e4d9a25e9b4aa8217f8ff3f80418c5de329 Mon Sep 17 00:00:00 2001 From: Cathie Yun Date: Sun, 21 Apr 2019 10:06:45 -0700 Subject: [PATCH 4/4] add equations for doubling and subtraction --- src/edwards.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/edwards.rs b/src/edwards.rs index be390ed..11dd05c 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -1,3 +1,8 @@ +//! Point arithmetic for the doppio curve. +//! +//! This implements the equations for point arithmetic from +//! HWCD: https://eprint.iacr.org/2008/522.pdf + #![allow(non_snake_case)] use core::ops::{Add, Neg, Sub}; @@ -40,8 +45,27 @@ impl Default for EdwardsPoint { impl EdwardsPoint { /// Add this point to itself. - pub(crate) fn double(&self) -> EdwardsPoint { - self + self + // TODO: add a test that A.double() = A * A + fn double(&self) -> EdwardsPoint { + let two: FieldElement = Ristretto255Scalar::from(2u8).into(); + + let A = self.X * self.X; + let B = self.Y * self.Y; + // Is it cheaper to add Z*Z + Z*Z or multiply 2*Z*Z? + let C = two * self.Z * self.Z; + // a = -1 + let D = -A; + let E = (self.X + self.Y) * (self.X + self.Y) - A - B; + let G = D + B; + let F = G - C; + let H = D - B; + + EdwardsPoint { + X: E * F, + Y: G * H, + Z: F * G, + T: E * H, + } } } @@ -51,9 +75,10 @@ impl EdwardsPoint { impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { type Output = EdwardsPoint; + fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint { // k = 2d'. d' = -d/a and a = -1, so k = 2d. - let two = Ristretto255Scalar::from(2u8).into(); + let two: FieldElement = Ristretto255Scalar::from(2u8).into(); let k = EDWARDS_D * two; let A = (self.Y - self.X) * (other.Y - other.X);