bls12_381_plus/
pairings.rs

1use crate::fp::Fp;
2use crate::fp12::Fp12;
3use crate::fp2::Fp2;
4use crate::fp6::Fp6;
5use crate::util::decode_hex_byte;
6use crate::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar, BLS_X, BLS_X_IS_NEGATIVE};
7
8use arrayref::array_ref;
9use core::{
10    borrow::Borrow,
11    fmt::{self, Display, Formatter, LowerHex, UpperHex},
12    iter::Sum,
13    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
14};
15use group::{Group, GroupEncoding};
16use pairing::{Engine, PairingCurveAffine};
17use rand_core::RngCore;
18use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
19
20use pairing::MultiMillerLoop;
21
22/// Represents results of a Miller loop, one of the most expensive portions
23/// of the pairing function. `MillerLoopResult`s cannot be compared with each
24/// other until `.final_exponentiation()` is called, which is also expensive.
25#[cfg_attr(docsrs, doc(cfg(feature = "pairings")))]
26#[derive(Copy, Clone, Debug)]
27pub struct MillerLoopResult(pub(crate) Fp12);
28
29impl Default for MillerLoopResult {
30    fn default() -> Self {
31        MillerLoopResult(Fp12::ONE)
32    }
33}
34
35impl zeroize::DefaultIsZeroes for MillerLoopResult {}
36
37impl ConditionallySelectable for MillerLoopResult {
38    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
39        MillerLoopResult(Fp12::conditional_select(&a.0, &b.0, choice))
40    }
41}
42
43impl MillerLoopResult {
44    /// This performs a "final exponentiation" routine to convert the result
45    /// of a Miller loop into an element of `Gt` with help of efficient squaring
46    /// operation in the so-called `cyclotomic subgroup` of `Fq6` so that
47    /// it can be compared with other elements of `Gt`.
48    pub fn final_exponentiation(&self) -> Gt {
49        #[must_use]
50        fn fp4_square(a: Fp2, b: Fp2) -> (Fp2, Fp2) {
51            let t0 = a.square();
52            let t1 = b.square();
53            let mut t2 = t1.mul_by_nonresidue();
54            let c0 = t2 + t0;
55            t2 = a + b;
56            t2 = t2.square();
57            t2 -= t0;
58            let c1 = t2 - t1;
59
60            (c0, c1)
61        }
62        // Adaptation of Algorithm 5.5.4, Guide to Pairing-Based Cryptography
63        // Faster Squaring in the Cyclotomic Subgroup of Sixth Degree Extensions
64        // https://eprint.iacr.org/2009/565.pdf
65        #[must_use]
66        fn cyclotomic_square(f: Fp12) -> Fp12 {
67            let mut z0 = f.c0.c0;
68            let mut z4 = f.c0.c1;
69            let mut z3 = f.c0.c2;
70            let mut z2 = f.c1.c0;
71            let mut z1 = f.c1.c1;
72            let mut z5 = f.c1.c2;
73
74            let (t0, t1) = fp4_square(z0, z1);
75
76            // For A
77            z0 = t0 - z0;
78            z0 = z0 + z0 + t0;
79
80            z1 = t1 + z1;
81            z1 = z1 + z1 + t1;
82
83            let (mut t0, t1) = fp4_square(z2, z3);
84            let (t2, t3) = fp4_square(z4, z5);
85
86            // For C
87            z4 = t0 - z4;
88            z4 = z4 + z4 + t0;
89
90            z5 = t1 + z5;
91            z5 = z5 + z5 + t1;
92
93            // For B
94            t0 = t3.mul_by_nonresidue();
95            z2 = t0 + z2;
96            z2 = z2 + z2 + t0;
97
98            z3 = t2 - z3;
99            z3 = z3 + z3 + t2;
100
101            Fp12 {
102                c0: Fp6 {
103                    c0: z0,
104                    c1: z4,
105                    c2: z3,
106                },
107                c1: Fp6 {
108                    c0: z2,
109                    c1: z1,
110                    c2: z5,
111                },
112            }
113        }
114        #[must_use]
115        fn cycolotomic_exp(f: Fp12) -> Fp12 {
116            let x = BLS_X;
117            let mut tmp = Fp12::ONE;
118            let mut found_one = false;
119            for i in (0..64).rev().map(|b| ((x >> b) & 1) == 1) {
120                if found_one {
121                    tmp = cyclotomic_square(tmp)
122                } else {
123                    found_one = i;
124                }
125
126                if i {
127                    tmp *= f;
128                }
129            }
130
131            tmp.conjugate()
132        }
133
134        let mut f = self.0;
135        let mut t0 = f
136            .frobenius_map()
137            .frobenius_map()
138            .frobenius_map()
139            .frobenius_map()
140            .frobenius_map()
141            .frobenius_map();
142        Gt(f.invert()
143            .map(|mut t1| {
144                let mut t2 = t0 * t1;
145                t1 = t2;
146                t2 = t2.frobenius_map().frobenius_map();
147                t2 *= t1;
148                t1 = cyclotomic_square(t2).conjugate();
149                let mut t3 = cycolotomic_exp(t2);
150                let mut t4 = cyclotomic_square(t3);
151                let mut t5 = t1 * t3;
152                t1 = cycolotomic_exp(t5);
153                t0 = cycolotomic_exp(t1);
154                let mut t6 = cycolotomic_exp(t0);
155                t6 *= t4;
156                t4 = cycolotomic_exp(t6);
157                t5 = t5.conjugate();
158                t4 *= t5 * t2;
159                t5 = t2.conjugate();
160                t1 *= t2;
161                t1 = t1.frobenius_map().frobenius_map().frobenius_map();
162                t6 *= t5;
163                t6 = t6.frobenius_map();
164                t3 *= t0;
165                t3 = t3.frobenius_map().frobenius_map();
166                t3 *= t1;
167                t3 *= t6;
168                f = t3 * t4;
169
170                f
171            })
172            // We unwrap() because `MillerLoopResult` can only be constructed
173            // by a function within this crate, and we uphold the invariant
174            // that the enclosed value is nonzero.
175            .unwrap())
176    }
177}
178
179impl<'a, 'b> Add<&'b MillerLoopResult> for &'a MillerLoopResult {
180    type Output = MillerLoopResult;
181
182    #[inline]
183    fn add(self, rhs: &'b MillerLoopResult) -> MillerLoopResult {
184        MillerLoopResult(self.0 * rhs.0)
185    }
186}
187
188impl_add_binop_specify_output!(MillerLoopResult, MillerLoopResult, MillerLoopResult);
189
190impl AddAssign<MillerLoopResult> for MillerLoopResult {
191    #[inline]
192    fn add_assign(&mut self, rhs: MillerLoopResult) {
193        *self = *self + rhs;
194    }
195}
196
197impl<'b> AddAssign<&'b MillerLoopResult> for MillerLoopResult {
198    #[inline]
199    fn add_assign(&mut self, rhs: &'b MillerLoopResult) {
200        *self = *self + rhs;
201    }
202}
203
204/// This is an element of $\mathbb{G}_T$, the target group of the pairing function. As with
205/// $\mathbb{G}_1$ and $\mathbb{G}_2$ this group has order $q$.
206///
207/// Typically, $\mathbb{G}_T$ is written multiplicatively but we will write it additively to
208/// keep code and abstractions consistent.
209#[cfg_attr(docsrs, doc(cfg(feature = "pairings")))]
210#[derive(Copy, Clone, Debug)]
211pub struct Gt(pub(crate) Fp12);
212
213impl Default for Gt {
214    fn default() -> Self {
215        Self::IDENTITY
216    }
217}
218
219impl zeroize::DefaultIsZeroes for Gt {}
220
221impl LowerHex for Gt {
222    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
223        let bytes = self.to_bytes();
224        for &b in bytes.iter() {
225            write!(f, "{:02x}", b)?;
226        }
227        Ok(())
228    }
229}
230
231impl UpperHex for Gt {
232    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
233        let bytes = self.to_bytes();
234        for &b in bytes.iter() {
235            write!(f, "{:02X}", b)?;
236        }
237        Ok(())
238    }
239}
240
241impl Display for Gt {
242    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
243        write!(f, "{:?}", self)
244    }
245}
246
247impl ConstantTimeEq for Gt {
248    fn ct_eq(&self, other: &Self) -> Choice {
249        self.0.ct_eq(&other.0)
250    }
251}
252
253impl ConditionallySelectable for Gt {
254    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
255        Gt(Fp12::conditional_select(&a.0, &b.0, choice))
256    }
257}
258
259impl Eq for Gt {}
260impl PartialEq for Gt {
261    #[inline]
262    fn eq(&self, other: &Self) -> bool {
263        bool::from(self.ct_eq(other))
264    }
265}
266
267impl Gt {
268    /// The group identity, which is $1$.
269    pub const IDENTITY: Self = Self(Fp12::ONE);
270
271    /// Bytes to represent this field
272    pub const BYTES: usize = 576;
273
274    const HEX_BYTES: usize = Self::BYTES * 2;
275
276    /// Returns the group identity, which is $1$.
277    #[deprecated(since = "0.5.5", note = "Use IDENTITY instead.")]
278    pub fn identity() -> Gt {
279        Gt(Fp12::ONE)
280    }
281
282    /// Doubles this group element.
283    pub fn double(&self) -> Gt {
284        Gt(self.0.square())
285    }
286
287    /// Return the byte representation of this value in big-endian
288    pub fn to_bytes(&self) -> [u8; Self::BYTES] {
289        let mut output = [0u8; Self::BYTES];
290        output[..48].copy_from_slice(&self.0.c0.c0.c0.to_bytes());
291        output[48..96].copy_from_slice(&self.0.c0.c0.c1.to_bytes());
292        output[96..144].copy_from_slice(&self.0.c0.c1.c0.to_bytes());
293        output[144..192].copy_from_slice(&self.0.c0.c1.c1.to_bytes());
294        output[192..240].copy_from_slice(&self.0.c0.c2.c0.to_bytes());
295        output[240..288].copy_from_slice(&self.0.c0.c2.c1.to_bytes());
296        output[288..336].copy_from_slice(&self.0.c1.c0.c0.to_bytes());
297        output[336..384].copy_from_slice(&self.0.c1.c0.c1.to_bytes());
298        output[384..432].copy_from_slice(&self.0.c1.c1.c0.to_bytes());
299        output[432..480].copy_from_slice(&self.0.c1.c1.c1.to_bytes());
300        output[480..528].copy_from_slice(&self.0.c1.c2.c0.to_bytes());
301        output[528..Self::BYTES].copy_from_slice(&self.0.c1.c2.c1.to_bytes());
302        output
303    }
304
305    /// Attempts to convert a big-endian byte representation of
306    /// a scalar into a `Gt`, failing if the input is not canonical.
307    pub fn from_bytes(bytes: &[u8; Self::BYTES]) -> CtOption<Self> {
308        let c000 = Fp::from_bytes(array_ref![bytes, 0, 48]);
309        let c001 = Fp::from_bytes(array_ref![bytes, 48, 48]);
310        let c010 = Fp::from_bytes(array_ref![bytes, 96, 48]);
311        let c011 = Fp::from_bytes(array_ref![bytes, 144, 48]);
312        let c020 = Fp::from_bytes(array_ref![bytes, 192, 48]);
313        let c021 = Fp::from_bytes(array_ref![bytes, 240, 48]);
314        let c100 = Fp::from_bytes(array_ref![bytes, 288, 48]);
315        let c101 = Fp::from_bytes(array_ref![bytes, 336, 48]);
316        let c110 = Fp::from_bytes(array_ref![bytes, 384, 48]);
317        let c111 = Fp::from_bytes(array_ref![bytes, 432, 48]);
318        let c120 = Fp::from_bytes(array_ref![bytes, 480, 48]);
319        let c121 = Fp::from_bytes(array_ref![bytes, 528, 48]);
320
321        c000.and_then(|cc000| {
322            c001.and_then(|cc001| {
323                c010.and_then(|cc010| {
324                    c011.and_then(|cc011| {
325                        c020.and_then(|cc020| {
326                            c021.and_then(|cc021| {
327                                c100.and_then(|cc100| {
328                                    c101.and_then(|cc101| {
329                                        c110.and_then(|cc110| {
330                                            c111.and_then(|cc111| {
331                                                c120.and_then(|cc120| {
332                                                    c121.and_then(|cc121| {
333                                                        CtOption::new(
334                                                            Gt(Fp12 {
335                                                                c0: Fp6 {
336                                                                    c0: Fp2 {
337                                                                        c0: cc000,
338                                                                        c1: cc001,
339                                                                    },
340                                                                    c1: Fp2 {
341                                                                        c0: cc010,
342                                                                        c1: cc011,
343                                                                    },
344                                                                    c2: Fp2 {
345                                                                        c0: cc020,
346                                                                        c1: cc021,
347                                                                    },
348                                                                },
349                                                                c1: Fp6 {
350                                                                    c0: Fp2 {
351                                                                        c0: cc100,
352                                                                        c1: cc101,
353                                                                    },
354                                                                    c1: Fp2 {
355                                                                        c0: cc110,
356                                                                        c1: cc111,
357                                                                    },
358                                                                    c2: Fp2 {
359                                                                        c0: cc120,
360                                                                        c1: cc121,
361                                                                    },
362                                                                },
363                                                            }),
364                                                            Choice::from(1u8),
365                                                        )
366                                                    })
367                                                })
368                                            })
369                                        })
370                                    })
371                                })
372                            })
373                        })
374                    })
375                })
376            })
377        })
378    }
379
380    /// Attempts to convert a big-endian hex representation of
381    /// a scalar into a `Gt`, failing if the input is not canonical.
382    pub fn from_hex(hex: &str) -> CtOption<Self> {
383        let bytes = hex.as_bytes();
384        let mut buf = [0u8; Self::BYTES];
385        let mut i = 0;
386        while i < Self::BYTES {
387            buf[i] = decode_hex_byte([bytes[i * 2], bytes[i * 2 + 1]]);
388            i += 1;
389        }
390        Self::from_bytes(&buf)
391    }
392
393    /// Multiplies two Gt elements together
394    pub fn product(a: &Self, b: &Self) -> Self {
395        let r = a.0.mul(&b.0);
396        Self(r)
397    }
398
399    /// Compute the inverse of this element.
400    pub fn invert(&self) -> CtOption<Self> {
401        self.0.invert().map(|r| Self(r))
402    }
403}
404
405impl<'a> Neg for &'a Gt {
406    type Output = Gt;
407
408    #[inline]
409    fn neg(self) -> Gt {
410        // The element is unitary, so we just conjugate.
411        Gt(self.0.conjugate())
412    }
413}
414
415impl Neg for Gt {
416    type Output = Gt;
417
418    #[inline]
419    fn neg(self) -> Gt {
420        -&self
421    }
422}
423
424impl<'a, 'b> Add<&'b Gt> for &'a Gt {
425    type Output = Gt;
426
427    #[inline]
428    fn add(self, rhs: &'b Gt) -> Gt {
429        Gt(self.0 * rhs.0)
430    }
431}
432
433impl<'a, 'b> Sub<&'b Gt> for &'a Gt {
434    type Output = Gt;
435
436    #[inline]
437    fn sub(self, rhs: &'b Gt) -> Gt {
438        self + (-rhs)
439    }
440}
441
442impl<'a, 'b> Mul<&'b Scalar> for &'a Gt {
443    type Output = Gt;
444
445    fn mul(self, other: &'b Scalar) -> Self::Output {
446        let mut acc = Gt::IDENTITY;
447
448        // This is a simple double-and-add implementation of group element
449        // multiplication, moving from most significant to least
450        // significant bit of the scalar.
451        //
452        // We skip the leading bit because it's always unset for Fq
453        // elements.
454        for bit in other
455            .to_le_bytes()
456            .iter()
457            .rev()
458            .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
459            .skip(1)
460        {
461            acc = acc.double();
462            acc = Gt::conditional_select(&acc, &(acc + self), bit);
463        }
464
465        acc
466    }
467}
468
469impl Mul<Gt> for Gt {
470    type Output = Self;
471
472    fn mul(self, other: Gt) -> Self {
473        Gt::product(&self, &other)
474    }
475}
476
477impl Mul<&Gt> for Gt {
478    type Output = Self;
479
480    fn mul(self, other: &Gt) -> Self {
481        self * *other
482    }
483}
484
485impl Mul<Gt> for &Gt {
486    type Output = Gt;
487
488    fn mul(self, other: Gt) -> Gt {
489        *self * other
490    }
491}
492
493impl Mul<&Gt> for &Gt {
494    type Output = Gt;
495
496    fn mul(self, other: &Gt) -> Gt {
497        *self * *other
498    }
499}
500
501impl_binops_additive!(Gt, Gt);
502impl_binops_multiplicative!(Gt, Scalar);
503
504impl<T> Sum<T> for Gt
505where
506    T: Borrow<Gt>,
507{
508    fn sum<I>(iter: I) -> Self
509    where
510        I: Iterator<Item = T>,
511    {
512        iter.fold(Self::IDENTITY, |acc, item| acc + item.borrow())
513    }
514}
515
516impl Group for Gt {
517    type Scalar = Scalar;
518
519    fn random(mut rng: impl RngCore) -> Self {
520        loop {
521            let inner = Fp12::random(&mut rng);
522
523            // Not all elements of Fp12 are elements of the prime-order multiplicative
524            // subgroup. We run the random element through final_exponentiation to obtain
525            // a valid element, which requires that it is non-zero.
526            if !bool::from(inner.is_zero()) {
527                return MillerLoopResult(inner).final_exponentiation();
528            }
529        }
530    }
531
532    fn identity() -> Self {
533        Self::IDENTITY
534    }
535
536    fn generator() -> Self {
537        // pairing(&G1Affine::generator(), &G2Affine::generator())
538        Gt(Fp12 {
539            c0: Fp6 {
540                c0: Fp2 {
541                    c0: Fp::from_raw_unchecked([
542                        0x1972_e433_a01f_85c5,
543                        0x97d3_2b76_fd77_2538,
544                        0xc8ce_546f_c96b_cdf9,
545                        0xcef6_3e73_66d4_0614,
546                        0xa611_3427_8184_3780,
547                        0x13f3_448a_3fc6_d825,
548                    ]),
549                    c1: Fp::from_raw_unchecked([
550                        0xd263_31b0_2e9d_6995,
551                        0x9d68_a482_f779_7e7d,
552                        0x9c9b_2924_8d39_ea92,
553                        0xf480_1ca2_e131_07aa,
554                        0xa16c_0732_bdbc_b066,
555                        0x083c_a4af_ba36_0478,
556                    ]),
557                },
558                c1: Fp2 {
559                    c0: Fp::from_raw_unchecked([
560                        0x59e2_61db_0916_b641,
561                        0x2716_b6f4_b23e_960d,
562                        0xc8e5_5b10_a0bd_9c45,
563                        0x0bdb_0bd9_9c4d_eda8,
564                        0x8cf8_9ebf_57fd_aac5,
565                        0x12d6_b792_9e77_7a5e,
566                    ]),
567                    c1: Fp::from_raw_unchecked([
568                        0x5fc8_5188_b0e1_5f35,
569                        0x34a0_6e3a_8f09_6365,
570                        0xdb31_26a6_e02a_d62c,
571                        0xfc6f_5aa9_7d9a_990b,
572                        0xa12f_55f5_eb89_c210,
573                        0x1723_703a_926f_8889,
574                    ]),
575                },
576                c2: Fp2 {
577                    c0: Fp::from_raw_unchecked([
578                        0x9358_8f29_7182_8778,
579                        0x43f6_5b86_11ab_7585,
580                        0x3183_aaf5_ec27_9fdf,
581                        0xfa73_d7e1_8ac9_9df6,
582                        0x64e1_76a6_a64c_99b0,
583                        0x179f_a78c_5838_8f1f,
584                    ]),
585                    c1: Fp::from_raw_unchecked([
586                        0x672a_0a11_ca2a_ef12,
587                        0x0d11_b9b5_2aa3_f16b,
588                        0xa444_12d0_699d_056e,
589                        0xc01d_0177_221a_5ba5,
590                        0x66e0_cede_6c73_5529,
591                        0x05f5_a71e_9fdd_c339,
592                    ]),
593                },
594            },
595            c1: Fp6 {
596                c0: Fp2 {
597                    c0: Fp::from_raw_unchecked([
598                        0xd30a_88a1_b062_c679,
599                        0x5ac5_6a5d_35fc_8304,
600                        0xd0c8_34a6_a81f_290d,
601                        0xcd54_30c2_da37_07c7,
602                        0xf0c2_7ff7_8050_0af0,
603                        0x0924_5da6_e2d7_2eae,
604                    ]),
605                    c1: Fp::from_raw_unchecked([
606                        0x9f2e_0676_791b_5156,
607                        0xe2d1_c823_4918_fe13,
608                        0x4c9e_459f_3c56_1bf4,
609                        0xa3e8_5e53_b9d3_e3c1,
610                        0x820a_121e_21a7_0020,
611                        0x15af_6183_41c5_9acc,
612                    ]),
613                },
614                c1: Fp2 {
615                    c0: Fp::from_raw_unchecked([
616                        0x7c95_658c_2499_3ab1,
617                        0x73eb_3872_1ca8_86b9,
618                        0x5256_d749_4774_34bc,
619                        0x8ba4_1902_ea50_4a8b,
620                        0x04a3_d3f8_0c86_ce6d,
621                        0x18a6_4a87_fb68_6eaa,
622                    ]),
623                    c1: Fp::from_raw_unchecked([
624                        0xbb83_e71b_b920_cf26,
625                        0x2a52_77ac_92a7_3945,
626                        0xfc0e_e59f_94f0_46a0,
627                        0x7158_cdf3_7860_58f7,
628                        0x7cc1_061b_82f9_45f6,
629                        0x03f8_47aa_9fdb_e567,
630                    ]),
631                },
632                c2: Fp2 {
633                    c0: Fp::from_raw_unchecked([
634                        0x8078_dba5_6134_e657,
635                        0x1cd7_ec9a_4399_8a6e,
636                        0xb1aa_599a_1a99_3766,
637                        0xc9a0_f62f_0842_ee44,
638                        0x8e15_9be3_b605_dffa,
639                        0x0c86_ba0d_4af1_3fc2,
640                    ]),
641                    c1: Fp::from_raw_unchecked([
642                        0xe80f_f2a0_6a52_ffb1,
643                        0x7694_ca48_721a_906c,
644                        0x7583_183e_03b0_8514,
645                        0xf567_afdd_40ce_e4e2,
646                        0x9a6d_96d2_e526_a5fc,
647                        0x197e_9f49_861f_2242,
648                    ]),
649                },
650            },
651        })
652    }
653
654    fn is_identity(&self) -> Choice {
655        self.ct_eq(&Self::IDENTITY)
656    }
657
658    #[must_use]
659    fn double(&self) -> Self {
660        self.double()
661    }
662}
663
664impl GroupEncoding for Gt {
665    type Repr = GtRepr;
666
667    fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
668        Self::from_bytes(&bytes.0)
669    }
670
671    fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
672        Self::from_bytes(&bytes.0)
673    }
674
675    fn to_bytes(&self) -> Self::Repr {
676        GtRepr(self.to_bytes())
677    }
678}
679
680/// The representation of bytes for Gt
681#[derive(Copy, Clone, Debug)]
682pub struct GtRepr([u8; Gt::BYTES]);
683
684impl Default for GtRepr {
685    fn default() -> Self {
686        Self([0u8; Gt::BYTES])
687    }
688}
689
690impl AsRef<[u8]> for GtRepr {
691    fn as_ref(&self) -> &[u8] {
692        &self.0
693    }
694}
695
696impl AsMut<[u8]> for GtRepr {
697    fn as_mut(&mut self) -> &mut [u8] {
698        self.0.as_mut()
699    }
700}
701
702impl_serde!(
703    Gt,
704    |p: &Gt| p.to_bytes(),
705    |arr: &[u8; Gt::BYTES]| Gt::from_bytes(arr),
706    Gt::BYTES,
707    Gt::HEX_BYTES
708);
709
710impl_from_bytes!(Gt, |p: &Gt| p.to_bytes(), |arr: &[u8]| {
711    if arr.len() != Gt::BYTES {
712        return Err(alloc::format!(
713            "Invalid number of bytes for Gt, expected {}, found {}",
714            Gt::BYTES,
715            arr.len()
716        ));
717    }
718    let mut buf = [0u8; Gt::BYTES];
719    buf.copy_from_slice(arr);
720    Ok(Gt::from_bytes(&buf))
721});
722
723#[cfg_attr(docsrs, doc(cfg(all(feature = "pairings"))))]
724#[derive(Clone, Debug)]
725/// This structure contains cached computations pertaining to a $\mathbb{G}_2$
726/// element as part of the pairing function (specifically, the Miller loop) and
727/// so should be computed whenever a $\mathbb{G}_2$ element is being used in
728/// multiple pairings or is otherwise known in advance. This should be used in
729/// conjunction with the [`multi_miller_loop`](crate::multi_miller_loop)
730/// function provided by this crate.
731///
732/// Requires the `pairing` crate features to be enabled.
733pub struct G2Prepared {
734    infinity: Choice,
735    coeffs: PairingCoefficients,
736}
737
738impl From<G2Affine> for G2Prepared {
739    fn from(q: G2Affine) -> G2Prepared {
740        struct Adder {
741            cur: G2Projective,
742            base: G2Affine,
743            coeffs: PairingCoefficients,
744        }
745
746        impl MillerLoopDriver for Adder {
747            type Output = ();
748
749            fn doubling_step(&mut self, _: Self::Output) -> Self::Output {
750                let coeffs = doubling_step(&mut self.cur);
751                self.coeffs.push(coeffs);
752            }
753            fn addition_step(&mut self, _: Self::Output) -> Self::Output {
754                let coeffs = addition_step(&mut self.cur, &self.base);
755                self.coeffs.push(coeffs);
756            }
757            fn square_output(_: Self::Output) -> Self::Output {}
758            fn conjugate(_: Self::Output) -> Self::Output {}
759            fn one() -> Self::Output {}
760        }
761
762        let is_identity = q.is_identity();
763        let q = G2Affine::conditional_select(&q, &G2Affine::generator(), is_identity);
764
765        let mut adder = Adder {
766            cur: G2Projective::from(q),
767            base: q,
768            coeffs: PairingCoefficients::default(),
769        };
770
771        miller_loop(&mut adder);
772
773        debug_assert_eq!(adder.coeffs.len(), 68);
774
775        G2Prepared {
776            infinity: is_identity,
777            coeffs: adder.coeffs,
778        }
779    }
780}
781
782#[cfg_attr(docsrs, doc(cfg(all(feature = "pairings"))))]
783/// Computes $$\sum_{i=1}^n \textbf{ML}(a_i, b_i)$$ given a series of terms
784/// $$(a_1, b_1), (a_2, b_2), ..., (a_n, b_n).$$
785///
786/// Requires the `pairing` crate features to be enabled.
787pub fn multi_miller_loop(terms: &[(&G1Affine, &G2Prepared)]) -> MillerLoopResult {
788    struct Adder<'a, 'b, 'c> {
789        terms: &'c [(&'a G1Affine, &'b G2Prepared)],
790        index: usize,
791    }
792
793    impl<'a, 'b, 'c> MillerLoopDriver for Adder<'a, 'b, 'c> {
794        type Output = Fp12;
795
796        fn doubling_step(&mut self, mut f: Self::Output) -> Self::Output {
797            let index = self.index;
798            for term in self.terms {
799                let either_identity = term.0.is_identity() | term.1.infinity;
800
801                let new_f = ell(f, &term.1.coeffs[index], term.0);
802                f = Fp12::conditional_select(&new_f, &f, either_identity);
803            }
804            self.index += 1;
805
806            f
807        }
808        fn addition_step(&mut self, mut f: Self::Output) -> Self::Output {
809            let index = self.index;
810            for term in self.terms {
811                let either_identity = term.0.is_identity() | term.1.infinity;
812
813                let new_f = ell(f, &term.1.coeffs[index], term.0);
814                f = Fp12::conditional_select(&new_f, &f, either_identity);
815            }
816            self.index += 1;
817
818            f
819        }
820        fn square_output(f: Self::Output) -> Self::Output {
821            f.square()
822        }
823        fn conjugate(f: Self::Output) -> Self::Output {
824            f.conjugate()
825        }
826        fn one() -> Self::Output {
827            Fp12::ONE
828        }
829    }
830
831    let mut adder = Adder { terms, index: 0 };
832
833    let tmp = miller_loop(&mut adder);
834
835    MillerLoopResult(tmp)
836}
837
838/// Invoke the pairing function without the use of precomputation and other optimizations.
839#[cfg_attr(docsrs, doc(cfg(feature = "pairings")))]
840pub fn pairing(p: &G1Affine, q: &G2Affine) -> Gt {
841    struct Adder {
842        cur: G2Projective,
843        base: G2Affine,
844        p: G1Affine,
845    }
846
847    impl MillerLoopDriver for Adder {
848        type Output = Fp12;
849
850        fn doubling_step(&mut self, f: Self::Output) -> Self::Output {
851            let coeffs = doubling_step(&mut self.cur);
852            ell(f, &coeffs, &self.p)
853        }
854        fn addition_step(&mut self, f: Self::Output) -> Self::Output {
855            let coeffs = addition_step(&mut self.cur, &self.base);
856            ell(f, &coeffs, &self.p)
857        }
858        fn square_output(f: Self::Output) -> Self::Output {
859            f.square()
860        }
861        fn conjugate(f: Self::Output) -> Self::Output {
862            f.conjugate()
863        }
864        fn one() -> Self::Output {
865            Fp12::ONE
866        }
867    }
868
869    let either_identity = p.is_identity() | q.is_identity();
870    let p = G1Affine::conditional_select(p, &G1Affine::generator(), either_identity);
871    let q = G2Affine::conditional_select(q, &G2Affine::generator(), either_identity);
872
873    let mut adder = Adder {
874        cur: G2Projective::from(q),
875        base: q,
876        p,
877    };
878
879    let tmp = miller_loop(&mut adder);
880    let tmp = MillerLoopResult(Fp12::conditional_select(&tmp, &Fp12::ONE, either_identity));
881    tmp.final_exponentiation()
882}
883
884trait MillerLoopDriver {
885    type Output;
886
887    fn doubling_step(&mut self, f: Self::Output) -> Self::Output;
888    fn addition_step(&mut self, f: Self::Output) -> Self::Output;
889    fn square_output(f: Self::Output) -> Self::Output;
890    fn conjugate(f: Self::Output) -> Self::Output;
891    fn one() -> Self::Output;
892}
893
894/// This is a "generic" implementation of the Miller loop to avoid duplicating code
895/// structure elsewhere; instead, we'll write concrete instantiations of
896/// `MillerLoopDriver` for whatever purposes we need (such as caching modes).
897fn miller_loop<D: MillerLoopDriver>(driver: &mut D) -> D::Output {
898    let mut f = D::one();
899
900    let mut found_one = false;
901    for i in (0..64).rev().map(|b| (((BLS_X >> 1) >> b) & 1) == 1) {
902        if !found_one {
903            found_one = i;
904            continue;
905        }
906
907        f = driver.doubling_step(f);
908
909        if i {
910            f = driver.addition_step(f);
911        }
912
913        f = D::square_output(f);
914    }
915
916    f = driver.doubling_step(f);
917
918    if BLS_X_IS_NEGATIVE {
919        f = D::conjugate(f);
920    }
921
922    f
923}
924
925fn ell(f: Fp12, coeffs: &(Fp2, Fp2, Fp2), p: &G1Affine) -> Fp12 {
926    let mut c0 = coeffs.0;
927    let mut c1 = coeffs.1;
928
929    c0.c0 *= p.y;
930    c0.c1 *= p.y;
931
932    c1.c0 *= p.x;
933    c1.c1 *= p.x;
934
935    f.mul_by_014(&coeffs.2, &c1, &c0)
936}
937
938fn doubling_step(r: &mut G2Projective) -> (Fp2, Fp2, Fp2) {
939    // Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
940    let tmp0 = r.x.square();
941    let tmp1 = r.y.square();
942    let tmp2 = tmp1.square();
943    let tmp3 = (tmp1 + r.x).square() - tmp0 - tmp2;
944    let tmp3 = tmp3 + tmp3;
945    let tmp4 = tmp0 + tmp0 + tmp0;
946    let tmp6 = r.x + tmp4;
947    let tmp5 = tmp4.square();
948    let zsquared = r.z.square();
949    r.x = tmp5 - tmp3 - tmp3;
950    r.z = (r.z + r.y).square() - tmp1 - zsquared;
951    r.y = (tmp3 - r.x) * tmp4;
952    let tmp2 = tmp2 + tmp2;
953    let tmp2 = tmp2 + tmp2;
954    let tmp2 = tmp2 + tmp2;
955    r.y -= tmp2;
956    let tmp3 = tmp4 * zsquared;
957    let tmp3 = tmp3 + tmp3;
958    let tmp3 = -tmp3;
959    let tmp6 = tmp6.square() - tmp0 - tmp5;
960    let tmp1 = tmp1 + tmp1;
961    let tmp1 = tmp1 + tmp1;
962    let tmp6 = tmp6 - tmp1;
963    let tmp0 = r.z * zsquared;
964    let tmp0 = tmp0 + tmp0;
965
966    (tmp0, tmp3, tmp6)
967}
968
969fn addition_step(r: &mut G2Projective, q: &G2Affine) -> (Fp2, Fp2, Fp2) {
970    // Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
971    let zsquared = r.z.square();
972    let ysquared = q.y.square();
973    let t0 = zsquared * q.x;
974    let t1 = ((q.y + r.z).square() - ysquared - zsquared) * zsquared;
975    let t2 = t0 - r.x;
976    let t3 = t2.square();
977    let t4 = t3 + t3;
978    let t4 = t4 + t4;
979    let t5 = t4 * t2;
980    let t6 = t1 - r.y - r.y;
981    let t9 = t6 * q.x;
982    let t7 = t4 * r.x;
983    r.x = t6.square() - t5 - t7 - t7;
984    r.z = (r.z + t2).square() - zsquared - t3;
985    let t10 = q.y + r.z;
986    let t8 = (t7 - r.x) * t6;
987    let t0 = r.y * t5;
988    let t0 = t0 + t0;
989    r.y = t8 - t0;
990    let t10 = t10.square() - ysquared;
991    let ztsquared = r.z.square();
992    let t10 = t10 - ztsquared;
993    let t9 = t9 + t9 - t10;
994    let t10 = r.z + r.z;
995    let t6 = -t6;
996    let t1 = t6 + t6;
997
998    (t10, t1, t9)
999}
1000
1001impl PairingCurveAffine for G1Affine {
1002    type Pair = G2Affine;
1003    type PairingResult = Gt;
1004
1005    fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
1006        pairing(self, other)
1007    }
1008}
1009
1010impl PairingCurveAffine for G2Affine {
1011    type Pair = G1Affine;
1012    type PairingResult = Gt;
1013
1014    fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
1015        pairing(other, self)
1016    }
1017}
1018
1019/// A [`pairing::Engine`] for BLS12-381 pairing operations.
1020#[cfg_attr(docsrs, doc(cfg(feature = "pairings")))]
1021#[derive(Clone, Debug)]
1022pub struct Bls12;
1023
1024impl Engine for Bls12 {
1025    type Fr = Scalar;
1026    type G1 = G1Projective;
1027    type G1Affine = G1Affine;
1028    type G2 = G2Projective;
1029    type G2Affine = G2Affine;
1030    type Gt = Gt;
1031
1032    fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
1033        pairing(p, q)
1034    }
1035}
1036
1037impl pairing::MillerLoopResult for MillerLoopResult {
1038    type Gt = Gt;
1039
1040    fn final_exponentiation(&self) -> Self::Gt {
1041        self.final_exponentiation()
1042    }
1043}
1044
1045impl MultiMillerLoop for Bls12 {
1046    type G2Prepared = G2Prepared;
1047    type Result = MillerLoopResult;
1048
1049    fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
1050        multi_miller_loop(terms)
1051    }
1052}
1053
1054#[derive(Clone, Debug)]
1055struct PairingCoefficients {
1056    space: [(Fp2, Fp2, Fp2); 68],
1057    length: usize,
1058}
1059
1060impl Default for PairingCoefficients {
1061    fn default() -> Self {
1062        Self {
1063            space: [(Fp2::ZERO, Fp2::ZERO, Fp2::ZERO); 68],
1064            length: 0,
1065        }
1066    }
1067}
1068
1069impl core::ops::Index<usize> for PairingCoefficients {
1070    type Output = (Fp2, Fp2, Fp2);
1071
1072    fn index(&self, index: usize) -> &Self::Output {
1073        &self.space[index]
1074    }
1075}
1076
1077impl PairingCoefficients {
1078    pub fn push(&mut self, coeffs: (Fp2, Fp2, Fp2)) {
1079        self.space[self.length] = coeffs;
1080        self.length += 1;
1081    }
1082
1083    pub fn len(&self) -> usize {
1084        self.length
1085    }
1086}
1087
1088#[test]
1089fn test_gt_generator() {
1090    assert_eq!(
1091        Gt::generator(),
1092        pairing(&G1Affine::generator(), &G2Affine::generator())
1093    );
1094}
1095
1096#[test]
1097fn test_bilinearity() {
1098    use crate::Scalar;
1099
1100    let a = Scalar::from_raw_unchecked([1, 2, 3, 4])
1101        .invert()
1102        .unwrap()
1103        .square();
1104    let b = Scalar::from_raw_unchecked([5, 6, 7, 8])
1105        .invert()
1106        .unwrap()
1107        .square();
1108    let c = a * b;
1109
1110    let g = G1Affine::from(G1Affine::generator() * a);
1111    let h = G2Affine::from(G2Affine::generator() * b);
1112    let p = pairing(&g, &h);
1113
1114    assert_ne!(p, Gt::IDENTITY);
1115
1116    let expected = G1Affine::from(G1Affine::generator() * c);
1117
1118    assert_eq!(p, pairing(&expected, &G2Affine::generator()));
1119    assert_eq!(
1120        p,
1121        pairing(&G1Affine::generator(), &G2Affine::generator()) * c
1122    );
1123}
1124
1125#[test]
1126fn test_unitary() {
1127    let g = G1Affine::generator();
1128    let h = G2Affine::generator();
1129    let p = -pairing(&g, &h);
1130    let q = pairing(&g, &-h);
1131    let r = pairing(&-g, &h);
1132
1133    assert_eq!(p, q);
1134    assert_eq!(q, r);
1135}
1136
1137#[test]
1138fn test_multi_miller_loop() {
1139    let a1 = G1Affine::generator();
1140    let b1 = G2Affine::generator();
1141
1142    let a2 = G1Affine::from(
1143        G1Affine::generator()
1144            * Scalar::from_raw_unchecked([1, 2, 3, 4])
1145                .invert()
1146                .unwrap()
1147                .square(),
1148    );
1149    let b2 = G2Affine::from(
1150        G2Affine::generator()
1151            * Scalar::from_raw_unchecked([4, 2, 2, 4])
1152                .invert()
1153                .unwrap()
1154                .square(),
1155    );
1156
1157    let a3 = G1Affine::identity();
1158    let b3 = G2Affine::from(
1159        G2Affine::generator()
1160            * Scalar::from_raw_unchecked([9, 2, 2, 4])
1161                .invert()
1162                .unwrap()
1163                .square(),
1164    );
1165
1166    let a4 = G1Affine::from(
1167        G1Affine::generator()
1168            * Scalar::from_raw_unchecked([5, 5, 5, 5])
1169                .invert()
1170                .unwrap()
1171                .square(),
1172    );
1173    let b4 = G2Affine::identity();
1174
1175    let a5 = G1Affine::from(
1176        G1Affine::generator()
1177            * Scalar::from_raw_unchecked([323, 32, 3, 1])
1178                .invert()
1179                .unwrap()
1180                .square(),
1181    );
1182    let b5 = G2Affine::from(
1183        G2Affine::generator()
1184            * Scalar::from_raw_unchecked([4, 2, 2, 9099])
1185                .invert()
1186                .unwrap()
1187                .square(),
1188    );
1189
1190    let b1_prepared = G2Prepared::from(b1);
1191    let b2_prepared = G2Prepared::from(b2);
1192    let b3_prepared = G2Prepared::from(b3);
1193    let b4_prepared = G2Prepared::from(b4);
1194    let b5_prepared = G2Prepared::from(b5);
1195
1196    let expected = pairing(&a1, &b1)
1197        + pairing(&a2, &b2)
1198        + pairing(&a3, &b3)
1199        + pairing(&a4, &b4)
1200        + pairing(&a5, &b5);
1201
1202    let test = multi_miller_loop(&[
1203        (&a1, &b1_prepared),
1204        (&a2, &b2_prepared),
1205        (&a3, &b3_prepared),
1206        (&a4, &b4_prepared),
1207        (&a5, &b5_prepared),
1208    ])
1209    .final_exponentiation();
1210
1211    assert_eq!(expected, test);
1212}
1213
1214#[test]
1215fn test_miller_loop_result_default() {
1216    assert_eq!(
1217        MillerLoopResult::default().final_exponentiation(),
1218        Gt::IDENTITY,
1219    );
1220}
1221
1222#[test]
1223fn test_miller_loop_result_zeroize() {
1224    use zeroize::Zeroize;
1225
1226    let mut m = multi_miller_loop(&[
1227        (&G1Affine::generator(), &G2Affine::generator().into()),
1228        (&-G1Affine::generator(), &G2Affine::generator().into()),
1229    ]);
1230    m.zeroize();
1231    assert_eq!(m.0, MillerLoopResult::default().0);
1232}
1233
1234#[test]
1235fn tricking_miller_loop_result() {
1236    assert_eq!(
1237        multi_miller_loop(&[(&G1Affine::identity(), &G2Affine::generator().into())]).0,
1238        Fp12::ONE
1239    );
1240    assert_eq!(
1241        multi_miller_loop(&[(&G1Affine::generator(), &G2Affine::identity().into())]).0,
1242        Fp12::ONE
1243    );
1244    assert_ne!(
1245        multi_miller_loop(&[
1246            (&G1Affine::generator(), &G2Affine::generator().into()),
1247            (&-G1Affine::generator(), &G2Affine::generator().into())
1248        ])
1249        .0,
1250        Fp12::ONE
1251    );
1252    assert_eq!(
1253        multi_miller_loop(&[
1254            (&G1Affine::generator(), &G2Affine::generator().into()),
1255            (&-G1Affine::generator(), &G2Affine::generator().into())
1256        ])
1257        .final_exponentiation(),
1258        Gt::IDENTITY
1259    );
1260}
1261
1262#[test]
1263fn serialization() {
1264    use rand_core::SeedableRng;
1265    use rand_xorshift::XorShiftRng;
1266
1267    let seed = [1u8; 16];
1268    let rng = XorShiftRng::from_seed(seed);
1269
1270    let t1 = Gt::random(rng);
1271    let bytes = t1.to_bytes();
1272    let res = Gt::from_bytes(&bytes);
1273    assert_eq!(res.is_some().unwrap_u8(), 1u8);
1274    let t2 = res.unwrap();
1275    assert_eq!(t1, t2);
1276
1277    let res = serde_bare::to_vec(&t1);
1278    assert!(res.is_ok());
1279    let bytes = res.unwrap();
1280    let res = serde_bare::from_slice(&bytes);
1281    assert!(res.is_ok());
1282    let t2 = res.unwrap();
1283    assert_eq!(t1, t2);
1284}
1285
1286#[test]
1287fn test_hex() {
1288    let s1 = Gt::generator();
1289    let hex = format!("{:x}", s1);
1290    let s2 = Gt::from_hex(&hex);
1291    assert_eq!(s2.is_some().unwrap_u8(), 1u8);
1292    assert_eq!(s1, s2.unwrap());
1293}
1294
1295#[test]
1296fn test_product() {
1297    use crate::Scalar;
1298    use rand_core::SeedableRng;
1299    use rand_xorshift::XorShiftRng;
1300
1301    // tests Gt * Gt
1302    let s1 = Gt::generator();
1303    let s2 = Gt::generator();
1304    let s3 = s1 * s2;
1305    let s4 = s2 * s1;
1306    assert_eq!(s3, s4);
1307
1308    // test borrowed versions as well
1309
1310    let seed = [1u8; 16];
1311    let seed_2 = [2u8; 16];
1312    let rng_1 = XorShiftRng::from_seed(seed);
1313    let rng_2 = XorShiftRng::from_seed(seed_2);
1314
1315    let t1 = Gt::random(rng_1);
1316    let t2 = Gt::random(rng_2);
1317
1318    let s1 = &t1 * t2;
1319    let s2 = t2 * &t1;
1320
1321    assert_eq!(s1, s2);
1322
1323    // test from Scalars, too
1324
1325    let a = Scalar::from_raw_unchecked([1, 2, 3, 4])
1326        .invert()
1327        .unwrap()
1328        .square();
1329    let b = Scalar::from_raw_unchecked([5, 6, 7, 8])
1330        .invert()
1331        .unwrap()
1332        .square();
1333
1334    let d = G1Affine::from(G1Affine::generator() * a);
1335    let e = G2Affine::from(G2Affine::generator() * b);
1336    let f = pairing(&d, &e);
1337
1338    let g = Scalar::from_raw_unchecked([4, 2, 3, 4])
1339        .invert()
1340        .unwrap()
1341        .square();
1342    let h = Scalar::from_raw_unchecked([8, 6, 7, 8])
1343        .invert()
1344        .unwrap()
1345        .square();
1346
1347    let j = G1Affine::from(G1Affine::generator() * g);
1348    let k = G2Affine::from(G2Affine::generator() * h);
1349    let l = pairing(&j, &k);
1350
1351    let product = f * l;
1352    let product_2 = pairing(&d, &e) * pairing(&j, &k);
1353
1354    assert_eq!(product, product_2);
1355}