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#[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 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 #[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 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 z4 = t0 - z4;
88 z4 = z4 + z4 + t0;
89
90 z5 = t1 + z5;
91 z5 = z5 + z5 + t1;
92
93 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 .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#[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 pub const IDENTITY: Self = Self(Fp12::ONE);
270
271 pub const BYTES: usize = 576;
273
274 const HEX_BYTES: usize = Self::BYTES * 2;
275
276 #[deprecated(since = "0.5.5", note = "Use IDENTITY instead.")]
278 pub fn identity() -> Gt {
279 Gt(Fp12::ONE)
280 }
281
282 pub fn double(&self) -> Gt {
284 Gt(self.0.square())
285 }
286
287 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 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 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 pub fn product(a: &Self, b: &Self) -> Self {
395 let r = a.0.mul(&b.0);
396 Self(r)
397 }
398
399 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 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 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 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 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#[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)]
725pub 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"))))]
783pub 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#[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
894fn 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 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 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#[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 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 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 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}