Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add group ops #8

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
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
153 changes: 153 additions & 0 deletions src/edwards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//! 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};

use crate::field::{FieldElement, EDWARDS_D};
use crate::Ristretto255Scalar;

// ------------------------------------------------------------------------
// 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.
// 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,
}
}
}

// ------------------------------------------------------------------------
// Addition and Subtraction
// ------------------------------------------------------------------------

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: FieldElement = 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,
}
}
}

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 {
// 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,
}
}
}

// ------------------------------------------------------------------------
// 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
}
}
14 changes: 13 additions & 1 deletion src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -182,6 +186,14 @@ impl Into<Ristretto255Scalar> for FieldElement {
}
}

impl Neg for FieldElement {
type Output = Self;

fn neg(self) -> Self {
unimplemented!()
}
}

impl FieldElement {
pub fn zero() -> FieldElement {
FieldElement([0; 5])
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub type Ristretto255Scalar = curve25519_dalek::scalar::Scalar;

mod edwards;
mod field;

#[cfg(test)]
Expand Down