Browse Source

Add the ed25519 curve (#121)

* add ed25519 curve

* changelog

* curve info

* fix

* cleanup the script

* Update ed25519/src/curves/mod.rs

* Update ed25519/src/curves/mod.rs

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
cherry-pick
Weikeng Chen 2 years ago
committed by GitHub
parent
commit
a7d266f73d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 548 additions and 0 deletions
  1. +2
    -0
      CHANGELOG.md
  2. +2
    -0
      Cargo.toml
  3. +30
    -0
      ed25519/Cargo.toml
  4. +1
    -0
      ed25519/LICENSE-APACHE
  5. +1
    -0
      ed25519/LICENSE-MIT
  6. +91
    -0
      ed25519/scripts/fr.ipynb
  7. +260
    -0
      ed25519/scripts/g1.ipynb
  8. +11
    -0
      ed25519/src/constraints/curves.rs
  9. +11
    -0
      ed25519/src/constraints/fields.rs
  10. +8
    -0
      ed25519/src/constraints/mod.rs
  11. +72
    -0
      ed25519/src/curves/mod.rs
  12. +4
    -0
      ed25519/src/curves/tests.rs
  13. +7
    -0
      ed25519/src/fields/fq.rs
  14. +7
    -0
      ed25519/src/fields/fr.rs
  15. +8
    -0
      ed25519/src/fields/mod.rs
  16. +5
    -0
      ed25519/src/fields/tests.rs
  17. +28
    -0
      ed25519/src/lib.rs

+ 2
- 0
CHANGELOG.md

@ -12,6 +12,8 @@
### Features
- [\#121](https://github.com/arkworks-rs/curves/pull/121) Add the ed25519 curve.
### Improvements
- [\#74](https://github.com/arkworks-rs/curves/pull/74) Use Scott's subgroup membership tests for `G1` and `G2` of BLS12-381.

+ 2
- 0
Cargo.toml

@ -29,6 +29,8 @@ members = [
"pallas",
"vesta",
"ed25519",
]
resolver = "2"

+ 30
- 0
ed25519/Cargo.toml

@ -0,0 +1,30 @@
[package]
name = "ark-ed25519"
version = "0.3.0"
authors = [ "arkworks contributors" ]
description = "The ed25519 twisted Edwards curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-ed25519/"
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2021"
[dependencies]
ark-ff = { version = "^0.3.0", default-features = false }
ark-ec = { version = "^0.3.0", default-features = false }
ark-std = { version = "^0.3.0", default-features = false }
ark-r1cs-std = { version = "^0.3.0", default-features = false, optional = true }
[dev-dependencies]
ark-relations = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false }
ark-algebra-test-templates = { version = "^0.3.0", default-features = false }
ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false }
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
r1cs = [ "ark-r1cs-std" ]

+ 1
- 0
ed25519/LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-APACHE

+ 1
- 0
ed25519/LICENSE-MIT

@ -0,0 +1 @@
../LICENSE-MIT

+ 91
- 0
ed25519/scripts/fr.ipynb

@ -0,0 +1,91 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "04264893",
"metadata": {},
"outputs": [],
"source": [
"r = 7237005577332262213973186563042994240857116359379907606001950938285454250989"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1603b293",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2^2 * 3 * 11 * 198211423230930754013084525763697 * 276602624281642239937218680557139826668747"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"factor(r - 1)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "425ceac7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7237005577332262213973186563042994240857116359379907606001950938285454250988\n",
"1570463851528226261927580272323658009530148727742783848239914322803198255651\n",
"4908983020090465803374304318106080751443647916949975825112097080460587568629\n",
"7119675135705137915307919240607293966034195415655343409829245710729128040338\n",
"2975531125133123119648879457563281269120703404158613135195788908093573672641\n"
]
}
],
"source": [
"gen = 2\n",
"print(pow(gen, (r - 1) / 2, r))\n",
"print(pow(gen, (r - 1) / 3, r))\n",
"print(pow(gen, (r - 1) / 11, r))\n",
"print(pow(gen, (r - 1) / 198211423230930754013084525763697, r))\n",
"print(pow(gen, (r - 1) / 276602624281642239937218680557139826668747, r))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f4c58ca4",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.2",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

+ 260
- 0
ed25519/scripts/g1.ipynb

@ -0,0 +1,260 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "f890e69f",
"metadata": {},
"outputs": [],
"source": [
"q = pow(2,255) - 19"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d90a7f0b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"37095705934669439343138083508754565189542113879843219016388785533085940283555"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = ((q - 1) * (121665 * pow(121666, -1, q)) % q)\n",
"d"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1b2aebc5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"46316835694926478169428394003475163141307993866256225615783033603165251855960"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y = 4 * pow(5, -1, q) % q\n",
"y"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "aae2f8bf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"15112221349535400772501151409588531511454012693041857206046113283949847762202"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A\n",
"x"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ea9a4d90",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"26187595835145689230469591415084376402084551887632582719101735842039498021991"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x_squared = x^2 % q\n",
"x_squared"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "3499c817",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"37053468555941182535542715202780130513046395093004980492626426882532201484768"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y_squared = y^2 % q\n",
"y_squared"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "d9617d2d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10865872720795493305073123787695754110961843205372397773524691040492703462777"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"((q - 1) * x_squared + y_squared) % q"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "ece46a74",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10865872720795493305073123787695754110961843205372397773524691040492703462777"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"((d * x_squared * y_squared) % q + 1) % q"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "b430f926",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"21711016731996786641919559689128982722488122124807605757398297001483711807481"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pow(8, -1, q)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "d8575e54",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"486662"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = 2 * (-1 + d) / (-1 - d)\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "2ee580a3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"57896044618658097711785492504343953926634992332820282019728792003956564333285"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B = 4 / (-1 - d)\n",
"B"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ec089e21",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.2",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

+ 11
- 0
ed25519/src/constraints/curves.rs

@ -0,0 +1,11 @@
use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar;
use crate::{constraints::FqVar, *};
/// A variable that is the R1CS equivalent of `crate::EdwardsAffine`.
pub type EdwardsVar = AffineVar<EdwardsParameters, FqVar>;
#[test]
fn test() {
ark_curve_constraint_tests::curves::te_test::<EdwardsParameters, EdwardsVar>().unwrap();
}

+ 11
- 0
ed25519/src/constraints/fields.rs

@ -0,0 +1,11 @@
use ark_r1cs_std::fields::fp::FpVar;
use crate::Fq;
/// A variable that is the R1CS equivalent of `crate::Fq`.
pub type FqVar = FpVar<Fq>;
#[test]
fn test() {
ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap();
}

+ 8
- 0
ed25519/src/constraints/mod.rs

@ -0,0 +1,8 @@
//! This module implements the R1CS equivalent of `ark_ed25519`.
//! It requires a curve that embeds ed25519.
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

+ 72
- 0
ed25519/src/curves/mod.rs

@ -0,0 +1,72 @@
use crate::{Fq, Fr};
use ark_ec::{
models::CurveConfig,
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
};
use ark_ff::MontFp;
#[cfg(test)]
mod tests;
pub type EdwardsAffine = Affine<EdwardsParameters>;
pub type EdwardsProjective = Projective<EdwardsParameters>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct EdwardsParameters;
impl CurveConfig for EdwardsParameters {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR = 8
const COFACTOR: &'static [u64] = &[8];
/// COFACTOR_INV (mod r) =
/// 2713877091499598330239944961141122840321418634767465352250731601857045344121
const COFACTOR_INV: Fr =
MontFp!("2713877091499598330239944961141122840321418634767465352250731601857045344121");
}
impl TECurveConfig for EdwardsParameters {
/// COEFF_A = -1
const COEFF_A: Fq = MontFp!("-1");
/// COEFF_D = -121665 / 121666
const COEFF_D: Fq =
MontFp!("37095705934669439343138083508754565189542113879843219016388785533085940283555");
/// Standard generators from <https://neuromancer.sk/std/other/Ed25519>.
const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y);
type MontCurveConfig = EdwardsParameters;
/// Multiplication by `a` is just negation.
#[inline(always)]
fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
-elem
}
}
// We want to emphasize that this Montgomery curve is not Curve25519.
impl MontCurveConfig for EdwardsParameters {
/// COEFF_A = 486662
const COEFF_A: Fq = MontFp!("486662");
/// COEFF_B = 57896044618658097711785492504343953926634992332820282019728792003956564333285
/// This is not one, because ed25519 != curve25519
const COEFF_B: Fq =
MontFp!("57896044618658097711785492504343953926634992332820282019728792003956564333285");
type TECurveConfig = EdwardsParameters;
}
/// GENERATOR_X =
/// 15112221349535400772501151409588531511454012693041857206046113283949847762202
const GENERATOR_X: Fq =
MontFp!("15112221349535400772501151409588531511454012693041857206046113283949847762202");
/// GENERATOR_Y =
/// (4/5)
/// 46316835694926478169428394003475163141307993866256225615783033603165251855960
const GENERATOR_Y: Fq =
MontFp!("46316835694926478169428394003475163141307993866256225615783033603165251855960");

