Remaining extension field tower
This commit is contained in:
parent
17416ed162
commit
c8a0d56ba4
|
@ -51,12 +51,6 @@ impl<P: PrimeFieldParams> Field for Fp<P> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
use num::Zero;
|
||||
|
||||
self.value == BigUint::zero()
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Self {
|
||||
if self.is_zero() {
|
||||
// TODO: this should likely bleed through the abstraction layers
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
use ::Fq2;
|
||||
use ::Fq6;
|
||||
use rand::Rng;
|
||||
use fields::Field;
|
||||
use std::ops::{Mul,Add,Sub,Neg};
|
||||
use std::cmp::{PartialEq, Eq};
|
||||
use std::marker::PhantomData;
|
||||
use std::fmt;
|
||||
|
||||
pub trait Fp12Params {
|
||||
fn non_residue() -> Fq2;
|
||||
fn name() -> &'static str;
|
||||
}
|
||||
|
||||
pub struct Fp12<P: Fp12Params> {
|
||||
a: Fq6,
|
||||
b: Fq6,
|
||||
_marker: PhantomData<P>
|
||||
}
|
||||
|
||||
impl<P: Fp12Params> Fp12<P> {
|
||||
pub fn new(a: Fq6, b: Fq6) -> Self {
|
||||
Fp12 {
|
||||
a: a,
|
||||
b: b,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp12Params> fmt::Debug for Fp12<P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}({:?}, {:?})", P::name(), self.a, self.b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp12Params> Clone for Fp12<P> {
|
||||
fn clone(&self) -> Self {
|
||||
Fp12 {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp12Params> Field for Fp12<P> {
|
||||
fn zero() -> Self {
|
||||
Fp12 {
|
||||
a: Fq6::zero(),
|
||||
b: Fq6::zero(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
fn one() -> Self {
|
||||
Fp12 {
|
||||
a: Fq6::one(),
|
||||
b: Fq6::zero(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
fn random<R: Rng>(rng: &mut R) -> Self {
|
||||
Fp12 {
|
||||
a: Fq6::random(rng),
|
||||
b: Fq6::random(rng),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Self {
|
||||
let t = (self.a.squared() - (self.b.squared().mul_by_nonresidue(&P::non_residue()))).inverse();
|
||||
|
||||
Fp12 {
|
||||
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);
|
||||
|
||||
Fp12 {
|
||||
a: (b.mul_by_nonresidue(&P::non_residue()) + a) * (a + b) - ab - ab.mul_by_nonresidue(&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 {
|
||||
Fp12 {
|
||||
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);
|
||||
|
||||
Fp12 {
|
||||
a: b_b.mul_by_nonresidue(&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 {
|
||||
Fp12 {
|
||||
a: &self.a - &other.a,
|
||||
b: &self.b - &other.b,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
fn add(&self, other: &Self) -> Self {
|
||||
Fp12 {
|
||||
a: &self.a + &other.a,
|
||||
b: &self.b + &other.b,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forward_ops_to_field_ops!(impl(P: Fp12Params) Fp12<P>);
|
|
@ -1,6 +1,5 @@
|
|||
use ::Fq;
|
||||
use rand::Rng;
|
||||
use fields::fp::PrimeFieldParams;
|
||||
use fields::Field;
|
||||
use std::ops::{Mul,Add,Sub,Neg};
|
||||
use std::cmp::{PartialEq, Eq};
|
||||
|
@ -66,9 +65,7 @@ impl<P: Fp2Params> Field for Fp2<P> {
|
|||
_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();
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
use ::Fq2;
|
||||
use rand::Rng;
|
||||
use fields::Field;
|
||||
use std::ops::{Mul,Add,Sub,Neg};
|
||||
use std::cmp::{PartialEq, Eq};
|
||||
use std::marker::PhantomData;
|
||||
use std::fmt;
|
||||
|
||||
pub trait Fp6Params {
|
||||
fn non_residue() -> Fq2;
|
||||
fn name() -> &'static str;
|
||||
}
|
||||
|
||||
pub struct Fp6<P: Fp6Params> {
|
||||
a: Fq2,
|
||||
b: Fq2,
|
||||
c: Fq2,
|
||||
_marker: PhantomData<P>
|
||||
}
|
||||
|
||||
impl<P: Fp6Params> Fp6<P> {
|
||||
pub fn new(a: Fq2, b: Fq2, c: Fq2) -> Self {
|
||||
Fp6 {
|
||||
a: a,
|
||||
b: b,
|
||||
c: c,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp6Params> fmt::Debug for Fp6<P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}({:?}, {:?}, {:?})", P::name(), self.a, self.b, self.c)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp6Params> Clone for Fp6<P> {
|
||||
fn clone(&self) -> Self {
|
||||
Fp6 {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
c: self.c.clone(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp6Params> Field for Fp6<P> {
|
||||
fn zero() -> Self {
|
||||
Fp6 {
|
||||
a: Fq2::zero(),
|
||||
b: Fq2::zero(),
|
||||
c: Fq2::zero(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Fp6 {
|
||||
a: Fq2::one(),
|
||||
b: Fq2::zero(),
|
||||
c: Fq2::zero(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn random<R: Rng>(rng: &mut R) -> Self {
|
||||
Fp6 {
|
||||
a: Fq2::random(rng),
|
||||
b: Fq2::random(rng),
|
||||
c: Fq2::random(rng),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Self {
|
||||
let c0 = self.a.squared() - &self.b * &self.c * P::non_residue();
|
||||
let c1 = self.c.squared() * P::non_residue() - &self.a * &self.b;
|
||||
let c2 = self.b.squared() - &self.a * &self.c;
|
||||
let t = ((&self.c * &c1 + &self.b * &c2) * P::non_residue() + &self.a * &c0).inverse();
|
||||
|
||||
Fp6 {
|
||||
a: &t * &c0,
|
||||
b: &t * &c1,
|
||||
c: &t * &c2,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.a == other.a && self.b == other.b && self.c == other.c
|
||||
}
|
||||
|
||||
fn neg(&self) -> Self {
|
||||
Fp6 {
|
||||
a: -(&self.a),
|
||||
b: -(&self.b),
|
||||
c: -(&self.c),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn mul(&self, other: &Self) -> Self {
|
||||
let a_a = &self.a * &other.a;
|
||||
let b_b = &self.b * &other.b;
|
||||
let c_c = &self.c * &other.c;
|
||||
|
||||
Fp6 {
|
||||
a: ((&self.b + &self.c) * (&other.b + &other.c) - &b_b - &c_c) * P::non_residue() + &a_a,
|
||||
b: (&self.a + &self.b) * (&other.a + &other.b) - &a_a - &b_b + &c_c * P::non_residue(),
|
||||
c: (&self.a + &self.c) * (&other.a + &other.c) - &a_a + &b_b - &c_c,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn sub(&self, other: &Self) -> Self {
|
||||
Fp6 {
|
||||
a: &self.a - &other.a,
|
||||
b: &self.b - &other.b,
|
||||
c: &self.c - &other.c,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&self, other: &Self) -> Self {
|
||||
Fp6 {
|
||||
a: &self.a + &other.a,
|
||||
b: &self.b + &other.b,
|
||||
c: &self.c + &other.c,
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp6Params> Fp6<P> {
|
||||
pub fn mul_by_nonresidue(&self, other: &Fq2) -> Fp6<P> {
|
||||
Fp6 {
|
||||
a: &self.c * other,
|
||||
b: self.a.clone(),
|
||||
c: self.b.clone(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forward_ops_to_field_ops!(impl(P: Fp6Params) Fp6<P>);
|
|
@ -3,6 +3,8 @@ mod macros;
|
|||
|
||||
pub mod fp;
|
||||
pub mod fp2;
|
||||
pub mod fp6;
|
||||
pub mod fp12;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests;
|
||||
|
@ -15,7 +17,9 @@ pub trait Field: Sized + Clone + Debug {
|
|||
fn zero() -> Self;
|
||||
fn one() -> Self;
|
||||
fn random<R: Rng>(rng: &mut R) -> Self;
|
||||
fn is_zero(&self) -> bool;
|
||||
fn is_zero(&self) -> bool {
|
||||
self.eq(&Self::zero())
|
||||
}
|
||||
fn inverse(&self) -> Self;
|
||||
fn squared(&self) -> Self {
|
||||
self.mul(self)
|
||||
|
|
|
@ -8,13 +8,17 @@ mod groups;
|
|||
|
||||
pub use fields::fp::Fp;
|
||||
pub use fields::fp2::Fp2;
|
||||
pub use params::{FrParams,FqParams,Fq2Params,G1Params,G2Params};
|
||||
pub use fields::fp6::Fp6;
|
||||
pub use fields::fp12::Fp12;
|
||||
pub use params::{FrParams,FqParams,Fq2Params,G1Params,G2Params,Fq6Params,Fq12Params};
|
||||
pub use fields::Field;
|
||||
pub use groups::Jacobian;
|
||||
|
||||
pub type Fr = Fp<FrParams>;
|
||||
pub type Fq = Fp<FqParams>;
|
||||
pub type Fq2 = Fp2<Fq2Params>;
|
||||
pub type Fq6 = Fp6<Fq6Params>;
|
||||
pub type Fq12 = Fp12<Fq12Params>;
|
||||
|
||||
pub type Scalar = Fr;
|
||||
pub type G1 = Jacobian<G1Params>;
|
||||
|
|
128
src/params.rs
128
src/params.rs
|
@ -2,7 +2,9 @@ use num::{Num,BigUint};
|
|||
use fields::Field;
|
||||
use fields::fp::PrimeFieldParams;
|
||||
use fields::fp2::Fp2Params;
|
||||
use super::{Fr,Fq,Fq2,G1,G2};
|
||||
use fields::fp6::Fp6Params;
|
||||
use fields::fp12::Fp12Params;
|
||||
use super::{Fr,Fq,Fq2,Fq6,Fq12,G1,G2};
|
||||
use groups::*;
|
||||
|
||||
pub struct FrParams;
|
||||
|
@ -166,3 +168,127 @@ fn g2_test_vector() {
|
|||
|
||||
assert_eq!(expect, e);
|
||||
}
|
||||
|
||||
pub struct Fq6Params;
|
||||
|
||||
impl Fp6Params for Fq6Params {
|
||||
fn non_residue() -> Fq2 {
|
||||
Fq2::new(Fq::from("9"), Fq::from("1"))
|
||||
}
|
||||
fn name() -> &'static str {
|
||||
"Fq6"
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq6() {
|
||||
use fields;
|
||||
|
||||
fields::tests::field_trials::<Fq6>();
|
||||
}
|
||||
|
||||
pub struct Fq12Params;
|
||||
|
||||
impl Fp12Params for Fq12Params {
|
||||
fn non_residue() -> Fq2 {
|
||||
Fq2::new(Fq::from("9"), Fq::from("1"))
|
||||
}
|
||||
fn name() -> &'static str {
|
||||
"Fq12"
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq12() {
|
||||
use fields;
|
||||
|
||||
fields::tests::field_trials::<Fq12>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fq12_test_vector() {
|
||||
let start = Fq12::new(
|
||||
Fq6::new(
|
||||
Fq2::new(
|
||||
Fq::from("19797905000333868150253315089095386158892526856493194078073564469188852136946"),
|
||||
Fq::from("10509658143212501778222314067134547632307419253211327938344904628569123178733")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("208316612133170645758860571704540129781090973693601051684061348604461399206"),
|
||||
Fq::from("12617661120538088237397060591907161689901553895660355849494983891299803248390")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("2897490589776053688661991433341220818937967872052418196321943489809183508515"),
|
||||
Fq::from("2730506433347642574983433139433778984782882168213690554721050571242082865799")
|
||||
)
|
||||
),
|
||||
Fq6::new(
|
||||
Fq2::new(
|
||||
Fq::from("17870056122431653936196746815433147921488990391314067765563891966783088591110"),
|
||||
Fq::from("14314041658607615069703576372547568077123863812415914883625850585470406221594")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("10123533891707846623287020000407963680629966110211808794181173248765209982878"),
|
||||
Fq::from("5062091880848845693514855272640141851746424235009114332841857306926659567101")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("9839781502639936537333620974973645053542086898304697594692219798017709586567"),
|
||||
Fq::from("1583892292110602864638265389721494775152090720173641072176370350017825640703")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Do a bunch of arbitrary stuff to the element
|
||||
|
||||
let mut next = start.clone();
|
||||
for _ in 0..100 {
|
||||
next = &next * &start;
|
||||
}
|
||||
|
||||
let mut cpy = next.clone();
|
||||
|
||||
for _ in 0..10 {
|
||||
next = next.squared();
|
||||
}
|
||||
|
||||
for _ in 0..10 {
|
||||
next = &next + &start;
|
||||
next = &next - &cpy;
|
||||
next = -&next;
|
||||
}
|
||||
|
||||
next = next.squared();
|
||||
|
||||
let finally = Fq12::new(
|
||||
Fq6::new(
|
||||
Fq2::new(
|
||||
Fq::from("18388750939593263065521177085001223024106699964957029146547831509155008229833"),
|
||||
Fq::from("18370529854582635460997127698388761779167953912610241447912705473964014492243")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("3691824277096717481466579496401243638295254271265821828017111951446539785268"),
|
||||
Fq::from("20513494218085713799072115076991457239411567892860153903443302793553884247235")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("12214155472433286415803224222551966441740960297013786627326456052558698216399"),
|
||||
Fq::from("10987494248070743195602580056085773610850106455323751205990078881956262496575")
|
||||
)
|
||||
),
|
||||
Fq6::new(
|
||||
Fq2::new(
|
||||
Fq::from("5134522153456102954632718911439874984161223687865160221119284322136466794876"),
|
||||
Fq::from("20119236909927036376726859192821071338930785378711977469360149362002019539920")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("8839766648621210419302228913265679710586991805716981851373026244791934012854"),
|
||||
Fq::from("9103032146464138788288547957401673544458789595252696070370942789051858719203")
|
||||
),
|
||||
Fq2::new(
|
||||
Fq::from("10378379548636866240502412547812481928323945124508039853766409196375806029865"),
|
||||
Fq::from("9021627154807648093720460686924074684389554332435186899318369174351765754041")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(finally, next);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue