diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 4bb3c62..3773bc1 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -82,25 +82,6 @@ impl Field for Fp

{ res } } - - fn pow(&self, exp: &Fp) -> Self { - let mut res = Self::one(); - - let mut found_one = false; - - for i in (0..P2::bits()).rev() { - if found_one { - res = res.squared(); - } - - if exp.test_bit(i) { - found_one = true; - res = res * self; - } - } - - res - } fn neg(&self) -> Self { use num::Zero; diff --git a/src/fields/fp2.rs b/src/fields/fp2.rs new file mode 100644 index 0000000..a28d234 --- /dev/null +++ b/src/fields/fp2.rs @@ -0,0 +1,140 @@ +use ::Fq; +use rand::Rng; +use fields::fp::PrimeFieldParams; +use fields::Field; +use std::ops::{Mul,Add,Sub,Neg}; +use std::cmp::{PartialEq, Eq}; +use std::marker::PhantomData; +use std::fmt; + +pub trait Fp2Params { + fn non_residue() -> Fq; + fn name() -> &'static str; +} + +pub struct Fp2 { + a: Fq, + b: Fq, + _marker: PhantomData

+} + +impl Fp2

{ + pub fn new(a: Fq, b: Fq) -> Self { + Fp2 { + a: a, + b: b, + _marker: PhantomData + } + } +} + +impl fmt::Debug for Fp2

{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}({:?}, {:?})", P::name(), self.a, self.b) + } +} + +impl Clone for Fp2

{ + fn clone(&self) -> Self { + Fp2 { + a: self.a.clone(), + b: self.b.clone(), + _marker: PhantomData + } + } +} + +impl Field for Fp2

{ + fn zero() -> Self { + Fp2 { + a: Fq::zero(), + b: Fq::zero(), + _marker: PhantomData + } + } + fn one() -> Self { + Fp2 { + a: Fq::one(), + b: Fq::zero(), + _marker: PhantomData + } + } + fn random(rng: &mut R) -> Self { + Fp2 { + a: Fq::random(rng), + b: Fq::random(rng), + _marker: PhantomData + } + } + fn is_zero(&self) -> bool { + self == &Self::zero() + } + fn inverse(&self) -> Self { + let t = (self.a.squared() - (self.b.squared() * P::non_residue())).inverse(); + + Fp2 { + a: &self.a * &t, + b: -(&self.b * &t), + _marker: PhantomData + } + } + fn squared(&self) -> Self { + let a = &self.a; let b = &self.b; + let ab = &(a * b); + + Fp2 { + a: (b * P::non_residue() + a) * (a + b) - ab - ab * P::non_residue(), + b: ab + ab, + _marker: PhantomData + } + } + + fn eq(&self, other: &Self) -> bool { + self.a == other.a && self.b == other.b + } + fn neg(&self) -> Self { + Fp2 { + a: -(&self.a), + b: -(&self.b), + _marker: PhantomData + } + } + fn mul(&self, other: &Self) -> Self { + let a_a = &(&self.a * &other.a); + let b_b = &(&self.b * &other.b); + + Fp2 { + a: b_b * P::non_residue() + a_a, + b: (&self.a + &self.b) * (&other.a + &other.b) - a_a - b_b, + _marker: PhantomData + } + } + fn sub(&self, other: &Self) -> Self { + Fp2 { + a: &self.a - &other.a, + b: &self.b - &other.b, + _marker: PhantomData + } + } + fn add(&self, other: &Self) -> Self { + Fp2 { + a: &self.a + &other.a, + b: &self.b + &other.b, + _marker: PhantomData + } + } +} + +impl<'a, 'b, P: Fp2Params> Mul<&'a Fq> for &'b Fp2

{ + type Output = Fp2

; + + fn mul(self, other: &Fq) -> Fp2

{ + Fp2 { + a: &self.a * other, + b: &self.b * other, + _marker: PhantomData + } + } +} + +forward_ops_to_field_ops!(impl(P: Fp2Params) Fp2

); diff --git a/src/fields/mod.rs b/src/fields/mod.rs index 1bd6a67..bfb5610 100644 --- a/src/fields/mod.rs +++ b/src/fields/mod.rs @@ -2,6 +2,7 @@ mod macros; pub mod fp; +pub mod fp2; #[cfg(test)] pub mod tests; @@ -11,18 +12,35 @@ use self::fp::{Fp, PrimeFieldParams}; use std::fmt::Debug; pub trait Field: Sized + Clone + Debug { - fn zero() -> Self; - fn one() -> Self; + fn zero() -> Self; + fn one() -> Self; fn random(rng: &mut R) -> Self; fn is_zero(&self) -> bool; fn inverse(&self) -> Self; fn squared(&self) -> Self { - self.mul(self) + self.mul(self) + } + fn pow(&self, exp: &Fp

) -> Self { + let mut res = Self::one(); + + let mut found_one = false; + + for i in (0..P::bits()).rev() { + if found_one { + res = res.squared(); + } + + if exp.test_bit(i) { + found_one = true; + res = self.mul(&res); + } + } + + res } - fn pow(&self, exp: &Fp

) -> Self; fn eq(&self, other: &Self) -> bool; fn ne(&self, other: &Self) -> bool { - !self.eq(other) + !self.eq(other) } fn neg(&self) -> Self; diff --git a/src/lib.rs b/src/lib.rs index 2b273c3..219db22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,12 +7,15 @@ mod params; mod groups; pub use fields::fp::Fp; -pub use params::{FrParams,FqParams,G1Params}; +pub use fields::fp2::Fp2; +pub use params::{FrParams,FqParams,Fq2Params,G1Params,G2Params}; pub use fields::Field; pub use groups::Jacobian; pub type Fr = Fp; pub type Fq = Fp; +pub type Fq2 = Fp2; pub type Scalar = Fr; pub type G1 = Jacobian; +pub type G2 = Jacobian; diff --git a/src/params.rs b/src/params.rs index 5fdef1f..567f783 100644 --- a/src/params.rs +++ b/src/params.rs @@ -1,7 +1,8 @@ use num::{Num,BigUint}; use fields::Field; use fields::fp::PrimeFieldParams; -use super::{Fr,Fq,G1}; +use fields::fp2::Fp2Params; +use super::{Fr,Fq,Fq2,G1,G2}; use groups::*; pub struct FrParams; @@ -28,20 +29,20 @@ impl PrimeFieldParams for FqParams { fn test_fr() { use fields; - fields::tests::field_trials::(); + fields::tests::field_trials::(); } #[test] fn test_fq() { use fields; - fields::tests::field_trials::(); + fields::tests::field_trials::(); } pub struct G1Params; impl GroupParams for G1Params { - type Base = super::Fq; + type Base = Fq; fn name() -> &'static str { "G1" @@ -62,12 +63,15 @@ fn test_g1() { use groups; groups::tests::group_trials::(); + + assert_eq!(G1::zero(), G1::one() + (G1::zero() - G1::one())); + assert_eq!(G1::zero(), G1::one() * Fr::from("21888242871839275222246405745257275088548364400416034343698204186575808495616") + G1::one()); } #[test] fn g1_test_vector() { - let a = G1::one() * &Fr::from("19797905000333868150253315089095386158892526856493194078073564469188852136946"); - let b = G1::one() * &Fr::from("2730506433347642574983433139433778984782882168213690554721050571242082865799"); + let a = G1::one() * Fr::from("19797905000333868150253315089095386158892526856493194078073564469188852136946"); + let b = G1::one() * Fr::from("2730506433347642574983433139433778984782882168213690554721050571242082865799"); let e = &a + &b; let expect = G1::new( @@ -76,5 +80,89 @@ fn g1_test_vector() { Fq::one() ).unwrap(); - assert!(expect.eq(&e)); + assert_eq!(expect, e); +} + +pub struct Fq2Params; + +impl Fp2Params for Fq2Params { + fn non_residue() -> Fq { + Fq::from("21888242871839275222246405745257275088696311157297823662689037894645226208582") + } + fn name() -> &'static str { + "Fq2" + } +} + +#[test] +fn test_fq2() { + use fields; + + fields::tests::field_trials::(); +} + +pub struct G2Params; + +impl G2Params { + pub fn twist() -> Fq2 { + Fq2::new(Fq::from("9"), Fq::from("1")) + } +} + +impl GroupParams for G2Params { + type Base = Fq2; + + fn name() -> &'static str { + "G2" + } + fn zero() -> Jacobian { + Jacobian::new(Fq2::zero(), Fq2::one(), Fq2::zero()).unwrap() + } + fn one() -> Jacobian { + Jacobian::new( + Fq2::new( + Fq::from("10857046999023057135944570762232829481370756359578518086990519993285655852781"), + Fq::from("11559732032986387107991004021392285783925812861821192530917403151452391805634") + ), + Fq2::new( + Fq::from("8495653923123431417604973247489272438418190587263600148770280649306958101930"), + Fq::from("4082367875863433681332203403145435568316851327593401208105741076214120093531") + ), + Fq2::one() + ).unwrap() + } + fn coeff_b() -> Self::Base { + &G2Params::twist().inverse() * &Fq::from("3") + } +} + +#[test] +fn test_g2() { + use groups; + + groups::tests::group_trials::(); + + assert_eq!(G2::zero(), G2::one() + (G2::zero() - G2::one())); + assert_eq!(G2::zero(), G2::one() * Fr::from("21888242871839275222246405745257275088548364400416034343698204186575808495616") + G2::one()); +} + +#[test] +fn g2_test_vector() { + let a = G2::one() * Fr::from("19797905000333868150253315089095386158892526856493194078073564469188852136946"); + let b = G2::one() * Fr::from("2730506433347642574983433139433778984782882168213690554721050571242082865799"); + let e = &a + &b; + + let expect = G2::new( + Fq2::new( + Fq::from("10805137482603266627116066166226222153808813611856467496561473491230213987197"), + Fq::from("11018998371825437935082073888099464993330606622517843684670450190973893289235") + ), + Fq2::new( + Fq::from("371699491666579792038680273553261511891341995868329474144713691525212078012"), + Fq::from("2123259504314265904107110265140842273706723557882599408954283209162529085097") + ), + Fq2::one() + ).unwrap(); + + assert_eq!(expect, e); }