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