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

fix: add twisted edwards trait + proper constants #22

Merged
Show file tree
Hide file tree
Changes from 5 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
75 changes: 45 additions & 30 deletions src/ed25519/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use core::fmt::Debug;
use core::iter::Sum;
use core::ops::{Add, Mul, Neg, Sub};
use ff::{BatchInverter, Field, PrimeField};
use group::{self, Curve, Group};
use group::{self, Curve};
use group::{prime::PrimeCurveAffine, GroupEncoding};
use rand::RngCore;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -57,7 +57,7 @@ pub struct Ed25519Affine {
pub y: Fq,
}

#[derive(Copy, Clone, Hash)]
#[derive(Copy, Clone, Hash, Default)]
pub struct Ed25519Compressed([u8; 32]);

impl Ed25519 {
Expand Down Expand Up @@ -103,7 +103,7 @@ impl Ed25519 {
.skip(3)
{
acc = acc.double();
acc += Ed25519::conditional_select(&zero, &self, bit);
acc += Ed25519::conditional_select(&zero, self, bit);
}

acc
Expand Down Expand Up @@ -155,12 +155,6 @@ impl Ed25519 {
}
}

impl Ed25519 {
fn endomorphism_base(&self) -> Self {
unimplemented!();
}
}

impl Ed25519Affine {
/// Constructs the neutral element `(0, 1)`.
pub const fn identity() -> Self {
Expand Down Expand Up @@ -287,12 +281,6 @@ impl std::fmt::Debug for Ed25519Compressed {
}
}

impl Default for Ed25519Compressed {
fn default() -> Self {
Ed25519Compressed([0; 32])
}
}

impl AsRef<[u8]> for Ed25519Compressed {
fn as_ref(&self) -> &[u8] {
&self.0
Expand Down Expand Up @@ -357,8 +345,13 @@ impl CurveExt for Ed25519 {

const CURVE_ID: &'static str = "ed25519";

fn is_on_curve(&self) -> Choice {
let affine = Ed25519Affine::from(*self);
!self.z.is_zero() & affine.is_on_curve() & (affine.x * affine.y * self.z).ct_eq(&self.t)
shuklaayush marked this conversation as resolved.
Show resolved Hide resolved
}

fn endo(&self) -> Self {
self.endomorphism_base()
unimplemented!();
}

fn jacobian_coordinates(&self) -> (Fq, Fq, Fq) {
Expand All @@ -369,20 +362,12 @@ impl CurveExt for Ed25519 {
unimplemented!();
}

fn is_on_curve(&self) -> Choice {
let affine = Ed25519Affine::from(*self);

println!("affine: {:?}", affine);

!self.z.is_zero() & affine.is_on_curve() & (affine.x * affine.y * self.z).ct_eq(&self.t)
}

fn a() -> Self::Base {
unimplemented!()
}

fn b() -> Self::Base {
ED25519_D
unimplemented!()
}

fn new_jacobian(_x: Self::Base, _y: Self::Base, _z: Self::Base) -> CtOption<Self> {
Expand All @@ -408,8 +393,8 @@ impl group::Curve for Ed25519 {
let tmp = q.x;

// Set the coordinates to the correct value
q.x = p.x * &tmp; // Multiply by 1/z
q.y = p.y * &tmp; // Multiply by 1/z
q.x = p.x * tmp; // Multiply by 1/z
q.y = p.y * tmp; // Multiply by 1/z
}
}

Expand Down Expand Up @@ -482,7 +467,7 @@ impl crate::serde::SerdeObject for Ed25519 {
x.zip(y).zip(z).zip(t).and_then(|(((x, y), z), t)| {
let res = Self { x, y, z, t };
// Check that the point is on the curve.
bool::from(res.is_on_curve()).then(|| res)
bool::from(res.is_on_curve()).then_some(res)
})
}
fn to_raw_bytes(&self) -> Vec<u8> {
Expand Down Expand Up @@ -601,7 +586,7 @@ impl crate::serde::SerdeObject for Ed25519Affine {
x.zip(y).and_then(|(x, y)| {
let res = Self { x, y };
// Check that the point is on the curve.
bool::from(res.is_on_curve()).then(|| res)
bool::from(res.is_on_curve()).then_some(res)
})
}
fn to_raw_bytes(&self) -> Vec<u8> {
Expand Down Expand Up @@ -697,7 +682,7 @@ impl CurveAffine for Ed25519Affine {
}

fn b() -> Self::Base {
ED25519_D
unimplemented!()
}
}

Expand Down Expand Up @@ -916,6 +901,36 @@ impl CurveAffineExt for Ed25519Affine {
}
}

pub trait TwistedEdwardsCurveExt: CurveExt {
fn a() -> <Self as CurveExt>::Base;
fn d() -> <Self as CurveExt>::Base;
}

impl TwistedEdwardsCurveExt for Ed25519 {
fn a() -> Fq {
-Fq::ONE
}

fn d() -> Fq {
ED25519_D
}
}

pub trait TwistedEdwardsCurveAffineExt: CurveAffineExt {
fn a() -> <Self as CurveAffine>::Base;
fn d() -> <Self as CurveAffine>::Base;
}

impl TwistedEdwardsCurveAffineExt for Ed25519Affine {
fn a() -> Fq {
-Fq::ONE
}

fn d() -> Fq {
ED25519_D
}
}

#[test]
fn test_is_on_curve() {
assert!(bool::from(Ed25519Affine::identity().is_on_curve()));
Expand Down
51 changes: 31 additions & 20 deletions src/ed25519/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ const MODULUS_LIMBS_32: [u32; 8] = [
/// Constant representing the modulus as static str
const MODULUS_STR: &str = "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed";

/// Obtained with:
/// `sage: GF(57896044618658097711785492504343953926634992332820282019728792003956564819949).primitive_element()`
/// Obtained with sage:
/// `GF(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed).primitive_element()`
const MULTIPLICATIVE_GENERATOR: Fq = Fq::from_raw([0x02, 0x0, 0x0, 0x0]);

/// INV = -(p^{-1} mod 2^64) mod 2^64
/// INV = -(q^{-1} mod 2^64) mod 2^64
const INV: u64 = 0x86bca1af286bca1b;

/// R = 2^256 mod q
Expand All @@ -72,20 +72,34 @@ const TWO_INV: Fq = Fq::from_raw([
0x3fffffffffffffff,
]);

/// sqrt(-1) mod q = 2^((p - 1) / 4) mod q
/// sqrt(-1) mod q = 2^((q - 1) / 4) mod q
const SQRT_MINUS_ONE: Fq = Fq::from_raw([
0xc4ee1b274a0ea0b0,
0x2f431806ad2fe478,
0x2b4d00993dfbd7a7,
0x2b8324804fc1df0b,
]);

/// TODO
const ZETA: Fq = Fq::zero();
/// TODO
const DELTA: Fq = Fq::zero();
/// TODO
const ROOT_OF_UNITY_INV: Fq = Fq::zero();
// Element in small order subgroup (3-order)
const ZETA: Fq = Fq::from_raw([
shuklaayush marked this conversation as resolved.
Show resolved Hide resolved
0xaa86d89d8618e538,
0x1a1aada8413a4550,
0xd9872fccc55bd529,
0x381cba36aa6565b5,
]);
const ROOT_OF_UNITY: Fq = Fq::from_raw([
0xc4ee1b274a0ea0b0,
0x2f431806ad2fe478,
0x2b4d00993dfbd7a7,
0x2b8324804fc1df0b,
]);
const ROOT_OF_UNITY_INV: Fq = Fq::from_raw([
0x3b11e4d8b5f15f3d,
0xd0bce7f952d01b87,
0xd4b2ff66c2042858,
0x547cdb7fb03e20f4,
]);
const DELTA: Fq = Fq::from_raw([0x10, 0, 0, 0]);

use crate::{
field_arithmetic, field_common, field_specific, impl_add_binop_specify_output,
Expand Down Expand Up @@ -151,14 +165,14 @@ impl ff::Field for Fq {
// = a^((q + 3) / 8) * (2^((q - 1) / 4))
// OR
// Doesn't exist
let x1 = self.pow(&[
let x1 = self.pow([
0xfffffffffffffffe,
0xffffffffffffffff,
0xffffffffffffffff,
0x0fffffffffffffff,
]);

let choice1 = x1.square().ct_eq(&self);
let choice1 = x1.square().ct_eq(self);
let choice2 = x1.square().ct_eq(&-self);

let sqrt = Self::conditional_select(&x1, &(x1 * SQRT_MINUS_ONE), choice2);
Expand Down Expand Up @@ -206,17 +220,15 @@ impl ff::Field for Fq {
impl ff::PrimeField for Fq {
type Repr = [u8; 32];

const MODULUS: &'static str = MODULUS_STR;
const NUM_BITS: u32 = 256;
const CAPACITY: u32 = 255;
const MODULUS: &'static str = MODULUS_STR;
const MULTIPLICATIVE_GENERATOR: Self = MULTIPLICATIVE_GENERATOR;
/// TODO
const ROOT_OF_UNITY: Self = Self::one();
/// TODO
const ROOT_OF_UNITY_INV: Self = Self::zero();
const TWO_INV: Self = TWO_INV;
const MULTIPLICATIVE_GENERATOR: Self = MULTIPLICATIVE_GENERATOR;
const S: u32 = 2;
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
const DELTA: Self = DELTA;
const S: u32 = 1;

fn from_repr(repr: Self::Repr) -> CtOption<Self> {
let mut tmp = Fq([0, 0, 0, 0]);
Expand Down Expand Up @@ -281,7 +293,6 @@ impl FromUniformBytes<64> for Fq {
}

impl WithSmallOrderMulGroup<3> for Fq {
/// TODO
const ZETA: Self = ZETA;
}

Expand Down
49 changes: 33 additions & 16 deletions src/ed25519/fr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ const MODULUS_LIMBS_32: [u32; 8] = [
///Constant representing the modulus as static str
const MODULUS_STR: &str = "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed";

/// INV = -(q^{-1} mod 2^64) mod 2^64
/// Obtained with sage:
/// `GF(0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed).primitive_element()`
const MULTIPLICATIVE_GENERATOR: Fr = Fr::from_raw([0x02, 0x0, 0x0, 0x0]);

/// INV = -(r^{-1} mod 2^64) mod 2^64
const INV: u64 = 0xd2b51da312547e1b;

/// R = 2^256 mod r
Expand Down Expand Up @@ -83,17 +87,34 @@ const TWO_INV: Fr = Fr::from_raw([
0x0800000000000000,
]);

/// sqrt(-1) mod p = 2^((p - 1) / 4) mod p
/// sqrt(-1) mod r = 2^((r - 1) / 4) mod r
const SQRT_MINUS_ONE: Fr = Fr::from_raw([
0xbe8775dfebbe07d4,
0x0ef0565342ce83fe,
0x7d3d6d60abc1c27a,
0x094a7310e07981e7,
]);

const ZETA: Fr = Fr::zero();
const DELTA: Fr = Fr::zero();
const ROOT_OF_UNITY_INV: Fr = Fr::zero();
// Element in small order subgroup (3-order)
const ZETA: Fr = Fr::from_raw([
shuklaayush marked this conversation as resolved.
Show resolved Hide resolved
0x158687e51e07e223,
0x471dd911c6cce91e,
0xeb08f579fb8841ae,
0x0378d9ddc674005f,
]);
const ROOT_OF_UNITY: Fr = Fr::from_raw([
0xbe8775dfebbe07d4,
0x0ef0565342ce83fe,
0x7d3d6d60abc1c27a,
0x094a7310e07981e7,
]);
const ROOT_OF_UNITY_INV: Fr = Fr::from_raw([
0x998aed3a7137cc19,
0x05eea38b602918d7,
0x82c2929f543e3d86,
0x06b58cef1f867e18,
]);
const DELTA: Fr = Fr::from_raw([0x10, 0, 0, 0]);

use crate::{
field_arithmetic, field_common, field_specific, impl_add_binop_specify_output,
Expand Down Expand Up @@ -159,14 +180,14 @@ impl ff::Field for Fr {
// = a^((p + 3) / 8) * (2^((p - 1) / 4))
// OR
// Doesn't exist
let x1 = self.pow(&[
let x1 = self.pow([
0xcb024c634b9eba7e,
0x029bdf3bd45ef39a,
0x0000000000000000,
0x0200000000000000,
]);

let choice1 = x1.square().ct_eq(&self);
let choice1 = x1.square().ct_eq(self);
let choice2 = x1.square().ct_eq(&-self);

let sqrt = Self::conditional_select(&x1, &(x1 * SQRT_MINUS_ONE), choice2);
Expand Down Expand Up @@ -213,18 +234,15 @@ impl ff::Field for Fr {
impl ff::PrimeField for Fr {
type Repr = [u8; 32];

const MODULUS: &'static str = MODULUS_STR;
const NUM_BITS: u32 = 256;
const CAPACITY: u32 = 255;
const MODULUS: &'static str = MODULUS_STR;
/// TODO
const MULTIPLICATIVE_GENERATOR: Self = Self::one();
/// TODO
const ROOT_OF_UNITY: Self = Self::one();
/// TODO
const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
const TWO_INV: Self = TWO_INV;
const MULTIPLICATIVE_GENERATOR: Self = MULTIPLICATIVE_GENERATOR;
const S: u32 = 2;
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
const DELTA: Self = DELTA;
const S: u32 = 6;

fn from_repr(repr: Self::Repr) -> CtOption<Self> {
let mut tmp = Fr([0, 0, 0, 0]);
Expand Down Expand Up @@ -289,7 +307,6 @@ impl FromUniformBytes<64> for Fr {
}

impl WithSmallOrderMulGroup<3> for Fr {
/// TODO
const ZETA: Self = ZETA;
}

Expand Down