1use crate::error::{Error, Result};
4use core::borrow::Borrow;
5use core::fmt;
6use core::iter::Sum;
7use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8use rand_core::RngCore;
9use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
10
11#[cfg(feature = "alloc")]
12use alloc::vec;
13#[cfg(feature = "alloc")]
14use alloc::vec::Vec;
15
16use super::field::fp::Fp;
17use super::field::fp2::Fp2;
18use super::Scalar;
19
20#[derive(Copy, Clone, Debug)]
22pub struct G2Affine {
23 pub(crate) x: Fp2,
24 pub(crate) y: Fp2,
25 infinity: Choice,
26}
27
28impl Default for G2Affine {
29 fn default() -> G2Affine {
30 G2Affine::identity()
31 }
32}
33
34#[cfg(feature = "zeroize")]
35impl zeroize::DefaultIsZeroes for G2Affine {}
36
37impl fmt::Display for G2Affine {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 write!(f, "{:?}", self)
40 }
41}
42
43impl<'a> From<&'a G2Projective> for G2Affine {
44 fn from(p: &'a G2Projective) -> G2Affine {
45 let zinv = p.z.invert().unwrap_or(Fp2::zero());
46 let x = p.x * zinv;
47 let y = p.y * zinv;
48
49 let tmp = G2Affine {
50 x,
51 y,
52 infinity: Choice::from(0u8),
53 };
54
55 G2Affine::conditional_select(&tmp, &G2Affine::identity(), zinv.is_zero())
56 }
57}
58
59impl From<G2Projective> for G2Affine {
60 fn from(p: G2Projective) -> G2Affine {
61 G2Affine::from(&p)
62 }
63}
64
65impl ConstantTimeEq for G2Affine {
66 fn ct_eq(&self, other: &Self) -> Choice {
67 (self.infinity & other.infinity)
68 | ((!self.infinity)
69 & (!other.infinity)
70 & self.x.ct_eq(&other.x)
71 & self.y.ct_eq(&other.y))
72 }
73}
74
75impl ConditionallySelectable for G2Affine {
76 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
77 G2Affine {
78 x: Fp2::conditional_select(&a.x, &b.x, choice),
79 y: Fp2::conditional_select(&a.y, &b.y, choice),
80 infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice),
81 }
82 }
83}
84
85impl Eq for G2Affine {}
86impl PartialEq for G2Affine {
87 #[inline]
88 fn eq(&self, other: &Self) -> bool {
89 bool::from(self.ct_eq(other))
90 }
91}
92
93impl<'a> Neg for &'a G2Affine {
94 type Output = G2Affine;
95
96 #[inline]
97 fn neg(self) -> G2Affine {
98 G2Affine {
99 x: self.x,
100 y: Fp2::conditional_select(&-self.y, &Fp2::one(), self.infinity),
101 infinity: self.infinity,
102 }
103 }
104}
105
106impl Neg for G2Affine {
107 type Output = G2Affine;
108
109 #[inline]
110 fn neg(self) -> G2Affine {
111 -&self
112 }
113}
114
115impl<'a, 'b> Add<&'b G2Projective> for &'a G2Affine {
116 type Output = G2Projective;
117
118 #[inline]
119 fn add(self, rhs: &'b G2Projective) -> G2Projective {
120 rhs.add_mixed(self)
121 }
122}
123
124impl<'a, 'b> Add<&'b G2Affine> for &'a G2Projective {
125 type Output = G2Projective;
126
127 #[inline]
128 fn add(self, rhs: &'b G2Affine) -> G2Projective {
129 self.add_mixed(rhs)
130 }
131}
132
133impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Affine {
134 type Output = G2Projective;
135
136 #[inline]
137 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
138 self + &(-rhs)
139 }
140}
141
142impl<'a, 'b> Sub<&'b G2Affine> for &'a G2Projective {
143 type Output = G2Projective;
144
145 #[inline]
146 fn sub(self, rhs: &'b G2Affine) -> G2Projective {
147 self + &(-rhs)
148 }
149}
150
151impl<T> Sum<T> for G2Projective
152where
153 T: Borrow<G2Projective>,
154{
155 fn sum<I>(iter: I) -> Self
156 where
157 I: Iterator<Item = T>,
158 {
159 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
160 }
161}
162
163impl<'b> Add<&'b G2Affine> for G2Projective {
165 type Output = G2Projective;
166 #[inline]
167 fn add(self, rhs: &'b G2Affine) -> G2Projective {
168 &self + rhs
169 }
170}
171impl<'a> Add<G2Affine> for &'a G2Projective {
172 type Output = G2Projective;
173 #[inline]
174 fn add(self, rhs: G2Affine) -> G2Projective {
175 self + &rhs
176 }
177}
178impl Add<G2Affine> for G2Projective {
179 type Output = G2Projective;
180 #[inline]
181 fn add(self, rhs: G2Affine) -> G2Projective {
182 &self + &rhs
183 }
184}
185impl<'b> Sub<&'b G2Affine> for G2Projective {
186 type Output = G2Projective;
187 #[inline]
188 fn sub(self, rhs: &'b G2Affine) -> G2Projective {
189 &self - rhs
190 }
191}
192impl<'a> Sub<G2Affine> for &'a G2Projective {
193 type Output = G2Projective;
194 #[inline]
195 fn sub(self, rhs: G2Affine) -> G2Projective {
196 self - &rhs
197 }
198}
199impl Sub<G2Affine> for G2Projective {
200 type Output = G2Projective;
201 #[inline]
202 fn sub(self, rhs: G2Affine) -> G2Projective {
203 &self - &rhs
204 }
205}
206impl SubAssign<G2Affine> for G2Projective {
207 #[inline]
208 fn sub_assign(&mut self, rhs: G2Affine) {
209 *self = &*self - &rhs;
210 }
211}
212impl AddAssign<G2Affine> for G2Projective {
213 #[inline]
214 fn add_assign(&mut self, rhs: G2Affine) {
215 *self = &*self + &rhs;
216 }
217}
218impl<'b> SubAssign<&'b G2Affine> for G2Projective {
219 #[inline]
220 fn sub_assign(&mut self, rhs: &'b G2Affine) {
221 *self = &*self - rhs;
222 }
223}
224impl<'b> AddAssign<&'b G2Affine> for G2Projective {
225 #[inline]
226 fn add_assign(&mut self, rhs: &'b G2Affine) {
227 *self = &*self + rhs;
228 }
229}
230
231impl<'b> Add<&'b G2Projective> for G2Affine {
233 type Output = G2Projective;
234 #[inline]
235 fn add(self, rhs: &'b G2Projective) -> G2Projective {
236 &self + rhs
237 }
238}
239impl<'a> Add<G2Projective> for &'a G2Affine {
240 type Output = G2Projective;
241 #[inline]
242 fn add(self, rhs: G2Projective) -> G2Projective {
243 self + &rhs
244 }
245}
246impl Add<G2Projective> for G2Affine {
247 type Output = G2Projective;
248 #[inline]
249 fn add(self, rhs: G2Projective) -> G2Projective {
250 &self + &rhs
251 }
252}
253impl<'b> Sub<&'b G2Projective> for G2Affine {
254 type Output = G2Projective;
255 #[inline]
256 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
257 &self - rhs
258 }
259}
260impl<'a> Sub<G2Projective> for &'a G2Affine {
261 type Output = G2Projective;
262 #[inline]
263 fn sub(self, rhs: G2Projective) -> G2Projective {
264 self - &rhs
265 }
266}
267impl Sub<G2Projective> for G2Affine {
268 type Output = G2Projective;
269 #[inline]
270 fn sub(self, rhs: G2Projective) -> G2Projective {
271 &self - &rhs
272 }
273}
274
275const B: Fp2 = Fp2 {
277 c0: Fp::from_raw_unchecked([
278 0xaa27_0000_000c_fff3,
279 0x53cc_0032_fc34_000a,
280 0x478f_e97a_6b0a_807f,
281 0xb1d3_7ebe_e6ba_24d7,
282 0x8ec9_733b_bf78_ab2f,
283 0x09d6_4551_3d83_de7e,
284 ]),
285 c1: Fp::from_raw_unchecked([
286 0xaa27_0000_000c_fff3,
287 0x53cc_0032_fc34_000a,
288 0x478f_e97a_6b0a_807f,
289 0xb1d3_7ebe_e6ba_24d7,
290 0x8ec9_733b_bf78_ab2f,
291 0x09d6_4551_3d83_de7e,
292 ]),
293};
294
295const B3: Fp2 = Fp2::add(&Fp2::add(&B, &B), &B);
297
298#[inline(always)]
299fn mul_by_3b(a: Fp2) -> Fp2 {
300 a * B3
301}
302
303impl G2Affine {
304 pub fn identity() -> G2Affine {
306 G2Affine {
307 x: Fp2::zero(),
308 y: Fp2::one(),
309 infinity: Choice::from(1u8),
310 }
311 }
312
313 pub fn generator() -> G2Affine {
315 G2Affine {
316 x: Fp2 {
317 c0: Fp::from_raw_unchecked([
318 0xf5f2_8fa2_0294_0a10,
319 0xb3f5_fb26_87b4_961a,
320 0xa1a8_93b5_3e2a_e580,
321 0x9894_999d_1a3c_aee9,
322 0x6f67_b763_1863_366b,
323 0x0581_9192_4350_bcd7,
324 ]),
325 c1: Fp::from_raw_unchecked([
326 0xa5a9_c075_9e23_f606,
327 0xaaa0_c59d_bccd_60c3,
328 0x3bb1_7e18_e286_7806,
329 0x1b1a_b6cc_8541_b367,
330 0xc2b6_ed0e_f215_8547,
331 0x1192_2a09_7360_edf3,
332 ]),
333 },
334 y: Fp2 {
335 c0: Fp::from_raw_unchecked([
336 0x4c73_0af8_6049_4c4a,
337 0x597c_fa1f_5e36_9c5a,
338 0xe7e6_856c_aa0a_635a,
339 0xbbef_b5e9_6e0d_495f,
340 0x07d3_a975_f0ef_25a2,
341 0x0083_fd8e_7e80_dae5,
342 ]),
343 c1: Fp::from_raw_unchecked([
344 0xadc0_fc92_df64_b05d,
345 0x18aa_270a_2b14_61dc,
346 0x86ad_ac6a_3be4_eba0,
347 0x7949_5c4e_c93d_a33a,
348 0xe717_5850_a43c_caed,
349 0x0b2b_c2a1_63de_1bf2,
350 ]),
351 },
352 infinity: Choice::from(0u8),
353 }
354 }
355
356 pub fn to_compressed(&self) -> [u8; 96] {
358 let x = Fp2::conditional_select(&self.x, &Fp2::zero(), self.infinity);
359 let mut res = [0; 96];
360
361 res[0..48].copy_from_slice(&x.c1.to_bytes());
362 res[48..96].copy_from_slice(&x.c0.to_bytes());
363
364 res[0] |= 1u8 << 7; res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity); res[0] |= u8::conditional_select(
367 &0u8,
368 &(1u8 << 5),
369 (!self.infinity) & self.y.lexicographically_largest(), );
371 res
372 }
373
374 pub fn to_uncompressed(&self) -> [u8; 192] {
376 let mut res = [0; 192];
377 let x = Fp2::conditional_select(&self.x, &Fp2::zero(), self.infinity);
378 let y = Fp2::conditional_select(&self.y, &Fp2::zero(), self.infinity);
379
380 res[0..48].copy_from_slice(&x.c1.to_bytes());
381 res[48..96].copy_from_slice(&x.c0.to_bytes());
382 res[96..144].copy_from_slice(&y.c1.to_bytes());
383 res[144..192].copy_from_slice(&y.c0.to_bytes());
384
385 res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity);
386 res
387 }
388
389 pub fn from_uncompressed(bytes: &[u8; 192]) -> CtOption<Self> {
391 Self::from_uncompressed_unchecked(bytes)
392 .and_then(|p| CtOption::new(p, p.is_on_curve() & p.is_torsion_free()))
393 }
394
395 pub fn from_uncompressed_unchecked(bytes: &[u8; 192]) -> CtOption<Self> {
397 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
398 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
399 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
400
401 let xc1 = {
402 let mut tmp = [0; 48];
403 tmp.copy_from_slice(&bytes[0..48]);
404 tmp[0] &= 0b0001_1111;
405 Fp::from_bytes(&tmp)
406 };
407 let xc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[48..96]).unwrap());
408 let yc1 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[96..144]).unwrap());
409 let yc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[144..192]).unwrap());
410
411 xc1.and_then(|xc1| {
412 xc0.and_then(|xc0| {
413 yc1.and_then(|yc1| {
414 yc0.and_then(|yc0| {
415 let x = Fp2 { c0: xc0, c1: xc1 };
416 let y = Fp2 { c0: yc0, c1: yc1 };
417
418 let p = G2Affine::conditional_select(
419 &G2Affine {
420 x,
421 y,
422 infinity: infinity_flag_set,
423 },
424 &G2Affine::identity(),
425 infinity_flag_set,
426 );
427 CtOption::new(
428 p,
429 ((!infinity_flag_set)
430 | (infinity_flag_set & x.is_zero() & y.is_zero()))
431 & (!compression_flag_set)
432 & (!sort_flag_set),
433 )
434 })
435 })
436 })
437 })
438 }
439
440 pub fn from_compressed(bytes: &[u8; 96]) -> CtOption<Self> {
442 Self::from_compressed_unchecked(bytes).and_then(|p| CtOption::new(p, p.is_torsion_free()))
443 }
444
445 pub fn from_compressed_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
447 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
448 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
449 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
450
451 let xc1 = {
452 let mut tmp = [0; 48];
453 tmp.copy_from_slice(&bytes[0..48]);
454 tmp[0] &= 0b0001_1111;
455 Fp::from_bytes(&tmp)
456 };
457 let xc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[48..96]).unwrap());
458
459 xc1.and_then(|xc1| {
460 xc0.and_then(|xc0| {
461 let x = Fp2 { c0: xc0, c1: xc1 };
462 CtOption::new(
463 G2Affine::identity(),
464 infinity_flag_set & compression_flag_set & (!sort_flag_set) & x.is_zero(),
465 )
466 .or_else(|| {
467 ((x.square() * x) + B).sqrt().and_then(|y| {
468 let y = Fp2::conditional_select(
469 &y,
470 &-y,
471 y.lexicographically_largest() ^ sort_flag_set,
472 );
473 CtOption::new(
474 G2Affine {
475 x,
476 y,
477 infinity: infinity_flag_set,
478 },
479 (!infinity_flag_set) & compression_flag_set,
480 )
481 })
482 })
483 })
484 })
485 }
486
487 #[inline]
489 pub fn is_identity(&self) -> Choice {
490 self.infinity
491 }
492
493 pub fn is_on_curve(&self) -> Choice {
495 (self.y.square() - (self.x.square() * self.x)).ct_eq(&B) | self.infinity
496 }
497
498 pub fn is_torsion_free(&self) -> Choice {
500 let p = G2Projective::from(*self);
503 p.psi().ct_eq(&p.mul_by_x())
504 }
505}
506
507#[derive(Copy, Clone, Debug)]
509pub struct G2Projective {
510 pub(crate) x: Fp2,
511 pub(crate) y: Fp2,
512 pub(crate) z: Fp2,
513}
514
515impl Default for G2Projective {
516 fn default() -> G2Projective {
517 G2Projective::identity()
518 }
519}
520
521#[cfg(feature = "zeroize")]
522impl zeroize::DefaultIsZeroes for G2Projective {}
523
524impl fmt::Display for G2Projective {
525 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
526 write!(f, "{:?}", self)
527 }
528}
529
530impl<'a> From<&'a G2Affine> for G2Projective {
531 fn from(p: &'a G2Affine) -> G2Projective {
532 G2Projective {
533 x: p.x,
534 y: p.y,
535 z: Fp2::conditional_select(&Fp2::one(), &Fp2::zero(), p.infinity),
536 }
537 }
538}
539
540impl From<G2Affine> for G2Projective {
541 fn from(p: G2Affine) -> G2Projective {
542 G2Projective::from(&p)
543 }
544}
545
546impl ConstantTimeEq for G2Projective {
547 fn ct_eq(&self, other: &Self) -> Choice {
548 let x1 = self.x * other.z;
549 let x2 = other.x * self.z;
550 let y1 = self.y * other.z;
551 let y2 = other.y * self.z;
552 let self_is_zero = self.z.is_zero();
553 let other_is_zero = other.z.is_zero();
554
555 (self_is_zero & other_is_zero)
556 | ((!self_is_zero) & (!other_is_zero) & x1.ct_eq(&x2) & y1.ct_eq(&y2))
557 }
558}
559
560impl ConditionallySelectable for G2Projective {
561 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
562 G2Projective {
563 x: Fp2::conditional_select(&a.x, &b.x, choice),
564 y: Fp2::conditional_select(&a.y, &b.y, choice),
565 z: Fp2::conditional_select(&a.z, &b.z, choice),
566 }
567 }
568}
569
570impl Eq for G2Projective {}
571impl PartialEq for G2Projective {
572 #[inline]
573 fn eq(&self, other: &Self) -> bool {
574 bool::from(self.ct_eq(other))
575 }
576}
577
578impl<'a> Neg for &'a G2Projective {
579 type Output = G2Projective;
580
581 #[inline]
582 fn neg(self) -> G2Projective {
583 G2Projective {
584 x: self.x,
585 y: -self.y,
586 z: self.z,
587 }
588 }
589}
590
591impl Neg for G2Projective {
592 type Output = G2Projective;
593
594 #[inline]
595 fn neg(self) -> G2Projective {
596 -&self
597 }
598}
599
600impl<'a, 'b> Add<&'b G2Projective> for &'a G2Projective {
601 type Output = G2Projective;
602
603 #[inline]
604 fn add(self, rhs: &'b G2Projective) -> G2Projective {
605 self.add(rhs)
606 }
607}
608
609impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Projective {
610 type Output = G2Projective;
611
612 #[inline]
613 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
614 self + &(-rhs)
615 }
616}
617
618impl<'a, 'b> Mul<&'b Scalar> for &'a G2Projective {
619 type Output = G2Projective;
620
621 fn mul(self, other: &'b Scalar) -> Self::Output {
622 self.multiply(&other.to_bytes())
623 }
624}
625
626impl<'a, 'b> Mul<&'b G2Projective> for &'a Scalar {
627 type Output = G2Projective;
628
629 #[inline]
630 fn mul(self, rhs: &'b G2Projective) -> Self::Output {
631 rhs * self
632 }
633}
634
635impl<'a, 'b> Mul<&'b Scalar> for &'a G2Affine {
636 type Output = G2Projective;
637
638 fn mul(self, other: &'b Scalar) -> Self::Output {
639 G2Projective::from(self).multiply(&other.to_bytes())
640 }
641}
642
643impl<'a, 'b> Mul<&'b G2Affine> for &'a Scalar {
644 type Output = G2Projective;
645
646 #[inline]
647 fn mul(self, rhs: &'b G2Affine) -> Self::Output {
648 rhs * self
649 }
650}
651
652impl<'b> Add<&'b G2Projective> for G2Projective {
654 type Output = G2Projective;
655 #[inline]
656 fn add(self, rhs: &'b G2Projective) -> G2Projective {
657 &self + rhs
658 }
659}
660impl<'a> Add<G2Projective> for &'a G2Projective {
661 type Output = G2Projective;
662 #[inline]
663 fn add(self, rhs: G2Projective) -> G2Projective {
664 self + &rhs
665 }
666}
667impl Add<G2Projective> for G2Projective {
668 type Output = G2Projective;
669 #[inline]
670 fn add(self, rhs: G2Projective) -> G2Projective {
671 &self + &rhs
672 }
673}
674impl<'b> Sub<&'b G2Projective> for G2Projective {
675 type Output = G2Projective;
676 #[inline]
677 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
678 &self - rhs
679 }
680}
681impl<'a> Sub<G2Projective> for &'a G2Projective {
682 type Output = G2Projective;
683 #[inline]
684 fn sub(self, rhs: G2Projective) -> G2Projective {
685 self - &rhs
686 }
687}
688impl Sub<G2Projective> for G2Projective {
689 type Output = G2Projective;
690 #[inline]
691 fn sub(self, rhs: G2Projective) -> G2Projective {
692 &self - &rhs
693 }
694}
695impl SubAssign<G2Projective> for G2Projective {
696 #[inline]
697 fn sub_assign(&mut self, rhs: G2Projective) {
698 *self = &*self - &rhs;
699 }
700}
701impl AddAssign<G2Projective> for G2Projective {
702 #[inline]
703 fn add_assign(&mut self, rhs: G2Projective) {
704 *self = &*self + &rhs;
705 }
706}
707impl<'b> SubAssign<&'b G2Projective> for G2Projective {
708 #[inline]
709 fn sub_assign(&mut self, rhs: &'b G2Projective) {
710 *self = &*self - rhs;
711 }
712}
713impl<'b> AddAssign<&'b G2Projective> for G2Projective {
714 #[inline]
715 fn add_assign(&mut self, rhs: &'b G2Projective) {
716 *self = &*self + rhs;
717 }
718}
719
720impl<'b> Mul<&'b Scalar> for G2Projective {
722 type Output = G2Projective;
723 #[inline]
724 fn mul(self, rhs: &'b Scalar) -> G2Projective {
725 &self * rhs
726 }
727}
728impl<'a> Mul<Scalar> for &'a G2Projective {
729 type Output = G2Projective;
730 #[inline]
731 fn mul(self, rhs: Scalar) -> G2Projective {
732 self * &rhs
733 }
734}
735impl Mul<Scalar> for G2Projective {
736 type Output = G2Projective;
737 #[inline]
738 fn mul(self, rhs: Scalar) -> G2Projective {
739 &self * &rhs
740 }
741}
742impl MulAssign<Scalar> for G2Projective {
743 #[inline]
744 fn mul_assign(&mut self, rhs: Scalar) {
745 *self = &*self * &rhs;
746 }
747}
748impl<'b> MulAssign<&'b Scalar> for G2Projective {
749 #[inline]
750 fn mul_assign(&mut self, rhs: &'b Scalar) {
751 *self = &*self * rhs;
752 }
753}
754
755impl<'b> Mul<&'b Scalar> for G2Affine {
757 type Output = G2Projective;
758 #[inline]
759 fn mul(self, rhs: &'b Scalar) -> G2Projective {
760 &self * rhs
761 }
762}
763impl<'a> Mul<Scalar> for &'a G2Affine {
764 type Output = G2Projective;
765 #[inline]
766 fn mul(self, rhs: Scalar) -> G2Projective {
767 self * &rhs
768 }
769}
770impl Mul<Scalar> for G2Affine {
771 type Output = G2Projective;
772 #[inline]
773 fn mul(self, rhs: Scalar) -> G2Projective {
774 &self * &rhs
775 }
776}
777
778impl<'b> Mul<&'b G2Affine> for Scalar {
780 type Output = G2Projective;
781 #[inline]
782 fn mul(self, rhs: &'b G2Affine) -> G2Projective {
783 &self * rhs
784 }
785}
786impl<'a> Mul<G2Affine> for &'a Scalar {
787 type Output = G2Projective;
788 #[inline]
789 fn mul(self, rhs: G2Affine) -> G2Projective {
790 self * &rhs
791 }
792}
793impl Mul<G2Affine> for Scalar {
794 type Output = G2Projective;
795 #[inline]
796 fn mul(self, rhs: G2Affine) -> G2Projective {
797 &self * &rhs
798 }
799}
800
801impl<'b> Mul<&'b G2Projective> for Scalar {
803 type Output = G2Projective;
804 #[inline]
805 fn mul(self, rhs: &'b G2Projective) -> G2Projective {
806 &self * rhs
807 }
808}
809impl<'a> Mul<G2Projective> for &'a Scalar {
810 type Output = G2Projective;
811 #[inline]
812 fn mul(self, rhs: G2Projective) -> G2Projective {
813 self * &rhs
814 }
815}
816impl Mul<G2Projective> for Scalar {
817 type Output = G2Projective;
818 #[inline]
819 fn mul(self, rhs: G2Projective) -> G2Projective {
820 &self * &rhs
821 }
822}
823
824impl G2Projective {
825 pub fn identity() -> G2Projective {
827 G2Projective {
828 x: Fp2::zero(),
829 y: Fp2::one(),
830 z: Fp2::zero(),
831 }
832 }
833
834 pub fn generator() -> G2Projective {
836 G2Projective {
837 x: G2Affine::generator().x,
838 y: G2Affine::generator().y,
839 z: Fp2::one(),
840 }
841 }
842
843 pub fn random(mut rng: impl RngCore) -> Self {
845 loop {
846 let x = Fp2::random(&mut rng);
847 let flip_sign = rng.next_u32() % 2 != 0;
848
849 let p = ((x.square() * x) + B).sqrt().map(|y| G2Affine {
850 x,
851 y: if flip_sign { -y } else { y },
852 infinity: 0.into(),
853 });
854
855 if p.is_some().into() {
856 let p_proj = G2Projective::from(p.unwrap());
857 let p_cleared = p_proj.clear_cofactor();
858 if !bool::from(p_cleared.is_identity()) {
859 return p_cleared;
860 }
861 }
862 }
863 }
864
865 #[cfg(feature = "alloc")]
877 pub fn msm_vartime(points: &[G2Affine], scalars: &[Scalar]) -> Result<Self> {
878 if points.len() != scalars.len() {
879 return Err(Error::Parameter {
880 name: "points/scalars".into(),
881 reason: "Input slices must have the same length".into(),
882 });
883 }
884 Ok(Self::pippenger(points, scalars, true))
885 }
886
887 #[cfg(feature = "alloc")]
895 pub fn msm(points: &[G2Affine], scalars: &[Scalar]) -> Result<Self> {
896 if points.len() != scalars.len() {
897 return Err(Error::Parameter {
898 name: "points/scalars".into(),
899 reason: "Input slices must have the same length".into(),
900 });
901 }
902 Ok(Self::pippenger(points, scalars, false))
903 }
904
905 #[cfg(feature = "alloc")]
907 fn pippenger(points: &[G2Affine], scalars: &[Scalar], is_vartime: bool) -> Self {
908 if points.is_empty() {
909 return Self::identity();
910 }
911
912 let num_entries = points.len();
913 let scalar_bits = 255; let c = if is_vartime {
918 if num_entries < 32 {
919 3
920 } else {
921 let log2 = (usize::BITS - num_entries.leading_zeros() - 1) as usize;
924 log2 + 2
925 }
926 } else {
927 4
930 };
931
932 let num_windows = (scalar_bits + c - 1) / c;
933 let num_buckets = 1 << c;
934 let mut global_acc = Self::identity();
935
936 for w in (0..num_windows).rev() {
938 let mut window_acc = Self::identity();
939 let mut buckets = vec![Self::identity(); num_buckets];
940
941 for i in 0..num_entries {
943 let scalar_bytes = scalars[i].to_bytes();
944
945 let mut k = 0;
947 for bit_idx in 0..c {
948 let total_bit_idx = w * c + bit_idx;
949 if total_bit_idx < scalar_bits {
950 let byte_idx = total_bit_idx / 8;
951 let inner_bit_idx = total_bit_idx % 8;
952 let byte = scalar_bytes[byte_idx];
953 let bit = (byte >> inner_bit_idx) & 1;
954 k |= (bit as usize) << bit_idx;
955 }
956 }
957
958 if is_vartime {
959 if k > 0 {
960 buckets[k - 1] = buckets[k - 1].add_mixed(&points[i]);
961 }
962 } else {
963 for b in 0..num_buckets {
968 let bucket_idx = b + 1;
969 let choice = k.ct_eq(&bucket_idx);
971
972 let res = buckets[b].add_mixed(&points[i]);
973 buckets[b] = G2Projective::conditional_select(&buckets[b], &res, choice);
974 }
975 }
976 }
977
978 let mut running_sum = Self::identity();
980 for i in (0..num_buckets).rev() {
981 running_sum = running_sum.add(&buckets[i]);
982 window_acc = window_acc.add(&running_sum);
983 }
984
985 global_acc = global_acc.add(&window_acc);
987
988 if w > 0 {
990 for _ in 0..c {
991 global_acc = global_acc.double();
992 }
993 }
994 }
995
996 global_acc
997 }
998
999 pub fn double(&self) -> G2Projective {
1005 let t0 = self.y.square();
1006 let z3 = t0 + t0;
1007 let z3 = z3 + z3;
1008 let z3 = z3 + z3;
1009 let t1 = self.y * self.z;
1010 let t2 = self.z.square();
1011 let t2 = mul_by_3b(t2);
1012 let x3 = t2 * z3;
1013 let y3 = t0 + t2;
1014 let z3 = t1 * z3;
1015 let t1 = t2 + t2;
1016 let t2 = t1 + t2;
1017 let t0 = t0 - t2;
1018 let y3 = t0 * y3;
1019 let y3 = x3 + y3;
1020 let t1 = self.x * self.y;
1021 let x3 = t0 * t1;
1022 let x3 = x3 + x3;
1023
1024 let tmp = G2Projective {
1025 x: x3,
1026 y: y3,
1027 z: z3,
1028 };
1029 G2Projective::conditional_select(&tmp, &G2Projective::identity(), self.is_identity())
1030 }
1031
1032 pub fn add(&self, rhs: &G2Projective) -> G2Projective {
1034 let t0 = self.x * rhs.x;
1035 let t1 = self.y * rhs.y;
1036 let t2 = self.z * rhs.z;
1037 let t3 = self.x + self.y;
1038 let t4 = rhs.x + rhs.y;
1039 let t3 = t3 * t4;
1040 let t4 = t0 + t1;
1041 let t3 = t3 - t4;
1042 let t4 = self.y + self.z;
1043 let x3 = rhs.y + rhs.z;
1044 let t4 = t4 * x3;
1045 let x3 = t1 + t2;
1046 let t4 = t4 - x3;
1047 let x3 = self.x + self.z;
1048 let y3 = rhs.x + rhs.z;
1049 let x3 = x3 * y3;
1050 let y3 = t0 + t2;
1051 let y3 = x3 - y3;
1052 let x3 = t0 + t0;
1053 let t0 = x3 + t0;
1054 let t2 = mul_by_3b(t2);
1055 let z3 = t1 + t2;
1056 let t1 = t1 - t2;
1057 let y3 = mul_by_3b(y3);
1058 let x3 = t4 * y3;
1059 let t2 = t3 * t1;
1060 let x3 = t2 - x3;
1061 let y3 = y3 * t0;
1062 let t1 = t1 * z3;
1063 let y3 = t1 + y3;
1064 let t0 = t0 * t3;
1065 let z3 = z3 * t4;
1066 let z3 = z3 + t0;
1067
1068 G2Projective {
1069 x: x3,
1070 y: y3,
1071 z: z3,
1072 }
1073 }
1074
1075 pub fn add_mixed(&self, rhs: &G2Affine) -> G2Projective {
1077 let t0 = self.x * rhs.x;
1078 let t1 = self.y * rhs.y;
1079 let t3 = rhs.x + rhs.y;
1080 let t4 = self.x + self.y;
1081 let t3 = t3 * t4;
1082 let t4 = t0 + t1;
1083 let t3 = t3 - t4;
1084 let t4 = rhs.y * self.z;
1085 let t4 = t4 + self.y;
1086 let y3 = rhs.x * self.z;
1087 let y3 = y3 + self.x;
1088 let x3 = t0 + t0;
1089 let t0 = x3 + t0;
1090 let t2 = mul_by_3b(self.z);
1091 let z3 = t1 + t2;
1092 let t1 = t1 - t2;
1093 let y3 = mul_by_3b(y3);
1094 let x3 = t4 * y3;
1095 let t2 = t3 * t1;
1096 let x3 = t2 - x3;
1097 let y3 = y3 * t0;
1098 let t1 = t1 * z3;
1099 let y3 = t1 + y3;
1100 let t0 = t0 * t3;
1101 let z3 = z3 * t4;
1102 let z3 = z3 + t0;
1103
1104 let tmp = G2Projective {
1105 x: x3,
1106 y: y3,
1107 z: z3,
1108 };
1109 G2Projective::conditional_select(&tmp, self, rhs.is_identity())
1110 }
1111
1112 fn multiply(&self, by: &[u8; 32]) -> G2Projective {
1114 let mut acc = G2Projective::identity();
1115 for &byte in by.iter().rev() {
1116 for i in (0..8).rev() {
1117 acc = acc.double();
1118 let bit = Choice::from((byte >> i) & 1u8);
1119 acc = G2Projective::conditional_select(&acc, &(acc + self), bit);
1120 }
1121 }
1122 acc
1123 }
1124
1125 pub fn clear_cofactor(&self) -> G2Projective {
1127 let t1 = self.mul_by_x();
1128 let t2 = self.psi();
1129 self.double().psi2() + (t1 + t2).mul_by_x() - t1 - t2 - *self
1130 }
1131
1132 fn mul_by_x(&self) -> G2Projective {
1134 let mut xself = G2Projective::identity();
1135 let mut x = super::BLS_X >> 1;
1136 let mut acc = *self;
1137 while x != 0 {
1138 acc = acc.double();
1139 if x % 2 == 1 {
1140 xself += acc;
1141 }
1142 x >>= 1;
1143 }
1144 if super::BLS_X_IS_NEGATIVE {
1145 xself = -xself;
1146 }
1147 xself
1148 }
1149
1150 fn psi(&self) -> G2Projective {
1152 let psi_coeff_x = Fp2 {
1154 c0: Fp::zero(),
1155 c1: Fp::from_raw_unchecked([
1156 0x890d_c9e4_8675_45c3,
1157 0x2af3_2253_3285_a5d5,
1158 0x5088_0866_309b_7e2c,
1159 0xa20d_1b8c_7e88_1024,
1160 0x14e4_f04f_e2db_9068,
1161 0x14e5_6d3f_1564_853a,
1162 ]),
1163 };
1164 let psi_coeff_y = Fp2 {
1166 c0: Fp::from_raw_unchecked([
1167 0x3e2f_585d_a55c_9ad1,
1168 0x4294_213d_86c1_8183,
1169 0x3828_44c8_8b62_3732,
1170 0x92ad_2afd_1910_3e18,
1171 0x1d79_4e4f_ac7c_f0b9,
1172 0x0bd5_92fc_7d82_5ec8,
1173 ]),
1174 c1: Fp::from_raw_unchecked([
1175 0x7bcf_a7a2_5aa3_0fda,
1176 0xdc17_dec1_2a92_7e7c,
1177 0x2f08_8dd8_6b4e_bef1,
1178 0xd1ca_2087_da74_d4a7,
1179 0x2da2_5966_96ce_bc1d,
1180 0x0e2b_7eed_bbfd_87d2,
1181 ]),
1182 };
1183
1184 G2Projective {
1185 x: self.x.frobenius_map() * psi_coeff_x,
1186 y: self.y.frobenius_map() * psi_coeff_y,
1187 z: self.z.frobenius_map(),
1188 }
1189 }
1190
1191 fn psi2(&self) -> G2Projective {
1193 let psi2_coeff_x = Fp2 {
1195 c0: Fp::from_raw_unchecked([
1196 0xcd03_c9e4_8671_f071,
1197 0x5dab_2246_1fcd_a5d2,
1198 0x5870_42af_d385_1b95,
1199 0x8eb6_0ebe_01ba_cb9e,
1200 0x03f9_7d6e_83d0_50d2,
1201 0x18f0_2065_5463_8741,
1202 ]),
1203 c1: Fp::zero(),
1204 };
1205
1206 G2Projective {
1207 x: self.x * psi2_coeff_x,
1208 y: self.y.neg(),
1209 z: self.z,
1210 }
1211 }
1212
1213 pub fn batch_normalize(p: &[Self], q: &mut [G2Affine]) {
1215 assert_eq!(p.len(), q.len());
1216 let mut acc = Fp2::one();
1217 for (p, q) in p.iter().zip(q.iter_mut()) {
1218 q.x = acc;
1219 acc = Fp2::conditional_select(&(acc * p.z), &acc, p.is_identity());
1220 }
1221 acc = acc.invert().unwrap();
1222 for (p, q) in p.iter().rev().zip(q.iter_mut().rev()) {
1223 let skip = p.is_identity();
1224 let tmp = q.x * acc;
1225 acc = Fp2::conditional_select(&(acc * p.z), &acc, skip);
1226 q.x = p.x * tmp;
1227 q.y = p.y * tmp;
1228 q.infinity = Choice::from(0u8);
1229 *q = G2Affine::conditional_select(q, &G2Affine::identity(), skip);
1230 }
1231 }
1232
1233 #[inline]
1235 pub fn is_identity(&self) -> Choice {
1236 self.z.is_zero()
1237 }
1238
1239 pub fn is_on_curve(&self) -> Choice {
1241 (self.y.square() * self.z).ct_eq(&(self.x.square() * self.x + self.z.square() * self.z * B))
1242 | self.z.is_zero()
1243 }
1244
1245 pub fn from_bytes(bytes: &[u8; 96]) -> CtOption<Self> {
1247 G2Affine::from_compressed(bytes).map(G2Projective::from)
1248 }
1249
1250 pub fn from_bytes_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
1252 G2Affine::from_compressed_unchecked(bytes).map(G2Projective::from)
1253 }
1254
1255 pub fn to_bytes(&self) -> [u8; 96] {
1257 G2Affine::from(self).to_compressed()
1258 }
1259}
1260
1261#[cfg(test)]
1262mod tests {
1263 use super::*;
1264
1265 #[test]
1266 fn test_g2_msm() {
1267 let g = G2Affine::generator();
1268 let s1 = Scalar::from(5u64);
1269 let s2 = Scalar::from(6u64);
1270 let s3 = Scalar::from(7u64);
1271
1272 let p1 = G2Affine::from(G2Projective::from(g) * s1); let p2 = G2Affine::from(G2Projective::from(g) * s2); let p3 = G2Affine::from(G2Projective::from(g) * s3); let scalars = vec![s1, s2, s3];
1277 let points = vec![p1, p2, p3];
1278
1279 let expected = G2Projective::from(g) * Scalar::from(110u64);
1281
1282 let naive_result = (p1 * s1) + (p2 * s2) + (p3 * s3);
1284 assert_eq!(G2Affine::from(naive_result), G2Affine::from(expected));
1285
1286 let msm_result_vartime = G2Projective::msm_vartime(&points, &scalars).unwrap();
1288 assert_eq!(G2Affine::from(msm_result_vartime), G2Affine::from(expected));
1289
1290 let msm_result = G2Projective::msm(&points, &scalars).unwrap();
1292 assert_eq!(G2Affine::from(msm_result), G2Affine::from(expected));
1293
1294 let empty_res = G2Projective::msm(&[], &[]).unwrap();
1296 assert_eq!(empty_res, G2Projective::identity());
1297 }
1298}