bls12_381: Implement pairing traits
This commit is contained in:
parent
eae5df0fb9
commit
4b4a4ee8dc
|
@ -35,6 +35,11 @@ version = "0.6"
|
|||
default-features = false
|
||||
optional = true
|
||||
|
||||
[dependencies.pairing]
|
||||
path = "../pairing"
|
||||
version = "0.16"
|
||||
optional = true
|
||||
|
||||
[dependencies.rand_core]
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
|
@ -46,7 +51,7 @@ default-features = false
|
|||
[features]
|
||||
default = ["groups", "pairings", "alloc"]
|
||||
groups = ["group"]
|
||||
pairings = ["groups"]
|
||||
pairings = ["groups", "pairing"]
|
||||
alloc = []
|
||||
nightly = ["subtle/nightly"]
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::fp6::*;
|
|||
|
||||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use rand_core::RngCore;
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||
|
||||
/// This represents an element $c_0 + c_1 w$ of $\mathbb{F}_{p^12} = \mathbb{F}_{p^6} / w^2 - v$.
|
||||
|
@ -99,6 +100,13 @@ impl Fp12 {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||
Fp12 {
|
||||
c0: Fp6::random(rng),
|
||||
c1: Fp6::random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mul_by_014(&self, c0: &Fp2, c1: &Fp2, c4: &Fp2) -> Fp12 {
|
||||
let aa = self.c0.mul_by_01(c0, c1);
|
||||
let bb = self.c1.mul_by_1(c4);
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::fp2::*;
|
|||
|
||||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use rand_core::RngCore;
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||
|
||||
/// This represents an element $c_0 + c_1 v + c_2 v^2$ of $\mathbb{F}_{p^6} = \mathbb{F}_{p^2} / v^3 - u - 1$.
|
||||
|
@ -95,6 +96,14 @@ impl Fp6 {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||
Fp6 {
|
||||
c0: Fp2::random(rng),
|
||||
c1: Fp2::random(rng),
|
||||
c2: Fp2::random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mul_by_1(&self, c1: &Fp2) -> Fp6 {
|
||||
let b_b = self.c1 * c1;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ const BLS_X_IS_NEGATIVE: bool = true;
|
|||
mod pairings;
|
||||
|
||||
#[cfg(feature = "pairings")]
|
||||
pub use pairings::{pairing, Gt, MillerLoopResult};
|
||||
pub use pairings::{pairing, Bls12, Gt, MillerLoopResult};
|
||||
|
||||
#[cfg(all(feature = "pairings", feature = "alloc"))]
|
||||
pub use pairings::{multi_miller_loop, G2Prepared};
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
use crate::fp::Fp;
|
||||
use crate::fp12::Fp12;
|
||||
use crate::fp2::Fp2;
|
||||
use crate::fp6::Fp6;
|
||||
use crate::{G1Affine, G2Affine, G2Projective, Scalar, BLS_X, BLS_X_IS_NEGATIVE};
|
||||
use crate::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar, BLS_X, BLS_X_IS_NEGATIVE};
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::fmt;
|
||||
use core::iter::Sum;
|
||||
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
|
||||
use group::Group;
|
||||
use pairing::{Engine, MultiMillerLoop, PairingCurveAffine};
|
||||
use rand_core::RngCore;
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
|
@ -174,9 +180,15 @@ impl_add_binop_specify_output!(MillerLoopResult, MillerLoopResult, MillerLoopRes
|
|||
///
|
||||
/// Typically, $\mathbb{G}_T$ is written multiplicatively but we will write it additively to
|
||||
/// keep code and abstractions consistent.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct Gt(pub(crate) Fp12);
|
||||
|
||||
impl fmt::Display for Gt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for Gt {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
self.0.ct_eq(&other.0)
|
||||
|
@ -276,6 +288,166 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a Gt {
|
|||
impl_binops_additive!(Gt, Gt);
|
||||
impl_binops_multiplicative!(Gt, Scalar);
|
||||
|
||||
impl<T> Sum<T> for Gt
|
||||
where
|
||||
T: Borrow<Gt>,
|
||||
{
|
||||
fn sum<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
{
|
||||
iter.fold(Self::identity(), |acc, item| acc + item.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
impl Group for Gt {
|
||||
type Scalar = Scalar;
|
||||
|
||||
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||
loop {
|
||||
let inner = Fp12::random(rng);
|
||||
|
||||
// Not all elements of Fp12 are elements of the prime-order multiplicative
|
||||
// subgroup. We run the random element through final_exponentiation to obtain
|
||||
// a valid element, which requires that it is non-zero.
|
||||
if !bool::from(inner.is_zero()) {
|
||||
return MillerLoopResult(inner).final_exponentiation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn identity() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
|
||||
fn generator() -> Self {
|
||||
// pairing(&G1Affine::generator(), &G2Affine::generator())
|
||||
Gt(Fp12 {
|
||||
c0: Fp6 {
|
||||
c0: Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0x1972_e433_a01f_85c5,
|
||||
0x97d3_2b76_fd77_2538,
|
||||
0xc8ce_546f_c96b_cdf9,
|
||||
0xcef6_3e73_66d4_0614,
|
||||
0xa611_3427_8184_3780,
|
||||
0x13f3_448a_3fc6_d825,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0xd263_31b0_2e9d_6995,
|
||||
0x9d68_a482_f779_7e7d,
|
||||
0x9c9b_2924_8d39_ea92,
|
||||
0xf480_1ca2_e131_07aa,
|
||||
0xa16c_0732_bdbc_b066,
|
||||
0x083c_a4af_ba36_0478,
|
||||
]),
|
||||
},
|
||||
c1: Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0x59e2_61db_0916_b641,
|
||||
0x2716_b6f4_b23e_960d,
|
||||
0xc8e5_5b10_a0bd_9c45,
|
||||
0x0bdb_0bd9_9c4d_eda8,
|
||||
0x8cf8_9ebf_57fd_aac5,
|
||||
0x12d6_b792_9e77_7a5e,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0x5fc8_5188_b0e1_5f35,
|
||||
0x34a0_6e3a_8f09_6365,
|
||||
0xdb31_26a6_e02a_d62c,
|
||||
0xfc6f_5aa9_7d9a_990b,
|
||||
0xa12f_55f5_eb89_c210,
|
||||
0x1723_703a_926f_8889,
|
||||
]),
|
||||
},
|
||||
c2: Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0x9358_8f29_7182_8778,
|
||||
0x43f6_5b86_11ab_7585,
|
||||
0x3183_aaf5_ec27_9fdf,
|
||||
0xfa73_d7e1_8ac9_9df6,
|
||||
0x64e1_76a6_a64c_99b0,
|
||||
0x179f_a78c_5838_8f1f,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0x672a_0a11_ca2a_ef12,
|
||||
0x0d11_b9b5_2aa3_f16b,
|
||||
0xa444_12d0_699d_056e,
|
||||
0xc01d_0177_221a_5ba5,
|
||||
0x66e0_cede_6c73_5529,
|
||||
0x05f5_a71e_9fdd_c339,
|
||||
]),
|
||||
},
|
||||
},
|
||||
c1: Fp6 {
|
||||
c0: Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0xd30a_88a1_b062_c679,
|
||||
0x5ac5_6a5d_35fc_8304,
|
||||
0xd0c8_34a6_a81f_290d,
|
||||
0xcd54_30c2_da37_07c7,
|
||||
0xf0c2_7ff7_8050_0af0,
|
||||
0x0924_5da6_e2d7_2eae,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0x9f2e_0676_791b_5156,
|
||||
0xe2d1_c823_4918_fe13,
|
||||
0x4c9e_459f_3c56_1bf4,
|
||||
0xa3e8_5e53_b9d3_e3c1,
|
||||
0x820a_121e_21a7_0020,
|
||||
0x15af_6183_41c5_9acc,
|
||||
]),
|
||||
},
|
||||
c1: Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0x7c95_658c_2499_3ab1,
|
||||
0x73eb_3872_1ca8_86b9,
|
||||
0x5256_d749_4774_34bc,
|
||||
0x8ba4_1902_ea50_4a8b,
|
||||
0x04a3_d3f8_0c86_ce6d,
|
||||
0x18a6_4a87_fb68_6eaa,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0xbb83_e71b_b920_cf26,
|
||||
0x2a52_77ac_92a7_3945,
|
||||
0xfc0e_e59f_94f0_46a0,
|
||||
0x7158_cdf3_7860_58f7,
|
||||
0x7cc1_061b_82f9_45f6,
|
||||
0x03f8_47aa_9fdb_e567,
|
||||
]),
|
||||
},
|
||||
c2: Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0x8078_dba5_6134_e657,
|
||||
0x1cd7_ec9a_4399_8a6e,
|
||||
0xb1aa_599a_1a99_3766,
|
||||
0xc9a0_f62f_0842_ee44,
|
||||
0x8e15_9be3_b605_dffa,
|
||||
0x0c86_ba0d_4af1_3fc2,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0xe80f_f2a0_6a52_ffb1,
|
||||
0x7694_ca48_721a_906c,
|
||||
0x7583_183e_03b0_8514,
|
||||
0xf567_afdd_40ce_e4e2,
|
||||
0x9a6d_96d2_e526_a5fc,
|
||||
0x197e_9f49_861f_2242,
|
||||
]),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn is_identity(&self) -> Choice {
|
||||
self.ct_eq(&Self::identity())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn double(&self) -> Self {
|
||||
self.double()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Clone, Debug)]
|
||||
/// This structure contains cached computations pertaining to a $\mathbb{G}_2$
|
||||
|
@ -558,6 +730,66 @@ fn addition_step(r: &mut G2Projective, q: &G2Affine) -> (Fp2, Fp2, Fp2) {
|
|||
(t10, t1, t9)
|
||||
}
|
||||
|
||||
impl PairingCurveAffine for G1Affine {
|
||||
type Pair = G2Affine;
|
||||
type PairingResult = Gt;
|
||||
|
||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
||||
pairing(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PairingCurveAffine for G2Affine {
|
||||
type Pair = G1Affine;
|
||||
type PairingResult = Gt;
|
||||
|
||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
||||
pairing(other, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`pairing::Engine`] for BLS12-381 pairing operations.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Bls12;
|
||||
|
||||
impl Engine for Bls12 {
|
||||
type Fr = Scalar;
|
||||
type G1 = G1Projective;
|
||||
type G1Affine = G1Affine;
|
||||
type G2 = G2Projective;
|
||||
type G2Affine = G2Affine;
|
||||
type Gt = Gt;
|
||||
|
||||
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
||||
pairing(p, q)
|
||||
}
|
||||
}
|
||||
|
||||
impl pairing::MillerLoopResult for MillerLoopResult {
|
||||
type Gt = Gt;
|
||||
|
||||
fn final_exponentiation(&self) -> Self::Gt {
|
||||
self.final_exponentiation()
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiMillerLoop for Bls12 {
|
||||
type G2Prepared = G2Prepared;
|
||||
type Result = MillerLoopResult;
|
||||
|
||||
fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
|
||||
multi_miller_loop(terms)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gt_generator() {
|
||||
assert_eq!(
|
||||
Gt::generator(),
|
||||
pairing(&G1Affine::generator(), &G2Affine::generator())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bilinearity() {
|
||||
use crate::Scalar;
|
||||
|
|
Loading…
Reference in New Issue