1use core::borrow::Borrow;
4use core::fmt;
5use core::iter::Sum;
6use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7use rand_core::RngCore;
8use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
9
10use super::field::fp::Fp;
11use super::field::fp2::Fp2;
12use super::Scalar;
13
14#[derive(Copy, Clone, Debug)]
16pub struct G2Affine {
17 pub(crate) x: Fp2,
18 pub(crate) y: Fp2,
19 infinity: Choice,
20}
21
22impl Default for G2Affine {
23 fn default() -> G2Affine {
24 G2Affine::identity()
25 }
26}
27
28#[cfg(feature = "zeroize")]
29impl zeroize::DefaultIsZeroes for G2Affine {}
30
31impl fmt::Display for G2Affine {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 write!(f, "{:?}", self)
34 }
35}
36
37impl<'a> From<&'a G2Projective> for G2Affine {
38 fn from(p: &'a G2Projective) -> G2Affine {
39 let zinv = p.z.invert().unwrap_or(Fp2::zero());
40 let x = p.x * zinv;
41 let y = p.y * zinv;
42
43 let tmp = G2Affine {
44 x,
45 y,
46 infinity: Choice::from(0u8),
47 };
48
49 G2Affine::conditional_select(&tmp, &G2Affine::identity(), zinv.is_zero())
50 }
51}
52
53impl From<G2Projective> for G2Affine {
54 fn from(p: G2Projective) -> G2Affine {
55 G2Affine::from(&p)
56 }
57}
58
59impl ConstantTimeEq for G2Affine {
60 fn ct_eq(&self, other: &Self) -> Choice {
61 (self.infinity & other.infinity)
62 | ((!self.infinity)
63 & (!other.infinity)
64 & self.x.ct_eq(&other.x)
65 & self.y.ct_eq(&other.y))
66 }
67}
68
69impl ConditionallySelectable for G2Affine {
70 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
71 G2Affine {
72 x: Fp2::conditional_select(&a.x, &b.x, choice),
73 y: Fp2::conditional_select(&a.y, &b.y, choice),
74 infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice),
75 }
76 }
77}
78
79impl Eq for G2Affine {}
80impl PartialEq for G2Affine {
81 #[inline]
82 fn eq(&self, other: &Self) -> bool {
83 bool::from(self.ct_eq(other))
84 }
85}
86
87impl<'a> Neg for &'a G2Affine {
88 type Output = G2Affine;
89
90 #[inline]
91 fn neg(self) -> G2Affine {
92 G2Affine {
93 x: self.x,
94 y: Fp2::conditional_select(&-self.y, &Fp2::one(), self.infinity),
95 infinity: self.infinity,
96 }
97 }
98}
99
100impl Neg for G2Affine {
101 type Output = G2Affine;
102
103 #[inline]
104 fn neg(self) -> G2Affine {
105 -&self
106 }
107}
108
109impl<'a, 'b> Add<&'b G2Projective> for &'a G2Affine {
110 type Output = G2Projective;
111
112 #[inline]
113 fn add(self, rhs: &'b G2Projective) -> G2Projective {
114 rhs.add_mixed(self)
115 }
116}
117
118impl<'a, 'b> Add<&'b G2Affine> for &'a G2Projective {
119 type Output = G2Projective;
120
121 #[inline]
122 fn add(self, rhs: &'b G2Affine) -> G2Projective {
123 self.add_mixed(rhs)
124 }
125}
126
127impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Affine {
128 type Output = G2Projective;
129
130 #[inline]
131 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
132 self + &(-rhs)
133 }
134}
135
136impl<'a, 'b> Sub<&'b G2Affine> for &'a G2Projective {
137 type Output = G2Projective;
138
139 #[inline]
140 fn sub(self, rhs: &'b G2Affine) -> G2Projective {
141 self + &(-rhs)
142 }
143}
144
145impl<T> Sum<T> for G2Projective
146where
147 T: Borrow<G2Projective>,
148{
149 fn sum<I>(iter: I) -> Self
150 where
151 I: Iterator<Item = T>,
152 {
153 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
154 }
155}
156
157impl<'b> Add<&'b G2Affine> for G2Projective {
159 type Output = G2Projective;
160 #[inline]
161 fn add(self, rhs: &'b G2Affine) -> G2Projective {
162 &self + rhs
163 }
164}
165impl<'a> Add<G2Affine> for &'a G2Projective {
166 type Output = G2Projective;
167 #[inline]
168 fn add(self, rhs: G2Affine) -> G2Projective {
169 self + &rhs
170 }
171}
172impl Add<G2Affine> for G2Projective {
173 type Output = G2Projective;
174 #[inline]
175 fn add(self, rhs: G2Affine) -> G2Projective {
176 &self + &rhs
177 }
178}
179impl<'b> Sub<&'b G2Affine> for G2Projective {
180 type Output = G2Projective;
181 #[inline]
182 fn sub(self, rhs: &'b G2Affine) -> G2Projective {
183 &self - rhs
184 }
185}
186impl<'a> Sub<G2Affine> for &'a G2Projective {
187 type Output = G2Projective;
188 #[inline]
189 fn sub(self, rhs: G2Affine) -> G2Projective {
190 self - &rhs
191 }
192}
193impl Sub<G2Affine> for G2Projective {
194 type Output = G2Projective;
195 #[inline]
196 fn sub(self, rhs: G2Affine) -> G2Projective {
197 &self - &rhs
198 }
199}
200impl SubAssign<G2Affine> for G2Projective {
201 #[inline]
202 fn sub_assign(&mut self, rhs: G2Affine) {
203 *self = &*self - &rhs;
204 }
205}
206impl AddAssign<G2Affine> for G2Projective {
207 #[inline]
208 fn add_assign(&mut self, rhs: G2Affine) {
209 *self = &*self + &rhs;
210 }
211}
212impl<'b> SubAssign<&'b G2Affine> for G2Projective {
213 #[inline]
214 fn sub_assign(&mut self, rhs: &'b G2Affine) {
215 *self = &*self - rhs;
216 }
217}
218impl<'b> AddAssign<&'b G2Affine> for G2Projective {
219 #[inline]
220 fn add_assign(&mut self, rhs: &'b G2Affine) {
221 *self = &*self + rhs;
222 }
223}
224
225impl<'b> Add<&'b G2Projective> for G2Affine {
227 type Output = G2Projective;
228 #[inline]
229 fn add(self, rhs: &'b G2Projective) -> G2Projective {
230 &self + rhs
231 }
232}
233impl<'a> Add<G2Projective> for &'a G2Affine {
234 type Output = G2Projective;
235 #[inline]
236 fn add(self, rhs: G2Projective) -> G2Projective {
237 self + &rhs
238 }
239}
240impl Add<G2Projective> for G2Affine {
241 type Output = G2Projective;
242 #[inline]
243 fn add(self, rhs: G2Projective) -> G2Projective {
244 &self + &rhs
245 }
246}
247impl<'b> Sub<&'b G2Projective> for G2Affine {
248 type Output = G2Projective;
249 #[inline]
250 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
251 &self - rhs
252 }
253}
254impl<'a> Sub<G2Projective> for &'a G2Affine {
255 type Output = G2Projective;
256 #[inline]
257 fn sub(self, rhs: G2Projective) -> G2Projective {
258 self - &rhs
259 }
260}
261impl Sub<G2Projective> for G2Affine {
262 type Output = G2Projective;
263 #[inline]
264 fn sub(self, rhs: G2Projective) -> G2Projective {
265 &self - &rhs
266 }
267}
268
269const B: Fp2 = Fp2 {
271 c0: Fp::from_raw_unchecked([
272 0xaa27_0000_000c_fff3,
273 0x53cc_0032_fc34_000a,
274 0x478f_e97a_6b0a_807f,
275 0xb1d3_7ebe_e6ba_24d7,
276 0x8ec9_733b_bf78_ab2f,
277 0x09d6_4551_3d83_de7e,
278 ]),
279 c1: Fp::from_raw_unchecked([
280 0xaa27_0000_000c_fff3,
281 0x53cc_0032_fc34_000a,
282 0x478f_e97a_6b0a_807f,
283 0xb1d3_7ebe_e6ba_24d7,
284 0x8ec9_733b_bf78_ab2f,
285 0x09d6_4551_3d83_de7e,
286 ]),
287};
288
289const B3: Fp2 = Fp2::add(&Fp2::add(&B, &B), &B);
291
292#[inline(always)]
293fn mul_by_3b(a: Fp2) -> Fp2 {
294 a * B3
295}
296
297impl G2Affine {
298 pub fn identity() -> G2Affine {
300 G2Affine {
301 x: Fp2::zero(),
302 y: Fp2::one(),
303 infinity: Choice::from(1u8),
304 }
305 }
306
307 pub fn generator() -> G2Affine {
309 G2Affine {
310 x: Fp2 {
311 c0: Fp::from_raw_unchecked([
312 0xf5f2_8fa2_0294_0a10,
313 0xb3f5_fb26_87b4_961a,
314 0xa1a8_93b5_3e2a_e580,
315 0x9894_999d_1a3c_aee9,
316 0x6f67_b763_1863_366b,
317 0x0581_9192_4350_bcd7,
318 ]),
319 c1: Fp::from_raw_unchecked([
320 0xa5a9_c075_9e23_f606,
321 0xaaa0_c59d_bccd_60c3,
322 0x3bb1_7e18_e286_7806,
323 0x1b1a_b6cc_8541_b367,
324 0xc2b6_ed0e_f215_8547,
325 0x1192_2a09_7360_edf3,
326 ]),
327 },
328 y: Fp2 {
329 c0: Fp::from_raw_unchecked([
330 0x4c73_0af8_6049_4c4a,
331 0x597c_fa1f_5e36_9c5a,
332 0xe7e6_856c_aa0a_635a,
333 0xbbef_b5e9_6e0d_495f,
334 0x07d3_a975_f0ef_25a2,
335 0x0083_fd8e_7e80_dae5,
336 ]),
337 c1: Fp::from_raw_unchecked([
338 0xadc0_fc92_df64_b05d,
339 0x18aa_270a_2b14_61dc,
340 0x86ad_ac6a_3be4_eba0,
341 0x7949_5c4e_c93d_a33a,
342 0xe717_5850_a43c_caed,
343 0x0b2b_c2a1_63de_1bf2,
344 ]),
345 },
346 infinity: Choice::from(0u8),
347 }
348 }
349
350 pub fn to_compressed(&self) -> [u8; 96] {
352 let x = Fp2::conditional_select(&self.x, &Fp2::zero(), self.infinity);
353 let mut res = [0; 96];
354
355 res[0..48].copy_from_slice(&x.c1.to_bytes());
356 res[48..96].copy_from_slice(&x.c0.to_bytes());
357
358 res[0] |= 1u8 << 7; res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity); res[0] |= u8::conditional_select(
361 &0u8,
362 &(1u8 << 5),
363 (!self.infinity) & self.y.lexicographically_largest(), );
365 res
366 }
367
368 pub fn to_uncompressed(&self) -> [u8; 192] {
370 let mut res = [0; 192];
371 let x = Fp2::conditional_select(&self.x, &Fp2::zero(), self.infinity);
372 let y = Fp2::conditional_select(&self.y, &Fp2::zero(), self.infinity);
373
374 res[0..48].copy_from_slice(&x.c1.to_bytes());
375 res[48..96].copy_from_slice(&x.c0.to_bytes());
376 res[96..144].copy_from_slice(&y.c1.to_bytes());
377 res[144..192].copy_from_slice(&y.c0.to_bytes());
378
379 res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity);
380 res
381 }
382
383 pub fn from_uncompressed(bytes: &[u8; 192]) -> CtOption<Self> {
385 Self::from_uncompressed_unchecked(bytes)
386 .and_then(|p| CtOption::new(p, p.is_on_curve() & p.is_torsion_free()))
387 }
388
389 pub fn from_uncompressed_unchecked(bytes: &[u8; 192]) -> CtOption<Self> {
391 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
392 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
393 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
394
395 let xc1 = {
396 let mut tmp = [0; 48];
397 tmp.copy_from_slice(&bytes[0..48]);
398 tmp[0] &= 0b0001_1111;
399 Fp::from_bytes(&tmp)
400 };
401 let xc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[48..96]).unwrap());
402 let yc1 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[96..144]).unwrap());
403 let yc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[144..192]).unwrap());
404
405 xc1.and_then(|xc1| {
406 xc0.and_then(|xc0| {
407 yc1.and_then(|yc1| {
408 yc0.and_then(|yc0| {
409 let x = Fp2 {c0: xc0, c1: xc1};
410 let y = Fp2 {c0: yc0, c1: yc1};
411
412 let p = G2Affine::conditional_select(
413 &G2Affine {
414 x,
415 y,
416 infinity: infinity_flag_set,
417 },
418 &G2Affine::identity(),
419 infinity_flag_set,
420 );
421 CtOption::new(
422 p,
423 ((!infinity_flag_set) | (infinity_flag_set & x.is_zero() & y.is_zero()))
424 & (!compression_flag_set)
425 & (!sort_flag_set),
426 )
427 })
428 })
429 })
430 })
431 }
432
433 pub fn from_compressed(bytes: &[u8; 96]) -> CtOption<Self> {
435 Self::from_compressed_unchecked(bytes).and_then(|p| CtOption::new(p, p.is_torsion_free()))
436 }
437
438 pub fn from_compressed_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
440 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
441 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
442 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
443
444 let xc1 = {
445 let mut tmp = [0; 48];
446 tmp.copy_from_slice(&bytes[0..48]);
447 tmp[0] &= 0b0001_1111;
448 Fp::from_bytes(&tmp)
449 };
450 let xc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[48..96]).unwrap());
451
452 xc1.and_then(|xc1| {
453 xc0.and_then(|xc0| {
454 let x = Fp2 {c0: xc0, c1: xc1};
455 CtOption::new(
456 G2Affine::identity(),
457 infinity_flag_set & compression_flag_set & (!sort_flag_set) & x.is_zero(),
458 )
459 .or_else(|| {
460 ((x.square() * x) + B).sqrt().and_then(|y| {
461 let y = Fp2::conditional_select(
462 &y,
463 &-y,
464 y.lexicographically_largest() ^ sort_flag_set,
465 );
466 CtOption::new(
467 G2Affine {
468 x,
469 y,
470 infinity: infinity_flag_set,
471 },
472 (!infinity_flag_set) & compression_flag_set,
473 )
474 })
475 })
476 })
477 })
478 }
479
480 #[inline]
482 pub fn is_identity(&self) -> Choice {
483 self.infinity
484 }
485
486 pub fn is_on_curve(&self) -> Choice {
488 (self.y.square() - (self.x.square() * self.x)).ct_eq(&B) | self.infinity
489 }
490
491 pub fn is_torsion_free(&self) -> Choice {
493 let p = G2Projective::from(*self);
496 p.psi().ct_eq(&p.mul_by_x())
497 }
498}
499
500#[derive(Copy, Clone, Debug)]
502pub struct G2Projective {
503 pub(crate) x: Fp2,
504 pub(crate) y: Fp2,
505 pub(crate) z: Fp2,
506}
507
508impl Default for G2Projective {
509 fn default() -> G2Projective {
510 G2Projective::identity()
511 }
512}
513
514#[cfg(feature = "zeroize")]
515impl zeroize::DefaultIsZeroes for G2Projective {}
516
517impl fmt::Display for G2Projective {
518 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
519 write!(f, "{:?}", self)
520 }
521}
522
523impl<'a> From<&'a G2Affine> for G2Projective {
524 fn from(p: &'a G2Affine) -> G2Projective {
525 G2Projective {
526 x: p.x,
527 y: p.y,
528 z: Fp2::conditional_select(&Fp2::one(), &Fp2::zero(), p.infinity),
529 }
530 }
531}
532
533impl From<G2Affine> for G2Projective {
534 fn from(p: G2Affine) -> G2Projective {
535 G2Projective::from(&p)
536 }
537}
538
539impl ConstantTimeEq for G2Projective {
540 fn ct_eq(&self, other: &Self) -> Choice {
541 let x1 = self.x * other.z;
542 let x2 = other.x * self.z;
543 let y1 = self.y * other.z;
544 let y2 = other.y * self.z;
545 let self_is_zero = self.z.is_zero();
546 let other_is_zero = other.z.is_zero();
547
548 (self_is_zero & other_is_zero)
549 | ((!self_is_zero) & (!other_is_zero) & x1.ct_eq(&x2) & y1.ct_eq(&y2))
550 }
551}
552
553impl ConditionallySelectable for G2Projective {
554 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
555 G2Projective {
556 x: Fp2::conditional_select(&a.x, &b.x, choice),
557 y: Fp2::conditional_select(&a.y, &b.y, choice),
558 z: Fp2::conditional_select(&a.z, &b.z, choice),
559 }
560 }
561}
562
563impl Eq for G2Projective {}
564impl PartialEq for G2Projective {
565 #[inline]
566 fn eq(&self, other: &Self) -> bool {
567 bool::from(self.ct_eq(other))
568 }
569}
570
571impl<'a> Neg for &'a G2Projective {
572 type Output = G2Projective;
573
574 #[inline]
575 fn neg(self) -> G2Projective {
576 G2Projective {
577 x: self.x,
578 y: -self.y,
579 z: self.z,
580 }
581 }
582}
583
584impl Neg for G2Projective {
585 type Output = G2Projective;
586
587 #[inline]
588 fn neg(self) -> G2Projective {
589 -&self
590 }
591}
592
593impl<'a, 'b> Add<&'b G2Projective> for &'a G2Projective {
594 type Output = G2Projective;
595
596 #[inline]
597 fn add(self, rhs: &'b G2Projective) -> G2Projective {
598 self.add(rhs)
599 }
600}
601
602impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Projective {
603 type Output = G2Projective;
604
605 #[inline]
606 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
607 self + &(-rhs)
608 }
609}
610
611impl<'a, 'b> Mul<&'b Scalar> for &'a G2Projective {
612 type Output = G2Projective;
613
614 fn mul(self, other: &'b Scalar) -> Self::Output {
615 self.multiply(&other.to_bytes())
616 }
617}
618
619impl<'a, 'b> Mul<&'b G2Projective> for &'a Scalar {
620 type Output = G2Projective;
621
622 #[inline]
623 fn mul(self, rhs: &'b G2Projective) -> Self::Output {
624 rhs * self
625 }
626}
627
628impl<'a, 'b> Mul<&'b Scalar> for &'a G2Affine {
629 type Output = G2Projective;
630
631 fn mul(self, other: &'b Scalar) -> Self::Output {
632 G2Projective::from(self).multiply(&other.to_bytes())
633 }
634}
635
636impl<'a, 'b> Mul<&'b G2Affine> for &'a Scalar {
637 type Output = G2Projective;
638
639 #[inline]
640 fn mul(self, rhs: &'b G2Affine) -> Self::Output {
641 rhs * self
642 }
643}
644
645impl<'b> Add<&'b G2Projective> for G2Projective {
647 type Output = G2Projective;
648 #[inline]
649 fn add(self, rhs: &'b G2Projective) -> G2Projective {
650 &self + rhs
651 }
652}
653impl<'a> Add<G2Projective> for &'a G2Projective {
654 type Output = G2Projective;
655 #[inline]
656 fn add(self, rhs: G2Projective) -> G2Projective {
657 self + &rhs
658 }
659}
660impl Add<G2Projective> for G2Projective {
661 type Output = G2Projective;
662 #[inline]
663 fn add(self, rhs: G2Projective) -> G2Projective {
664 &self + &rhs
665 }
666}
667impl<'b> Sub<&'b G2Projective> for G2Projective {
668 type Output = G2Projective;
669 #[inline]
670 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
671 &self - rhs
672 }
673}
674impl<'a> Sub<G2Projective> for &'a G2Projective {
675 type Output = G2Projective;
676 #[inline]
677 fn sub(self, rhs: G2Projective) -> G2Projective {
678 self - &rhs
679 }
680}
681impl Sub<G2Projective> for G2Projective {
682 type Output = G2Projective;
683 #[inline]
684 fn sub(self, rhs: G2Projective) -> G2Projective {
685 &self - &rhs
686 }
687}
688impl SubAssign<G2Projective> for G2Projective {
689 #[inline]
690 fn sub_assign(&mut self, rhs: G2Projective) {
691 *self = &*self - &rhs;
692 }
693}
694impl AddAssign<G2Projective> for G2Projective {
695 #[inline]
696 fn add_assign(&mut self, rhs: G2Projective) {
697 *self = &*self + &rhs;
698 }
699}
700impl<'b> SubAssign<&'b G2Projective> for G2Projective {
701 #[inline]
702 fn sub_assign(&mut self, rhs: &'b G2Projective) {
703 *self = &*self - rhs;
704 }
705}
706impl<'b> AddAssign<&'b G2Projective> for G2Projective {
707 #[inline]
708 fn add_assign(&mut self, rhs: &'b G2Projective) {
709 *self = &*self + rhs;
710 }
711}
712
713impl<'b> Mul<&'b Scalar> for G2Projective {
715 type Output = G2Projective;
716 #[inline]
717 fn mul(self, rhs: &'b Scalar) -> G2Projective {
718 &self * rhs
719 }
720}
721impl<'a> Mul<Scalar> for &'a G2Projective {
722 type Output = G2Projective;
723 #[inline]
724 fn mul(self, rhs: Scalar) -> G2Projective {
725 self * &rhs
726 }
727}
728impl Mul<Scalar> for G2Projective {
729 type Output = G2Projective;
730 #[inline]
731 fn mul(self, rhs: Scalar) -> G2Projective {
732 &self * &rhs
733 }
734}
735impl MulAssign<Scalar> for G2Projective {
736 #[inline]
737 fn mul_assign(&mut self, rhs: Scalar) {
738 *self = &*self * &rhs;
739 }
740}
741impl<'b> MulAssign<&'b Scalar> for G2Projective {
742 #[inline]
743 fn mul_assign(&mut self, rhs: &'b Scalar) {
744 *self = &*self * rhs;
745 }
746}
747
748impl<'b> Mul<&'b Scalar> for G2Affine {
750 type Output = G2Projective;
751 #[inline]
752 fn mul(self, rhs: &'b Scalar) -> G2Projective {
753 &self * rhs
754 }
755}
756impl<'a> Mul<Scalar> for &'a G2Affine {
757 type Output = G2Projective;
758 #[inline]
759 fn mul(self, rhs: Scalar) -> G2Projective {
760 self * &rhs
761 }
762}
763impl Mul<Scalar> for G2Affine {
764 type Output = G2Projective;
765 #[inline]
766 fn mul(self, rhs: Scalar) -> G2Projective {
767 &self * &rhs
768 }
769}
770
771impl<'b> Mul<&'b G2Affine> for Scalar {
773 type Output = G2Projective;
774 #[inline]
775 fn mul(self, rhs: &'b G2Affine) -> G2Projective {
776 &self * rhs
777 }
778}
779impl<'a> Mul<G2Affine> for &'a Scalar {
780 type Output = G2Projective;
781 #[inline]
782 fn mul(self, rhs: G2Affine) -> G2Projective {
783 self * &rhs
784 }
785}
786impl Mul<G2Affine> for Scalar {
787 type Output = G2Projective;
788 #[inline]
789 fn mul(self, rhs: G2Affine) -> G2Projective {
790 &self * &rhs
791 }
792}
793
794impl<'b> Mul<&'b G2Projective> for Scalar {
796 type Output = G2Projective;
797 #[inline]
798 fn mul(self, rhs: &'b G2Projective) -> G2Projective {
799 &self * rhs
800 }
801}
802impl<'a> Mul<G2Projective> for &'a Scalar {
803 type Output = G2Projective;
804 #[inline]
805 fn mul(self, rhs: G2Projective) -> G2Projective {
806 self * &rhs
807 }
808}
809impl Mul<G2Projective> for Scalar {
810 type Output = G2Projective;
811 #[inline]
812 fn mul(self, rhs: G2Projective) -> G2Projective {
813 &self * &rhs
814 }
815}
816
817impl G2Projective {
818 pub fn identity() -> G2Projective {
820 G2Projective {
821 x: Fp2::zero(),
822 y: Fp2::one(),
823 z: Fp2::zero(),
824 }
825 }
826
827 pub fn generator() -> G2Projective {
829 G2Projective {
830 x: G2Affine::generator().x,
831 y: G2Affine::generator().y,
832 z: Fp2::one(),
833 }
834 }
835
836 pub fn random(mut rng: impl RngCore) -> Self {
838 loop {
839 let x = Fp2::random(&mut rng);
840 let flip_sign = rng.next_u32() % 2 != 0;
841
842 let p = ((x.square() * x) + B).sqrt().map(|y| G2Affine {
843 x,
844 y: if flip_sign { -y } else { y },
845 infinity: 0.into(),
846 });
847
848 if p.is_some().into() {
849 let p_proj = G2Projective::from(p.unwrap());
850 let p_cleared = p_proj.clear_cofactor();
851 if !bool::from(p_cleared.is_identity()) {
852 return p_cleared;
853 }
854 }
855 }
856 }
857
858 pub fn double(&self) -> G2Projective {
860 let t0 = self.y.square();
861 let z3 = t0 + t0;
862 let z3 = z3 + z3;
863 let z3 = z3 + z3;
864 let t1 = self.y * self.z;
865 let t2 = self.z.square();
866 let t2 = mul_by_3b(t2);
867 let x3 = t2 * z3;
868 let y3 = t0 + t2;
869 let z3 = t1 * z3;
870 let t1 = t2 + t2;
871 let t2 = t1 + t2;
872 let t0 = t0 - t2;
873 let y3 = t0 * y3;
874 let y3 = x3 + y3;
875 let t1 = self.x * self.y;
876 let x3 = t0 * t1;
877 let x3 = x3 + x3;
878
879 let tmp = G2Projective { x: x3, y: y3, z: z3 };
880 G2Projective::conditional_select(&tmp, &G2Projective::identity(), self.is_identity())
881 }
882
883 pub fn add(&self, rhs: &G2Projective) -> G2Projective {
885 let t0 = self.x * rhs.x;
886 let t1 = self.y * rhs.y;
887 let t2 = self.z * rhs.z;
888 let t3 = self.x + self.y;
889 let t4 = rhs.x + rhs.y;
890 let t3 = t3 * t4;
891 let t4 = t0 + t1;
892 let t3 = t3 - t4;
893 let t4 = self.y + self.z;
894 let x3 = rhs.y + rhs.z;
895 let t4 = t4 * x3;
896 let x3 = t1 + t2;
897 let t4 = t4 - x3;
898 let x3 = self.x + self.z;
899 let y3 = rhs.x + rhs.z;
900 let x3 = x3 * y3;
901 let y3 = t0 + t2;
902 let y3 = x3 - y3;
903 let x3 = t0 + t0;
904 let t0 = x3 + t0;
905 let t2 = mul_by_3b(t2);
906 let z3 = t1 + t2;
907 let t1 = t1 - t2;
908 let y3 = mul_by_3b(y3);
909 let x3 = t4 * y3;
910 let t2 = t3 * t1;
911 let x3 = t2 - x3;
912 let y3 = y3 * t0;
913 let t1 = t1 * z3;
914 let y3 = t1 + y3;
915 let t0 = t0 * t3;
916 let z3 = z3 * t4;
917 let z3 = z3 + t0;
918
919 G2Projective { x: x3, y: y3, z: z3 }
920 }
921
922 pub fn add_mixed(&self, rhs: &G2Affine) -> G2Projective {
924 let t0 = self.x * rhs.x;
925 let t1 = self.y * rhs.y;
926 let t3 = rhs.x + rhs.y;
927 let t4 = self.x + self.y;
928 let t3 = t3 * t4;
929 let t4 = t0 + t1;
930 let t3 = t3 - t4;
931 let t4 = rhs.y * self.z;
932 let t4 = t4 + self.y;
933 let y3 = rhs.x * self.z;
934 let y3 = y3 + self.x;
935 let x3 = t0 + t0;
936 let t0 = x3 + t0;
937 let t2 = mul_by_3b(self.z);
938 let z3 = t1 + t2;
939 let t1 = t1 - t2;
940 let y3 = mul_by_3b(y3);
941 let x3 = t4 * y3;
942 let t2 = t3 * t1;
943 let x3 = t2 - x3;
944 let y3 = y3 * t0;
945 let t1 = t1 * z3;
946 let y3 = t1 + y3;
947 let t0 = t0 * t3;
948 let z3 = z3 * t4;
949 let z3 = z3 + t0;
950
951 let tmp = G2Projective { x: x3, y: y3, z: z3 };
952 G2Projective::conditional_select(&tmp, self, rhs.is_identity())
953 }
954
955 fn multiply(&self, by: &[u8; 32]) -> G2Projective {
957 let mut acc = G2Projective::identity();
958 for &byte in by.iter().rev() {
959 for i in (0..8).rev() {
960 acc = acc.double();
961 let bit = Choice::from((byte >> i) & 1u8);
962 acc = G2Projective::conditional_select(&acc, &(acc + self), bit);
963 }
964 }
965 acc
966 }
967
968 pub fn clear_cofactor(&self) -> G2Projective {
970 let t1 = self.mul_by_x();
971 let t2 = self.psi();
972 self.double().psi2() + (t1 + t2).mul_by_x() - t1 - t2 - *self
973 }
974
975 fn mul_by_x(&self) -> G2Projective {
977 let mut xself = G2Projective::identity();
978 let mut x = super::BLS_X >> 1;
979 let mut acc = *self;
980 while x != 0 {
981 acc = acc.double();
982 if x % 2 == 1 {
983 xself += acc;
984 }
985 x >>= 1;
986 }
987 if super::BLS_X_IS_NEGATIVE {
988 xself = -xself;
989 }
990 xself
991 }
992
993 fn psi(&self) -> G2Projective {
995 let psi_coeff_x = Fp2 {
997 c0: Fp::zero(),
998 c1: Fp::from_raw_unchecked([
999 0x890d_c9e4_8675_45c3,
1000 0x2af3_2253_3285_a5d5,
1001 0x5088_0866_309b_7e2c,
1002 0xa20d_1b8c_7e88_1024,
1003 0x14e4_f04f_e2db_9068,
1004 0x14e5_6d3f_1564_853a,
1005 ]),
1006 };
1007 let psi_coeff_y = Fp2 {
1009 c0: Fp::from_raw_unchecked([
1010 0x3e2f_585d_a55c_9ad1,
1011 0x4294_213d_86c1_8183,
1012 0x3828_44c8_8b62_3732,
1013 0x92ad_2afd_1910_3e18,
1014 0x1d79_4e4f_ac7c_f0b9,
1015 0x0bd5_92fc_7d82_5ec8,
1016 ]),
1017 c1: Fp::from_raw_unchecked([
1018 0x7bcf_a7a2_5aa3_0fda,
1019 0xdc17_dec1_2a92_7e7c,
1020 0x2f08_8dd8_6b4e_bef1,
1021 0xd1ca_2087_da74_d4a7,
1022 0x2da2_5966_96ce_bc1d,
1023 0x0e2b_7eed_bbfd_87d2,
1024 ]),
1025 };
1026
1027 G2Projective {
1028 x: self.x.frobenius_map() * psi_coeff_x,
1029 y: self.y.frobenius_map() * psi_coeff_y,
1030 z: self.z.frobenius_map(),
1031 }
1032 }
1033
1034 fn psi2(&self) -> G2Projective {
1036 let psi2_coeff_x = Fp2 {
1038 c0: Fp::from_raw_unchecked([
1039 0xcd03_c9e4_8671_f071,
1040 0x5dab_2246_1fcd_a5d2,
1041 0x5870_42af_d385_1b95,
1042 0x8eb6_0ebe_01ba_cb9e,
1043 0x03f9_7d6e_83d0_50d2,
1044 0x18f0_2065_5463_8741,
1045 ]),
1046 c1: Fp::zero(),
1047 };
1048
1049 G2Projective {
1050 x: self.x * psi2_coeff_x,
1051 y: self.y.neg(),
1052 z: self.z,
1053 }
1054 }
1055
1056 pub fn batch_normalize(p: &[Self], q: &mut [G2Affine]) {
1058 assert_eq!(p.len(), q.len());
1059 let mut acc = Fp2::one();
1060 for (p, q) in p.iter().zip(q.iter_mut()) {
1061 q.x = acc;
1062 acc = Fp2::conditional_select(&(acc * p.z), &acc, p.is_identity());
1063 }
1064 acc = acc.invert().unwrap();
1065 for (p, q) in p.iter().rev().zip(q.iter_mut().rev()) {
1066 let skip = p.is_identity();
1067 let tmp = q.x * acc;
1068 acc = Fp2::conditional_select(&(acc * p.z), &acc, skip);
1069 q.x = p.x * tmp;
1070 q.y = p.y * tmp;
1071 q.infinity = Choice::from(0u8);
1072 *q = G2Affine::conditional_select(q, &G2Affine::identity(), skip);
1073 }
1074 }
1075
1076 #[inline]
1078 pub fn is_identity(&self) -> Choice {
1079 self.z.is_zero()
1080 }
1081
1082 pub fn is_on_curve(&self) -> Choice {
1084 (self.y.square() * self.z).ct_eq(&(self.x.square() * self.x + self.z.square() * self.z * B))
1085 | self.z.is_zero()
1086 }
1087
1088 pub fn from_bytes(bytes: &[u8; 96]) -> CtOption<Self> {
1090 G2Affine::from_compressed(bytes).map(G2Projective::from)
1091 }
1092
1093 pub fn from_bytes_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
1095 G2Affine::from_compressed_unchecked(bytes).map(G2Projective::from)
1096 }
1097
1098 pub fn to_bytes(&self) -> [u8; 96] {
1100 G2Affine::from(self).to_compressed()
1101 }
1102}