diff --git a/CHANGELOG.md b/CHANGELOG.md index 32012061..1c39e70c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,12 @@ ### Features +- [\#156](https://github.com/arkworks-rs/curves/pull/156) Add the bw6-767 curve. + ### Improvements +- [\#156](https://github.com/arkworks-rs/curves/pull/156) The hard part of the final exponentiation for bw6-761 relocated from arkworks/algebra. + ### Bugfixes ## v0.4.0 diff --git a/Cargo.toml b/Cargo.toml index 5981ae41..caf5ded3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ members = [ "bw6_761", "ed_on_bw6_761", + "bw6_767", + "cp6_782", "ed_on_cp6_782", diff --git a/bw6_761/src/curves/mod.rs b/bw6_761/src/curves/mod.rs index cfbbf4f5..55648b06 100644 --- a/bw6_761/src/curves/mod.rs +++ b/bw6_761/src/curves/mod.rs @@ -2,7 +2,9 @@ use ark_ec::{ bw6, bw6::{BW6Config, TwistType, BW6}, }; -use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt}; +use ark_ff::{ + biginteger::BigInteger768 as BigInteger, fp6_2over3::Fp6, BigInt, CyclotomicMultSubgroup, Field, +}; use crate::*; @@ -32,6 +34,21 @@ impl BW6Config for Config { ]); /// `x` is positive. const X_IS_NEGATIVE: bool = false; + // (X-1)/3 + const X_MINUS_1_DIV_3: BigInteger = BigInt::new([ + 0x2c58400000000000, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + ]); // X+1 const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000002]; const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false; @@ -47,11 +64,122 @@ impl BW6Config for Config { ]; const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false; const TWIST_TYPE: TwistType = TwistType::M; + const H_T: i64 = 13; + const H_Y: i64 = 9; + const T_MOD_R_IS_ZERO: bool = false; type Fp = Fq; type Fp3Config = Fq3Config; type Fp6Config = Fq6Config; type G1Config = g1::Config; type G2Config = g2::Config; + + fn final_exponentiation_hard_part(f: &Fp6) -> Fp6 { + // hard_part + // From https://eprint.iacr.org/2020/351.pdf, Alg.6 + + #[rustfmt::skip] + // R0(x) := (-103*x^7 + 70*x^6 + 269*x^5 - 197*x^4 - 314*x^3 - 73*x^2 - 263*x - 220) + // R1(x) := (103*x^9 - 276*x^8 + 77*x^7 + 492*x^6 - 445*x^5 - 65*x^4 + 452*x^3 - 181*x^2 + 34*x + 229) + // f ^ R0(u) * (f ^ q) ^ R1(u) in a 2-NAF multi-exp fashion. + + // steps 1,2,3 + let f0 = *f; + let mut f0p = f0; + f0p.frobenius_map_in_place(1); + let f1 = Self::exp_by_x(&f0); + let mut f1p = f1; + f1p.frobenius_map_in_place(1); + let f2 = Self::exp_by_x(&f1); + let mut f2p = f2; + f2p.frobenius_map_in_place(1); + let f3 = Self::exp_by_x(&f2); + let mut f3p = f3; + f3p.frobenius_map_in_place(1); + let f4 = Self::exp_by_x(&f3); + let mut f4p = f4; + f4p.frobenius_map_in_place(1); + let f5 = Self::exp_by_x(&f4); + let mut f5p = f5; + f5p.frobenius_map_in_place(1); + let f6 = Self::exp_by_x(&f5); + let mut f6p = f6; + f6p.frobenius_map_in_place(1); + let f7 = Self::exp_by_x(&f6); + let mut f7p = f7; + f7p.frobenius_map_in_place(1); + + // step 4 + let f8p = Self::exp_by_x(&f7p); + let f9p = Self::exp_by_x(&f8p); + + // step 5 + let mut f5p_p3 = f5p; + f5p_p3.cyclotomic_inverse_in_place(); + let result1 = f3p * &f6p * &f5p_p3; + + // step 6 + let result2 = result1.square(); + let f4_2p = f4 * &f2p; + let mut tmp1_p3 = f0 * &f1 * &f3 * &f4_2p * &f8p; + tmp1_p3.cyclotomic_inverse_in_place(); + let result3 = result2 * &f5 * &f0p * &tmp1_p3; + + // step 7 + let result4 = result3.square(); + let mut f7_p3 = f7; + f7_p3.cyclotomic_inverse_in_place(); + let result5 = result4 * &f9p * &f7_p3; + + // step 8 + let result6 = result5.square(); + let f2_4p = f2 * &f4p; + let f4_2p_5p = f4_2p * &f5p; + let mut tmp2_p3 = f2_4p * &f3 * &f3p; + tmp2_p3.cyclotomic_inverse_in_place(); + let result7 = result6 * &f4_2p_5p * &f6 * &f7p * &tmp2_p3; + + // step 9 + let result8 = result7.square(); + let mut tmp3_p3 = f0p * &f9p; + tmp3_p3.cyclotomic_inverse_in_place(); + let result9 = result8 * &f0 * &f7 * &f1p * &tmp3_p3; + + // step 10 + let result10 = result9.square(); + let f6p_8p = f6p * &f8p; + let f5_7p = f5 * &f7p; + let mut tmp4_p3 = f6p_8p; + tmp4_p3.cyclotomic_inverse_in_place(); + let result11 = result10 * &f5_7p * &f2p * &tmp4_p3; + + // step 11 + let result12 = result11.square(); + let f3_6 = f3 * &f6; + let f1_7 = f1 * &f7; + let mut tmp5_p3 = f1_7 * &f2; + tmp5_p3.cyclotomic_inverse_in_place(); + let result13 = result12 * &f3_6 * &f9p * &tmp5_p3; + + // step 12 + let result14 = result13.square(); + let mut tmp6_p3 = f4_2p * &f5_7p * &f6p_8p; + tmp6_p3.cyclotomic_inverse_in_place(); + let result15 = result14 * &f0 * &f0p * &f3p * &f5p * &tmp6_p3; + + // step 13 + let result16 = result15.square(); + let mut tmp7_p3 = f3_6; + tmp7_p3.cyclotomic_inverse_in_place(); + let result17 = result16 * &f1p * &tmp7_p3; + + // step 14 + let result18 = result17.square(); + let mut tmp8_p3 = f2_4p * &f4_2p_5p * &f9p; + tmp8_p3.cyclotomic_inverse_in_place(); + let result19 = result18 * &f1_7 * &f5_7p * &f0p * &tmp8_p3; + + result19 + } } pub type BW6_761 = BW6; diff --git a/bw6_767/Cargo.toml b/bw6_767/Cargo.toml new file mode 100644 index 00000000..903d238a --- /dev/null +++ b/bw6_767/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "ark-bw6-767" +version = "0.4.0" +authors = [ "arkworks contributors" ] +description = "The BW6-767 pairing-friendly elliptic curve" +homepage = "https://arkworks.rs" +repository = "https://github.com/arkworks-rs/curves" +documentation = "https://docs.rs/ark-bw6-767/" +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.4.0", default-features = false } +ark-ec = { version= "0.4.0", default-features = false } +ark-std = { version = "0.4.0", default-features = false } +ark-bls12-381 = { version = "0.4.0", path = "../bls12_381", default-features = false, features = [ "curve" ] } + +[dev-dependencies] +ark-serialize = { version = "0.4.0", default-features = false } +ark-algebra-test-templates = { version = "0.4.0", default-features = false } +ark-algebra-bench-templates = { version = "0.4.0", default-features = false } + +[features] +default = [] +std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-381/std" ] + +[[bench]] +name = "bw6_767" +path = "benches/bw6_767.rs" +harness = false diff --git a/bw6_767/LICENSE-APACHE b/bw6_767/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/bw6_767/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/bw6_767/LICENSE-MIT b/bw6_767/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/bw6_767/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/bw6_767/benches/bw6_767.rs b/bw6_767/benches/bw6_767.rs new file mode 100644 index 00000000..e5d47d0c --- /dev/null +++ b/bw6_767/benches/bw6_767.rs @@ -0,0 +1,16 @@ +use ark_algebra_bench_templates::*; + +use ark_bw6_767::{ + fq::Fq, fq3::Fq3, fq6::Fq6, fr::Fr, g1::G1Projective as G1, g2::G2Projective as G2, BW6_767, +}; + +bench!( + Name = "BW6_767", + Pairing = BW6_767, + G1 = G1, + G2 = G2, + ScalarField = Fr, + G1BaseField = Fq, + G2BaseField = Fq3, + TargetField = Fq6, +); diff --git a/bw6_767/scripts/base_field.sage b/bw6_767/scripts/base_field.sage new file mode 100644 index 00000000..2929afae --- /dev/null +++ b/bw6_767/scripts/base_field.sage @@ -0,0 +1,28 @@ +modulus = 496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431 + +assert(modulus.is_prime()) + +Fp = GF(modulus) + +generator = Fp(0); +for i in range(0, 20): + i = Fp(i); + neg_i = Fp(-i) + if not(i.is_primitive_root() or neg_i.is_primitive_root()): + continue + elif i.is_primitive_root(): + assert(i.is_primitive_root()); + print("Generator: %d" % i) + generator = i + break + else: + assert(neg_i.is_primitive_root()); + print("Generator: %d" % neg_i) + generator = neg_i + break + + +two_adicity = valuation(modulus - 1, 2); +trace = (modulus - 1) / 2**two_adicity; +two_adic_root_of_unity = generator^trace +print("2-adic Root of Unity: %d " % two_adic_root_of_unity) diff --git a/bw6_767/scripts/scalar_field.sage b/bw6_767/scripts/scalar_field.sage new file mode 100644 index 00000000..c714b9a3 --- /dev/null +++ b/bw6_767/scripts/scalar_field.sage @@ -0,0 +1,28 @@ +modulus = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 + +assert(modulus.is_prime()) + +Fp = GF(modulus) + +generator = Fp(0); +for i in range(0, 20): + i = Fp(i); + neg_i = Fp(-i) + if not(i.is_primitive_root() or neg_i.is_primitive_root()): + continue + elif i.is_primitive_root(): + assert(i.is_primitive_root()); + print("Generator: %d" % i) + generator = i + break + else: + assert(neg_i.is_primitive_root()); + print("Generator: %d" % neg_i) + generator = neg_i + break + + +two_adicity = valuation(modulus - 1, 2); +trace = (modulus - 1) / 2**two_adicity; +two_adic_root_of_unity = generator^trace +print("2-adic Root of Unity: %d " % two_adic_root_of_unity) diff --git a/bw6_767/src/curves/g1.rs b/bw6_767/src/curves/g1.rs new file mode 100644 index 00000000..51d4077a --- /dev/null +++ b/bw6_767/src/curves/g1.rs @@ -0,0 +1,59 @@ +use ark_ec::{ + models::{short_weierstrass::SWCurveConfig, CurveConfig}, + short_weierstrass::{Affine, Projective}, +}; +use ark_ff::{AdditiveGroup, MontFp}; + +use crate::{Fq, Fr}; + +pub type G1Affine = Affine; +pub type G1Projective = Projective; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct Config; + +impl CurveConfig for Config { + type BaseField = Fq; + type ScalarField = Fr; + + /// COFACTOR = + /// 124074696211871689196744963988542244365937182994917792082847997279938522233341057826255097957635256182243502012934844 + #[rustfmt::skip] + const COFACTOR: &'static [u64] = &[ + 0x9fed0006fffaaabc, + 0xfae29bffb34d7c0d, + 0xc51e35fba8145036, + 0x58c9927410ca3a62, + 0x7772b64205a0bc67, + 0x26212b5cf67cecaf, + 0x3, + ]; + + /// COFACTOR^(-1) mod r = + /// 1707860402533867312515920333330662452399178546610458136488910471176197226039103222144872611321997303708365553992812 + const COFACTOR_INV: Fr = MontFp!("1707860402533867312515920333330662452399178546610458136488910471176197226039103222144872611321997303708365553992812"); +} + +impl SWCurveConfig for Config { + /// COEFF_A = 0 + const COEFF_A: Fq = Fq::ZERO; + + /// COEFF_B = 1 + const COEFF_B: Fq = MontFp!("1"); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); + #[inline(always)] + fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField { + use ark_ff::Zero; + Self::BaseField::zero() + } +} + +/// G1_GENERATOR_X = +/// 127687253511432941835499154999732953539969793860764514205013635996439242747457934431893570832266740963864950713809357287070846939000367049554519743864924323440810949629217677483481194663331926309250818003412838087592587472550707218 +pub const G1_GENERATOR_X: Fq = MontFp!("127687253511432941835499154999732953539969793860764514205013635996439242747457934431893570832266740963864950713809357287070846939000367049554519743864924323440810949629217677483481194663331926309250818003412838087592587472550707218"); + +/// G1_GENERATOR_Y = +/// 415570529523170147223250223671601071129165798689804006717876771297003017718159840368703823786319144396618898691682149260290217115399107531975419658973137909698922937988511368601419289861827304905241655385035120916874417442125721204 +pub const G1_GENERATOR_Y: Fq = MontFp!("415570529523170147223250223671601071129165798689804006717876771297003017718159840368703823786319144396618898691682149260290217115399107531975419658973137909698922937988511368601419289861827304905241655385035120916874417442125721204"); diff --git a/bw6_767/src/curves/g2.rs b/bw6_767/src/curves/g2.rs new file mode 100644 index 00000000..d56c85fd --- /dev/null +++ b/bw6_767/src/curves/g2.rs @@ -0,0 +1,60 @@ +use ark_ec::{ + models::{short_weierstrass::SWCurveConfig, CurveConfig}, + short_weierstrass::{Affine, Projective}, +}; +use ark_ff::{AdditiveGroup, MontFp}; + +use crate::{Fq, Fr}; + +pub type G2Affine = Affine; +pub type G2Projective = Projective; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct Config; + +impl CurveConfig for Config { + type BaseField = Fq; + type ScalarField = Fr; + + /// COFACTOR = + /// 124074696211871689196744963988542244365937182994917792082847997279938522233341057826255097957635256182243502012934833 + #[rustfmt::skip] + const COFACTOR: &'static [u64] = &[ + 0x9fed0006fffaaab1, + 0xfae29bffb34d7c0d, + 0xc51e35fba8145036, + 0x58c9927410ca3a62, + 0x7772b64205a0bc67, + 0x26212b5cf67cecaf, + 0x3, + ]; + + /// COFACTOR^(-1) mod r = + /// 1034808299677096100380606582404873291173913026971901593767142419502683535585229274705219741821274468081298550569313 + const COFACTOR_INV: Fr = MontFp!("1034808299677096100380606582404873291173913026971901593767142419502683535585229274705219741821274468081298550569313"); +} + +impl SWCurveConfig for Config { + /// COEFF_A = 0 + const COEFF_A: Fq = Fq::ZERO; + + /// COEFF_B = 4 + const COEFF_B: Fq = MontFp!("3"); + + /// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y) + const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); + + #[inline(always)] + fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField { + use ark_ff::Zero; + Self::BaseField::zero() + } +} + +/// G2_GENERATOR_X = +/// 370611171465172359348863648443534520144617072349884185652206813771489664034831143983178049920510836078361116088420840622225267322852644540540617123958979924966938307707664543525950567252218300954395355151658118858470703533448342222 +pub const G2_GENERATOR_X: Fq = MontFp!("370611171465172359348863648443534520144617072349884185652206813771489664034831143983178049920510836078361116088420840622225267322852644540540617123958979924966938307707664543525950567252218300954395355151658118858470703533448342222"); + +/// G2_GENERATOR_Y = +/// 455144308204607096185992716699045373884508292978508084510087807751472279103896568109582325400258900176330927780121791269969939391813736974371796892558810828460226121428602798229282770695472612961143258458821149661074127679136388603 +pub const G2_GENERATOR_Y: Fq = MontFp!("455144308204607096185992716699045373884508292978508084510087807751472279103896568109582325400258900176330927780121791269969939391813736974371796892558810828460226121428602798229282770695472612961143258458821149661074127679136388603"); diff --git a/bw6_767/src/curves/mod.rs b/bw6_767/src/curves/mod.rs new file mode 100644 index 00000000..ad51306a --- /dev/null +++ b/bw6_767/src/curves/mod.rs @@ -0,0 +1,80 @@ +use ark_ec::{ + bw6, + bw6::{BW6Config, TwistType, BW6}, +}; +use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt}; + +use crate::*; + +pub mod g1; +pub mod g2; + +#[cfg(test)] +mod tests; + +#[derive(PartialEq, Eq)] +pub struct Config; + +impl BW6Config for Config { + // X is the same as in bls12_381 + const X: BigInteger = BigInt::new([ + 0xd201000000010000, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + ]); + const X_IS_NEGATIVE: bool = true; + // [(-X)+1]/3, since X < 0 + const X_MINUS_1_DIV_3: BigInteger = BigInt::new([ + 0x460055555555aaab, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + ]); + // -[(-X)+1] + const ATE_LOOP_COUNT_1: &'static [u64] = &[0xd20100000000ffff]; + const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = true; + // -[(-X)^3-(-X)^2-(-X)] in 2-NAF + const ATE_LOOP_COUNT_2: &'static [i8] = &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, + -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, + 0, -1, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, + 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 1, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, -1, 0, 1, 0, 0, 1, + ]; + const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = true; + const TWIST_TYPE: TwistType = TwistType::M; + const H_T: i64 = -4; + const H_Y: i64 = -6; + const T_MOD_R_IS_ZERO: bool = true; + type Fp = Fq; + type Fp3Config = Fq3Config; + type Fp6Config = Fq6Config; + type G1Config = g1::Config; + type G2Config = g2::Config; +} + +pub type BW6_767 = BW6; + +pub type G1Affine = bw6::G1Affine; +pub type G1Projective = bw6::G1Projective; +pub type G2Affine = bw6::G2Affine; +pub type G2Projective = bw6::G2Projective; diff --git a/bw6_767/src/curves/tests.rs b/bw6_767/src/curves/tests.rs new file mode 100644 index 00000000..949d9893 --- /dev/null +++ b/bw6_767/src/curves/tests.rs @@ -0,0 +1,8 @@ +use crate::*; +use ark_algebra_test_templates::*; +use ark_ff::Field; + +test_group!(g1; G1Projective; sw); +test_group!(g2; G2Projective; sw); +test_group!(pairing_output; ark_ec::pairing::PairingOutput; msm); +test_pairing!(pairing; crate::BW6_767); diff --git a/bw6_767/src/fields/fq.rs b/bw6_767/src/fields/fq.rs new file mode 100644 index 00000000..83b477b0 --- /dev/null +++ b/bw6_767/src/fields/fq.rs @@ -0,0 +1,7 @@ +use ark_ff::fields::{Fp768, MontBackend, MontConfig}; + +#[derive(MontConfig)] +#[modulus = "496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431"] +#[generator = "3"] +pub struct FqConfig; +pub type Fq = Fp768>; diff --git a/bw6_767/src/fields/fq3.rs b/bw6_767/src/fields/fq3.rs new file mode 100644 index 00000000..8e5366a1 --- /dev/null +++ b/bw6_767/src/fields/fq3.rs @@ -0,0 +1,79 @@ +use ark_ff::{ + fields::fp3::{Fp3, Fp3Config}, + AdditiveGroup, Field, MontFp, +}; + +use crate::Fq; + +pub type Fq3 = Fp3; + +pub struct Fq3Config; + +impl Fp3Config for Fq3Config { + type Fp = Fq; + + /// NONRESIDUE = 3 + // Fq3 = Fq\[u\]/u^3-3 + const NONRESIDUE: Fq = MontFp!("3"); + + // (MODULUS^3 - 1) % 2^TWO_ADICITY == 0 + const TWO_ADICITY: u32 = 1; + + // (T-1)/2 with T = (MODULUS^3-1) / 2^TWO_ADICITY + #[rustfmt::skip] + const TRACE_MINUS_ONE_DIV_TWO: &'static [u64] = &[ + 0x22d18a101ce54f7d, + 0x354335b0e7c460e8, + 0x8014efd2b7ade04d, + 0x3a3c62ab52e0a2c1, + 0x79ce8405b95dd2ee, + 0x24f75cbd8559a2b6, + 0x2519d1267e548214, + 0xea0034421965f6c8, + 0xbbaa92b6aca7d134, + 0x9ec0892af11e70cc, + 0x06e6ab40a2fd09ec, + 0xd333987617c1542a, + 0xdcb52167b1f0ae0f, + 0xeffa098d77a86e52, + 0x9fe0d744c24ed062, + 0x7df249c9ef981da1, + 0x01337d754cef36fa, + 0xf84c4f79c259bd8b, + 0x6552e19d7dc57335, + 0x9f2cab11727d9c89, + 0xe5cc4da17a684263, + 0xaab0632027470c14, + 0xb841a2fe447f48a3, + 0x6e705db09cb2c6c9, + 0x51d3c82bd5de018d, + 0xf0bb21ffbef26bd1, + 0x294ce678e6a4c0ff, + 0x130ad731f57d4c85, + 0xa1e367e5eb70a85b, + 0xd1b2d73d567515cd, + 0x0527dddbc3e9f165, + 0x1d9c04e0098344e7, + 0x5db616f391729475, + 0xd2834b1fae1c2c1b, + 0x7cf1b8c728557851, + 0x218325db61d6ebd, + ]; + + // NONRESIDUE^T % q + const QUADRATIC_NONRESIDUE_TO_T: Fq3 = Fq3::new(Fq::ONE, Fq::ZERO, Fq::ZERO); + + // NQR ^ (MODULUS^i - 1)/3, i=0,1,2 with NQR = u = (0,1,0) + const FROBENIUS_COEFF_FP3_C1: &'static [Fq] = &[ + Fq::ONE, + MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"), + MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"), + ]; + + // NQR ^ (2*MODULUS^i - 2)/3, i=0,1,2 with NQR = u = (0,1,0) + const FROBENIUS_COEFF_FP3_C2: &'static [Fq] = &[ + Fq::ONE, + MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"), + MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"), + ]; +} diff --git a/bw6_767/src/fields/fq6.rs b/bw6_767/src/fields/fq6.rs new file mode 100644 index 00000000..63f23d93 --- /dev/null +++ b/bw6_767/src/fields/fq6.rs @@ -0,0 +1,26 @@ +use ark_ff::{ + fields::fp6_2over3::{Fp6, Fp6Config}, + AdditiveGroup, Field, MontFp, +}; + +use crate::{Fq, Fq3, Fq3Config}; + +pub type Fq6 = Fp6; + +pub struct Fq6Config; + +impl Fp6Config for Fq6Config { + type Fp3Config = Fq3Config; + + /// NONRESIDUE = (0, 1, 0) + const NONRESIDUE: Fq3 = Fq3::new(Fq::ZERO, Fq::ONE, Fq::ZERO); + + const FROBENIUS_COEFF_FP6_C1: &'static [Fq] = &[ + Fq::ONE, + MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550171"), + MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"), + MontFp!("-1"), + MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"), + MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349261"), + ]; +} diff --git a/bw6_767/src/fields/fr.rs b/bw6_767/src/fields/fr.rs new file mode 100644 index 00000000..c75c3d7f --- /dev/null +++ b/bw6_767/src/fields/fr.rs @@ -0,0 +1 @@ +pub use ark_bls12_381::{Fq as Fr, FqConfig as FrConfig}; diff --git a/bw6_767/src/fields/mod.rs b/bw6_767/src/fields/mod.rs new file mode 100644 index 00000000..7bfd333d --- /dev/null +++ b/bw6_767/src/fields/mod.rs @@ -0,0 +1,14 @@ +pub mod fr; +pub use self::fr::*; + +pub mod fq; +pub use self::fq::*; + +pub mod fq3; +pub use self::fq3::*; + +pub mod fq6; +pub use self::fq6::*; + +#[cfg(test)] +mod tests; diff --git a/bw6_767/src/fields/tests.rs b/bw6_767/src/fields/tests.rs new file mode 100644 index 00000000..d7b1853f --- /dev/null +++ b/bw6_767/src/fields/tests.rs @@ -0,0 +1,7 @@ +use crate::*; +use ark_algebra_test_templates::*; + +test_field!(fr; Fr; mont_prime_field); +test_field!(fq; Fq; mont_prime_field); +test_field!(fq3; Fq3); +test_field!(fq6; Fq6); diff --git a/bw6_767/src/lib.rs b/bw6_767/src/lib.rs new file mode 100755 index 00000000..a7317a1a --- /dev/null +++ b/bw6_767/src/lib.rs @@ -0,0 +1,36 @@ +#![cfg_attr(not(feature = "std"), no_std)] +#![deny( + warnings, + unused, + future_incompatible, + nonstandard_style, + rust_2018_idioms +)] +#![forbid(unsafe_code)] + +//! This module implements the BW6_767 curve generated by [\[El Housni and Guillevic\]](https://hackmd.io/@gnark/bw6_bls12381), +//! using their generic approach described in [\[HG21\]](https://eprint.iacr.org/2021/1359). +//! The name denotes that it is a curve generated using the Brezing--Weng +//! method, and that its embedding degree is 6. +//! The main feature of this curve is that the scalar field equals the base +//! field of the BLS12_381 curve. +//! +//! Curve information: +//! * Base field: q = 496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431 +//! * Scalar field: r = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 +//! * valuation(q - 1, 2) = 1 +//! * valuation(r - 1, 2) = 1 +//! +//! G1 curve equation: y^2 = x^3 + Ax + B, where +//! * A = 0, +//! * B = 1 +//! +//! G2 curve equation: y^2 = x^3 + Ax + B, where +//! * A = 0 +//! * B = 3 + +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*;