+ 4
- 0
ed25519/src/curves/tests.rs

@ -0,0 +1,4 @@
use crate::*;
use ark_algebra_test_templates::*;
test_group!(te; EdwardsProjective; te);

+ 7
- 0
ed25519/src/fields/fq.rs

@ -0,0 +1,7 @@
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
#[derive(MontConfig)]
#[modulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949"]
#[generator = "2"]
pub struct FqConfig;
pub type Fq = Fp256<MontBackend<FqConfig, 4>>;

+ 7
- 0
ed25519/src/fields/fr.rs

@ -0,0 +1,7 @@
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
#[derive(MontConfig)]
#[modulus = "7237005577332262213973186563042994240857116359379907606001950938285454250989"]
#[generator = "2"]
pub struct FrConfig;
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;

+ 8
- 0
ed25519/src/fields/mod.rs

@ -0,0 +1,8 @@
mod fq;
mod fr;
pub use fq::*;
pub use fr::*;
#[cfg(test)]
mod tests;

+ 5
- 0
ed25519/src/fields/tests.rs

@ -0,0 +1,5 @@
use crate::{Fq, Fr};
use ark_algebra_test_templates::*;
test_field!(fr; Fr; mont_prime_field);
test_field!(fq; Fq; mont_prime_field);

+ 28
- 0
ed25519/src/lib.rs

@ -0,0 +1,28 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
warnings,
unused,
future_incompatible,
nonstandard_style,
rust_2018_idioms
)]
#![forbid(unsafe_code)]
//! This library implements the ed25519 twisted Edwards curve.
//!
//! Curve information:
//! * Base field: q =
//! 57896044618658097711785492504343953926634992332820282019728792003956564819949
//! * Scalar field: r =
//! 7237005577332262213973186563042994240857116359379907606001950938285454250989
//! * Curve equation: ax^2 + y^2 =1 + dx^2y^2, where
//! * a = -1
//! * d = -121665 / 121666
#[cfg(feature = "r1cs")]
pub mod constraints;
mod curves;
mod fields;
pub use curves::*;
pub use fields::*;

Loading…
Cancel
Save