diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs index 973bdbf..a4eaa1a 100644 --- a/src/bls12_381/ec.rs +++ b/src/bls12_381/ec.rs @@ -7,7 +7,8 @@ macro_rules! curve_impl { $basefield:ident, $scalarfield:ident, $uncompressed:ident, - $compressed:ident + $compressed:ident, + $pairing:ident ) => { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct $affine { @@ -113,6 +114,8 @@ macro_rules! curve_impl { type Projective = $projective; type Uncompressed = $uncompressed; type Compressed = $compressed; + type Pair = $pairing; + type PairingResult = Fq12; fn zero() -> Self { $affine { @@ -155,6 +158,10 @@ macro_rules! curve_impl { $prepared::from_affine(*self) } + fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult { + self.perform_pairing(other) + } + fn into_projective(&self) -> $projective { (*self).into() } @@ -574,10 +581,11 @@ macro_rules! curve_impl { pub mod g1 { use rand::{Rand, Rng}; - use super::super::{Fq, Fr, FrRepr, FqRepr}; - use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError}; + use super::g2::G2Affine; + use super::super::{Fq, Fr, FrRepr, FqRepr, Fq12}; + use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine}; - curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed); + curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed, G2Affine); #[derive(Copy)] pub struct G1Uncompressed([u8; 96]); @@ -828,6 +836,10 @@ pub mod g1 { fn get_coeff_b() -> Fq { super::super::fq::B_COEFF } + + fn perform_pairing(&self, other: &G2Affine) -> Fq12 { + super::super::Bls12::pairing(*self, *other) + } } impl G1 { @@ -1122,10 +1134,11 @@ pub mod g1 { pub mod g2 { use rand::{Rand, Rng}; - use super::super::{Fq2, Fr, Fq, FrRepr, FqRepr}; - use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError}; + use super::super::{Fq2, Fr, Fq, FrRepr, FqRepr, Fq12}; + use super::g1::G1Affine; + use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine}; - curve_impl!("G2", G2, G2Affine, G2Prepared, Fq2, Fr, G2Uncompressed, G2Compressed); + curve_impl!("G2", G2, G2Affine, G2Prepared, Fq2, Fr, G2Uncompressed, G2Compressed, G1Affine); #[derive(Copy)] pub struct G2Uncompressed([u8; 192]); @@ -1403,6 +1416,10 @@ pub mod g2 { c1: super::super::fq::B_COEFF } } + + fn perform_pairing(&self, other: &G1Affine) -> Fq12 { + super::super::Bls12::pairing(*other, *self) + } } impl G2 { diff --git a/src/lib.rs b/src/lib.rs index ca38451..6e98aa6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,13 +42,13 @@ pub trait Engine { type G1: CurveProjective + From; /// The affine representation of an element in G1. - type G1Affine: CurveAffine + From; + type G1Affine: CurveAffine + From; /// The projective representation of an element in G2. type G2: CurveProjective + From; /// The affine representation of an element in G2. - type G2Affine: CurveAffine + From; + type G2Affine: CurveAffine + From; /// The base field that hosts G1. type Fq: PrimeField + SqrtField; @@ -172,6 +172,8 @@ pub trait CurveAffine: Copy + type Prepared: Clone + Send + Sync + 'static; type Uncompressed: EncodedPoint; type Compressed: EncodedPoint; + type Pair: CurveAffine; + type PairingResult: Field; /// Returns the additive identity. fn zero() -> Self; @@ -192,6 +194,9 @@ pub trait CurveAffine: Copy + /// Prepares this element for pairing purposes. fn prepare(&self) -> Self::Prepared; + /// Perform a pairing + fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult; + /// Converts this element into its affine representation. fn into_projective(&self) -> Self::Projective; diff --git a/src/tests/engine.rs b/src/tests/engine.rs index b1bb754..03ffc6e 100644 --- a/src/tests/engine.rs +++ b/src/tests/engine.rs @@ -6,6 +6,14 @@ pub fn engine_tests() { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + for _ in 0..10 { + let a = E::G1::rand(&mut rng).into_affine(); + let b = E::G2::rand(&mut rng).into_affine(); + + assert!(a.pairing_with(&b) == b.pairing_with(&a)); + assert!(a.pairing_with(&b) == E::pairing(a, b)); + } + for _ in 0..1000 { let z1 = E::G1Affine::zero().prepare(); let z2 = E::G2Affine::zero().prepare();