From a7d266f73d760c5e6a3a9e9ab746aefa31e5ee01 Mon Sep 17 00:00:00 2001 From: Weikeng Chen Date: Sat, 29 Oct 2022 19:33:55 -0700 Subject: [PATCH] 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 --- CHANGELOG.md | 2 + Cargo.toml | 2 + ed25519/Cargo.toml | 30 ++++ ed25519/LICENSE-APACHE | 1 + ed25519/LICENSE-MIT | 1 + ed25519/scripts/fr.ipynb | 91 +++++++++++ ed25519/scripts/g1.ipynb | 260 ++++++++++++++++++++++++++++++ ed25519/src/constraints/curves.rs | 11 ++ ed25519/src/constraints/fields.rs | 11 ++ ed25519/src/constraints/mod.rs | 8 + ed25519/src/curves/mod.rs | 72 +++++++++ ed25519/src/curves/tests.rs | 4 + ed25519/src/fields/fq.rs | 7 + ed25519/src/fields/fr.rs | 7 + ed25519/src/fields/mod.rs | 8 + ed25519/src/fields/tests.rs | 5 + ed25519/src/lib.rs | 28 ++++ 17 files changed, 548 insertions(+) create mode 100644 ed25519/Cargo.toml create mode 120000 ed25519/LICENSE-APACHE create mode 120000 ed25519/LICENSE-MIT create mode 100644 ed25519/scripts/fr.ipynb create mode 100644 ed25519/scripts/g1.ipynb create mode 100644 ed25519/src/constraints/curves.rs create mode 100644 ed25519/src/constraints/fields.rs create mode 100644 ed25519/src/constraints/mod.rs create mode 100644 ed25519/src/curves/mod.rs create mode 100644 ed25519/src/curves/tests.rs create mode 100644 ed25519/src/fields/fq.rs create mode 100644 ed25519/src/fields/fr.rs create mode 100644 ed25519/src/fields/mod.rs create mode 100644 ed25519/src/fields/tests.rs create mode 100755 ed25519/src/lib.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c21316c..ffb7940 100644 --- a/CHANGELOG.md +++ b/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. diff --git a/Cargo.toml b/Cargo.toml index 387f801..c37d6e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ members = [ "pallas", "vesta", + + "ed25519", ] resolver = "2" diff --git a/ed25519/Cargo.toml b/ed25519/Cargo.toml new file mode 100644 index 0000000..f2c66a7 --- /dev/null +++ b/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" ] diff --git a/ed25519/LICENSE-APACHE b/ed25519/LICENSE-APACHE new file mode 120000 index 0000000..965b606 --- /dev/null +++ b/ed25519/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/ed25519/LICENSE-MIT b/ed25519/LICENSE-MIT new file mode 120000 index 0000000..76219eb --- /dev/null +++ b/ed25519/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/ed25519/scripts/fr.ipynb b/ed25519/scripts/fr.ipynb new file mode 100644 index 0000000..99e2b1b --- /dev/null +++ b/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 +} diff --git a/ed25519/scripts/g1.ipynb b/ed25519/scripts/g1.ipynb new file mode 100644 index 0000000..dda1214 --- /dev/null +++ b/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 +} diff --git a/ed25519/src/constraints/curves.rs b/ed25519/src/constraints/curves.rs new file mode 100644 index 0000000..7401d17 --- /dev/null +++ b/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; + +#[test] +fn test() { + ark_curve_constraint_tests::curves::te_test::().unwrap(); +} diff --git a/ed25519/src/constraints/fields.rs b/ed25519/src/constraints/fields.rs new file mode 100644 index 0000000..2c63654 --- /dev/null +++ b/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; + +#[test] +fn test() { + ark_curve_constraint_tests::fields::field_test::<_, _, FqVar>().unwrap(); +} diff --git a/ed25519/src/constraints/mod.rs b/ed25519/src/constraints/mod.rs new file mode 100644 index 0000000..257a851 --- /dev/null +++ b/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::*; diff --git a/ed25519/src/curves/mod.rs b/ed25519/src/curves/mod.rs new file mode 100644 index 0000000..000e816 --- /dev/null +++ b/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; +pub type EdwardsProjective = Projective; + +#[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 . + 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"); diff --git a/ed25519/src/curves/tests.rs b/ed25519/src/curves/tests.rs new file mode 100644 index 0000000..7b1ea09 --- /dev/null +++ b/ed25519/src/curves/tests.rs @@ -0,0 +1,4 @@ +use crate::*; +use ark_algebra_test_templates::*; + +test_group!(te; EdwardsProjective; te); diff --git a/ed25519/src/fields/fq.rs b/ed25519/src/fields/fq.rs new file mode 100644 index 0000000..05dcf2f --- /dev/null +++ b/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>; diff --git a/ed25519/src/fields/fr.rs b/ed25519/src/fields/fr.rs new file mode 100644 index 0000000..b387bff --- /dev/null +++ b/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>; diff --git a/ed25519/src/fields/mod.rs b/ed25519/src/fields/mod.rs new file mode 100644 index 0000000..6160678 --- /dev/null +++ b/ed25519/src/fields/mod.rs @@ -0,0 +1,8 @@ +mod fq; +mod fr; + +pub use fq::*; +pub use fr::*; + +#[cfg(test)] +mod tests; diff --git a/ed25519/src/fields/tests.rs b/ed25519/src/fields/tests.rs new file mode 100644 index 0000000..bd978b4 --- /dev/null +++ b/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); diff --git a/ed25519/src/lib.rs b/ed25519/src/lib.rs new file mode 100755 index 0000000..50ed7f7 --- /dev/null +++ b/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::*;