Curve instantiation on extension field

This commit is contained in:
Sean Bowe 2016-07-02 17:35:00 -06:00
parent b277f0d1e3
commit 17416ed162
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
5 changed files with 262 additions and 32 deletions

View File

@ -82,25 +82,6 @@ impl<P: PrimeFieldParams> Field for Fp<P> {
res
}
}
fn pow<P2: PrimeFieldParams>(&self, exp: &Fp<P2>) -> 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;

140
src/fields/fp2.rs Normal file
View File

@ -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<P: Fp2Params> {
a: Fq,
b: Fq,
_marker: PhantomData<P>
}
impl<P: Fp2Params> Fp2<P> {
pub fn new(a: Fq, b: Fq) -> Self {
Fp2 {
a: a,
b: b,
_marker: PhantomData
}
}
}
impl<P: Fp2Params> fmt::Debug for Fp2<P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}({:?}, {:?})", P::name(), self.a, self.b)
}
}
impl<P: Fp2Params> Clone for Fp2<P> {
fn clone(&self) -> Self {
Fp2 {
a: self.a.clone(),
b: self.b.clone(),
_marker: PhantomData
}
}
}
impl<P: Fp2Params> Field for Fp2<P> {
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<R: Rng>(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<P> {
type Output = Fp2<P>;
fn mul(self, other: &Fq) -> Fp2<P> {
Fp2 {
a: &self.a * other,
b: &self.b * other,
_marker: PhantomData
}
}
}
forward_ops_to_field_ops!(impl(P: Fp2Params) Fp2<P>);

View File

@ -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<R: Rng>(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<P: PrimeFieldParams>(&self, exp: &Fp<P>) -> 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<P: PrimeFieldParams>(&self, exp: &Fp<P>) -> Self;
fn eq(&self, other: &Self) -> bool;
fn ne(&self, other: &Self) -> bool {
!self.eq(other)
!self.eq(other)
}
fn neg(&self) -> Self;

View File

@ -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<FrParams>;
pub type Fq = Fp<FqParams>;
pub type Fq2 = Fp2<Fq2Params>;
pub type Scalar = Fr;
pub type G1 = Jacobian<G1Params>;
pub type G2 = Jacobian<G2Params>;

View File

@ -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::<super::Fr>();
fields::tests::field_trials::<Fr>();
}
#[test]
fn test_fq() {
use fields;
fields::tests::field_trials::<super::Fq>();
fields::tests::field_trials::<Fq>();
}
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::<G1Params>();
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::<Fq2>();
}
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<Self> {
Jacobian::new(Fq2::zero(), Fq2::one(), Fq2::zero()).unwrap()
}
fn one() -> Jacobian<Self> {
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::<G2Params>();
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);
}