Skip to content

Commit

Permalink
Merge pull request sec-bit#20 from sunhuachuang/master
Browse files Browse the repository at this point in the history
Add curve: baby_jubjub
  • Loading branch information
sunhuachuang committed Sep 30, 2020
2 parents ac4dea1 + 9dc6f49 commit f67f785
Show file tree
Hide file tree
Showing 9 changed files with 779 additions and 1 deletion.
16 changes: 15 additions & 1 deletion curve/Cargo.toml
Expand Up @@ -18,14 +18,28 @@ rand_xorshift = "0.2"
[features]
default = [ "std" ]

full = [ "bls12_377", "bls12_381", "bn_256", "sw6", "mnt4_298", "mnt4_753", "mnt6_298", "mnt6_753", "edwards_bls12", "edwards_sw6", "jubjub" ]
full = [
"bls12_377",
"bls12_381",
"bn_256",
"sw6",
"mnt4_298",
"mnt4_753",
"mnt6_298",
"mnt6_753",
"edwards_bls12",
"edwards_sw6",
"jubjub",
"baby_jubjub"
]

bls12_377 = []
bls12_381 = []
bn_256 = []
edwards_bls12 = []
edwards_sw6 = []
jubjub = []
baby_jubjub = ["bn_256"]
sw6 = []
mnt4_298 = []
mnt4_753 = []
Expand Down
111 changes: 111 additions & 0 deletions curve/src/baby_jubjub/curves/mod.rs
@@ -0,0 +1,111 @@
use crate::baby_jubjub::{Fq, Fr};
use math::{
biginteger::BigInteger256,
curves::{
models::{ModelParameters, MontgomeryModelParameters, TEModelParameters},
twisted_edwards_extended::{GroupAffine, GroupProjective},
},
field_new,
};

#[cfg(test)]
mod tests;

pub type EdwardsAffine = GroupAffine<EdwardsParameters>;
pub type EdwardsProjective = GroupProjective<EdwardsParameters>;

#[rustfmt::skip]
const GENERATOR_X: Fq = field_new!(Fq, BigInteger256([
0x3db6612c2863cc99,
0x8a9e4521b36347dc,
0x310a1a625c16a534,
0x23ceae2710df4a14,
]));
#[rustfmt::skip]
const GENERATOR_Y: Fq = field_new!(Fq, BigInteger256([
0xb83342d20d0201aa,
0x2ffef2f7cdcfeac7,
0xbfa79a9425a6e625,
0xdfb859dc3a44b70,
]));

/// `Baby-JubJub` is a twisted Edwards curve. These curves have equations of the
/// form: ax² + y² = 1 + dx²y².
/// over some base finite field Fq.
///
/// Baby-JubJub's curve equation: x² + y² = 1 + (168696/168700)x²y²
///
/// q = 21888242871839275222246405745257275088548364400416034343698204186575808495617
///
#[derive(Clone, Default, PartialEq, Eq)]
pub struct EdwardsParameters;

impl ModelParameters for EdwardsParameters {
type BaseField = Fq;
type ScalarField = Fr;
}

impl TEModelParameters for EdwardsParameters {
/// COEFF_A = 1
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, BigInteger256([
0xac96341c4ffffffb,
0x36fc76959f60cd29,
0x666ea36f7879462e,
0xe0a77c19a07df2f,
]));

#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
*elem
}

/// COEFF_D = 168696/168700 mod q
/// = 9706598848417545097372247223557719406784115219466060233080913168975159366771
#[rustfmt::skip]
const COEFF_D: Fq = field_new!(Fq, BigInteger256([
0xe7a66d1d9fb08e74,
0xd775bbd5e17629dc,
0x70ccd097286ef1e7,
0x45809398fdf98,
]));

/// COFACTOR = 8
const COFACTOR: &'static [u64] = &[8];

/// COFACTOR^(-1) mod r =
/// 2394026564107420727433200628387514462817212225638746351800188703329891451411
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, BigInteger256([
0xfac308b2e25a3d4b,
0xa7c55b66e25b59cb,
0xeccdd46def0f28c5,
0x1c14ef83340fbe5,
]));

/// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = (GENERATOR_X, GENERATOR_Y);

type MontgomeryModelParameters = EdwardsParameters;
}

impl MontgomeryModelParameters for EdwardsParameters {
/// COEFF_A = 168698
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, BigInteger256([
9251058552732279275u64,
16047179255329565110u64,
14708493084570629864u64,
2559515811206512830u64,
]));
/// COEFF_B = 168700
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, BigInteger256([
10785223227458347488u64,
2627865112663806840u64,
16189334210225400552u64,
1096023023792938739u64,
]));

type TEModelParameters = EdwardsParameters;
}
113 changes: 113 additions & 0 deletions curve/src/baby_jubjub/curves/tests.rs
@@ -0,0 +1,113 @@
use math::{
bytes::{FromBytes, ToBytes},
curves::{AffineCurve, ProjectiveCurve},
test_rng, Zero,
};
use core::str::FromStr;
use rand::Rng;

use crate::baby_jubjub::*;

use crate::tests::{curves::*, groups::*};

#[test]
fn test_projective_curve() {
curve_tests::<EdwardsProjective>();

edwards_tests::<EdwardsParameters>();
}

#[test]
fn test_projective_group() {
let mut rng = test_rng();
let a = rng.gen();
let b = rng.gen();
for _i in 0..100 {
group_test::<EdwardsProjective>(a, b);
}
}

#[test]
fn test_affine_group() {
let mut rng = test_rng();
let a: EdwardsAffine = rng.gen();
let b: EdwardsAffine = rng.gen();
for _i in 0..100 {
group_test::<EdwardsAffine>(a, b);
}
}

#[test]
fn test_generator() {
let generator = EdwardsAffine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}

#[test]
fn test_conversion() {
let mut rng = test_rng();
let a: EdwardsAffine = rng.gen();
let b: EdwardsAffine = rng.gen();
let a_b = {
use crate::groups::Group;
(a + &b).double().double()
};
let a_b2 = (a.into_projective() + &b.into_projective())
.double()
.double();
assert_eq!(a_b, a_b2.into_affine());
assert_eq!(a_b.into_projective(), a_b2);
}

#[test]
fn test_scalar_multiplication() {
println!("Started getting field elements");
let f1 = Fr::from_str(
"4691331900926794624732159288782398864809513177368446695323460897088210774597",
)
.unwrap();
let f2 = Fr::from_str(
"1305028103380024953477151132159456965337646722479526711736847301646466538045",
)
.unwrap();

println!("Finished getting field elements");
let g = EdwardsAffine::from_str(
"(15863623088992515880085393097393553694825975317405843389771115419751650972659, \
16950150798460657717958625567821834550301663161624707787222815936182638968203)",
)
.unwrap();
let f1f2g = EdwardsAffine::from_str(
"(20773645713088336957786354488799297695596635653208610804806657050882264237947, \
19987327827845206670850937090314462639017692512983955920885166014935289314257)",
)
.unwrap();

println!("Finished getting group elements");

assert!(!g.is_zero());
assert!(!f1f2g.is_zero());

let f1g = g.mul(f1).into_affine();
assert_eq!(g.mul(f1 * &f2).into_affine(), f1f2g);
assert_eq!(f1g.mul(f2).into_affine(), f1f2g);
}

#[test]
fn test_bytes() {
let g_from_repr = EdwardsAffine::from_str(
"(15863623088992515880085393097393553694825975317405843389771115419751650972659, \
16950150798460657717958625567821834550301663161624707787222815936182638968203)",
)
.unwrap();

let g_bytes = math::to_bytes![g_from_repr].unwrap();
let g = EdwardsAffine::read(g_bytes.as_slice()).unwrap();
assert_eq!(g_from_repr, g);
}

#[test]
fn test_montgomery_conversion() {
montgomery_conversion_test::<EdwardsParameters>();
}
1 change: 1 addition & 0 deletions curve/src/baby_jubjub/fields/fq.rs
@@ -0,0 +1 @@
pub use crate::bn_256::{Fr as Fq, FrParameters as FqParameters};
86 changes: 86 additions & 0 deletions curve/src/baby_jubjub/fields/fr.rs
@@ -0,0 +1,86 @@
use math::{
biginteger::BigInteger256 as BigInteger,
fields::{Fp256, Fp256Parameters, FpParameters},
};

pub type Fr = Fp256<FrParameters>;

pub struct FrParameters;

impl Fp256Parameters for FrParameters {}

impl FpParameters for FrParameters {
type BigInt = BigInteger;

/// MODULUS = 2736030358979909402780800718157159386076813972158567259200215660948447373041
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0x677297dc392126f1,
0xab3eedb83920ee0a,
0x370a08b6d0302b0b,
0x60c89ce5c263405,
]);

const MODULUS_BITS: u32 = 251;

const CAPACITY: u32 = Self::MODULUS_BITS - 1;

const REPR_SHAVE_BITS: u32 = 5;

#[rustfmt::skip]
const R: BigInteger = BigInteger([
0x073315dea08f9c76,
0xe7acffc6a098f24b,
0xf85a9201d818f015,
0x1f16424e1bb7724,
]);

#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0x35e44abee7ecb21e,
0x74646cacf5f84ec4,
0xe472df203faa158f,
0x445b524f1ba50a8,
]);

const INV: u64 = 0x532ce5aebc48f5ef;

#[rustfmt::skip]
/// GENERATOR = 31
const GENERATOR: BigInteger = BigInteger([
0x3c284f376f3993d1,
0x08bc9d93705cf8b8,
0x239d5fcbd9538f3e,
0x5ca4836185b994b,
]);

const TWO_ADICITY: u32 = 4;

const ROOT_OF_UNITY: BigInteger = BigInteger([
0x1721ada8d4d27255,
0xcda0f5264e0e35bb,
0x961a936922086fe6,
0x1ab00857387dd52,
]);

const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x33b94bee1c909378,
0xd59f76dc1c907705,
0x9b85045b68181585,
0x30644e72e131a02,
]);

const T: BigInteger = BigInteger([
0xa677297dc392126f,
0xbab3eedb83920ee0,
0x5370a08b6d0302b0,
0x60c89ce5c26340,
]);

const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x533b94bee1c90937,
0x5d59f76dc1c90770,
0x29b85045b6818158,
0x30644e72e131a0,
]);
}
8 changes: 8 additions & 0 deletions curve/src/baby_jubjub/fields/mod.rs
@@ -0,0 +1,8 @@
pub mod fq;
pub mod fr;

pub use fq::*;
pub use fr::*;

#[cfg(all(feature = "baby_jubjub", test))]
mod tests;

0 comments on commit f67f785

Please sign in to comment.