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::Vec;
13#[cfg(feature = "alloc")]
14use alloc::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) | (infinity_flag_set & x.is_zero() & y.is_zero()))
430 & (!compression_flag_set)
431 & (!sort_flag_set),
432 )
433 })
434 })
435 })
436 })
437 }
438
439 pub fn from_compressed(bytes: &[u8; 96]) -> CtOption<Self> {
441 Self::from_compressed_unchecked(bytes).and_then(|p| CtOption::new(p, p.is_torsion_free()))
442 }
443
444 pub fn from_compressed_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
446 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
447 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
448 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
449
450 let xc1 = {
451 let mut tmp = [0; 48];
452 tmp.copy_from_slice(&bytes[0..48]);
453 tmp[0] &= 0b0001_1111;
454 Fp::from_bytes(&tmp)
455 };
456 let xc0 = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[48..96]).unwrap());
457
458 xc1.and_then(|xc1| {
459 xc0.and_then(|xc0| {
460 let x = Fp2 {c0: xc0, c1: xc1};
461 CtOption::new(
462 G2Affine::identity(),
463 infinity_flag_set & compression_flag_set & (!sort_flag_set) & x.is_zero(),
464 )
465 .or_else(|| {
466 ((x.square() * x) + B).sqrt().and_then(|y| {
467 let y = Fp2::conditional_select(
468 &y,
469 &-y,
470 y.lexicographically_largest() ^ sort_flag_set,
471 );
472 CtOption::new(
473 G2Affine {
474 x,
475 y,
476 infinity: infinity_flag_set,
477 },
478 (!infinity_flag_set) & compression_flag_set,
479 )
480 })
481 })
482 })
483 })
484 }
485
486 #[inline]
488 pub fn is_identity(&self) -> Choice {
489 self.infinity
490 }
491
492 pub fn is_on_curve(&self) -> Choice {
494 (self.y.square() - (self.x.square() * self.x)).ct_eq(&B) | self.infinity
495 }
496
497 pub fn is_torsion_free(&self) -> Choice {
499 let p = G2Projective::from(*self);
502 p.psi().ct_eq(&p.mul_by_x())
503 }
504}
505
506#[derive(Copy, Clone, Debug)]
508pub struct G2Projective {
509 pub(crate) x: Fp2,
510 pub(crate) y: Fp2,
511 pub(crate) z: Fp2,
512}
513
514impl Default for G2Projective {
515 fn default() -> G2Projective {
516 G2Projective::identity()
517 }
518}
519
520#[cfg(feature = "zeroize")]
521impl zeroize::DefaultIsZeroes for G2Projective {}
522
523impl fmt::Display for G2Projective {
524 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
525 write!(f, "{:?}", self)
526 }
527}
528
529impl<'a> From<&'a G2Affine> for G2Projective {
530 fn from(p: &'a G2Affine) -> G2Projective {
531 G2Projective {
532 x: p.x,
533 y: p.y,
534 z: Fp2::conditional_select(&Fp2::one(), &Fp2::zero(), p.infinity),
535 }
536 }
537}
538
539impl From<G2Affine> for G2Projective {
540 fn from(p: G2Affine) -> G2Projective {
541 G2Projective::from(&p)
542 }
543}
544
545impl ConstantTimeEq for G2Projective {
546 fn ct_eq(&self, other: &Self) -> Choice {
547 let x1 = self.x * other.z;
548 let x2 = other.x * self.z;
549 let y1 = self.y * other.z;
550 let y2 = other.y * self.z;
551 let self_is_zero = self.z.is_zero();
552 let other_is_zero = other.z.is_zero();
553
554 (self_is_zero & other_is_zero)
555 | ((!self_is_zero) & (!other_is_zero) & x1.ct_eq(&x2) & y1.ct_eq(&y2))
556 }
557}
558
559impl ConditionallySelectable for G2Projective {
560 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
561 G2Projective {
562 x: Fp2::conditional_select(&a.x, &b.x, choice),
563 y: Fp2::conditional_select(&a.y, &b.y, choice),
564 z: Fp2::conditional_select(&a.z, &b.z, choice),
565 }
566 }
567}
568
569impl Eq for G2Projective {}
570impl PartialEq for G2Projective {
571 #[inline]
572 fn eq(&self, other: &Self) -> bool {
573 bool::from(self.ct_eq(other))
574 }
575}
576
577impl<'a> Neg for &'a G2Projective {
578 type Output = G2Projective;
579
580 #[inline]
581 fn neg(self) -> G2Projective {
582 G2Projective {
583 x: self.x,
584 y: -self.y,
585 z: self.z,
586 }
587 }
588}
589
590impl Neg for G2Projective {
591 type Output = G2Projective;
592
593 #[inline]
594 fn neg(self) -> G2Projective {
595 -&self
596 }
597}
598
599impl<'a, 'b> Add<&'b G2Projective> for &'a G2Projective {
600 type Output = G2Projective;
601
602 #[inline]
603 fn add(self, rhs: &'b G2Projective) -> G2Projective {
604 self.add(rhs)
605 }
606}
607
608impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Projective {
609 type Output = G2Projective;
610
611 #[inline]
612 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
613 self + &(-rhs)
614 }
615}
616
617impl<'a, 'b> Mul<&'b Scalar> for &'a G2Projective {
618 type Output = G2Projective;
619
620 fn mul(self, other: &'b Scalar) -> Self::Output {
621 self.multiply(&other.to_bytes())
622 }
623}
624
625impl<'a, 'b> Mul<&'b G2Projective> for &'a Scalar {
626 type Output = G2Projective;
627
628 #[inline]
629 fn mul(self, rhs: &'b G2Projective) -> Self::Output {
630 rhs * self
631 }
632}
633
634impl<'a, 'b> Mul<&'b Scalar> for &'a G2Affine {
635 type Output = G2Projective;
636
637 fn mul(self, other: &'b Scalar) -> Self::Output {
638 G2Projective::from(self).multiply(&other.to_bytes())
639 }
640}
641
642impl<'a, 'b> Mul<&'b G2Affine> for &'a Scalar {
643 type Output = G2Projective;
644
645 #[inline]
646 fn mul(self, rhs: &'b G2Affine) -> Self::Output {
647 rhs * self
648 }
649}
650
651impl<'b> Add<&'b G2Projective> for G2Projective {
653 type Output = G2Projective;
654 #[inline]
655 fn add(self, rhs: &'b G2Projective) -> G2Projective {
656 &self + rhs
657 }
658}
659impl<'a> Add<G2Projective> for &'a G2Projective {
660 type Output = G2Projective;
661 #[inline]
662 fn add(self, rhs: G2Projective) -> G2Projective {
663 self + &rhs
664 }
665}
666impl Add<G2Projective> for G2Projective {
667 type Output = G2Projective;
668 #[inline]
669 fn add(self, rhs: G2Projective) -> G2Projective {
670 &self + &rhs
671 }
672}
673impl<'b> Sub<&'b G2Projective> for G2Projective {
674 type Output = G2Projective;
675 #[inline]
676 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
677 &self - rhs
678 }
679}
680impl<'a> Sub<G2Projective> for &'a G2Projective {
681 type Output = G2Projective;
682 #[inline]
683 fn sub(self, rhs: G2Projective) -> G2Projective {
684 self - &rhs
685 }
686}
687impl Sub<G2Projective> for G2Projective {
688 type Output = G2Projective;
689 #[inline]
690 fn sub(self, rhs: G2Projective) -> G2Projective {
691 &self - &rhs
692 }
693}
694impl SubAssign<G2Projective> for G2Projective {
695 #[inline]
696 fn sub_assign(&mut self, rhs: G2Projective) {
697 *self = &*self - &rhs;
698 }
699}
700impl AddAssign<G2Projective> for G2Projective {
701 #[inline]
702 fn add_assign(&mut self, rhs: G2Projective) {
703 *self = &*self + &rhs;
704 }
705}
706impl<'b> SubAssign<&'b G2Projective> for G2Projective {
707 #[inline]
708 fn sub_assign(&mut self, rhs: &'b G2Projective) {
709 *self = &*self - rhs;
710 }
711}
712impl<'b> AddAssign<&'b G2Projective> for G2Projective {
713 #[inline]
714 fn add_assign(&mut self, rhs: &'b G2Projective) {
715 *self = &*self + rhs;
716 }
717}
718
719impl<'b> Mul<&'b Scalar> for G2Projective {
721 type Output = G2Projective;
722 #[inline]
723 fn mul(self, rhs: &'b Scalar) -> G2Projective {
724 &self * rhs
725 }
726}
727impl<'a> Mul<Scalar> for &'a G2Projective {
728 type Output = G2Projective;
729 #[inline]
730 fn mul(self, rhs: Scalar) -> G2Projective {
731 self * &rhs
732 }
733}
734impl Mul<Scalar> for G2Projective {
735 type Output = G2Projective;
736 #[inline]
737 fn mul(self, rhs: Scalar) -> G2Projective {
738 &self * &rhs
739 }
740}
741impl MulAssign<Scalar> for G2Projective {
742 #[inline]
743 fn mul_assign(&mut self, rhs: Scalar) {
744 *self = &*self * &rhs;
745 }
746}
747impl<'b> MulAssign<&'b Scalar> for G2Projective {
748 #[inline]
749 fn mul_assign(&mut self, rhs: &'b Scalar) {
750 *self = &*self * rhs;
751 }
752}
753
754impl<'b> Mul<&'b Scalar> for G2Affine {
756 type Output = G2Projective;
757 #[inline]
758 fn mul(self, rhs: &'b Scalar) -> G2Projective {
759 &self * rhs
760 }
761}
762impl<'a> Mul<Scalar> for &'a G2Affine {
763 type Output = G2Projective;
764 #[inline]
765 fn mul(self, rhs: Scalar) -> G2Projective {
766 self * &rhs
767 }
768}
769impl Mul<Scalar> for G2Affine {
770 type Output = G2Projective;
771 #[inline]
772 fn mul(self, rhs: Scalar) -> G2Projective {
773 &self * &rhs
774 }
775}
776
777impl<'b> Mul<&'b G2Affine> for Scalar {
779 type Output = G2Projective;
780 #[inline]
781 fn mul(self, rhs: &'b G2Affine) -> G2Projective {
782 &self * rhs
783 }
784}
785impl<'a> Mul<G2Affine> for &'a Scalar {
786 type Output = G2Projective;
787 #[inline]
788 fn mul(self, rhs: G2Affine) -> G2Projective {
789 self * &rhs
790 }
791}
792impl Mul<G2Affine> for Scalar {
793 type Output = G2Projective;
794 #[inline]
795 fn mul(self, rhs: G2Affine) -> G2Projective {
796 &self * &rhs
797 }
798}
799
800impl<'b> Mul<&'b G2Projective> for Scalar {
802 type Output = G2Projective;
803 #[inline]
804 fn mul(self, rhs: &'b G2Projective) -> G2Projective {
805 &self * rhs
806 }
807}
808impl<'a> Mul<G2Projective> for &'a Scalar {
809 type Output = G2Projective;
810 #[inline]
811 fn mul(self, rhs: G2Projective) -> G2Projective {
812 self * &rhs
813 }
814}
815impl Mul<G2Projective> for Scalar {
816 type Output = G2Projective;
817 #[inline]
818 fn mul(self, rhs: G2Projective) -> G2Projective {
819 &self * &rhs
820 }
821}
822
823impl G2Projective {
824 pub fn identity() -> G2Projective {
826 G2Projective {
827 x: Fp2::zero(),
828 y: Fp2::one(),
829 z: Fp2::zero(),
830 }
831 }
832
833 pub fn generator() -> G2Projective {
835 G2Projective {
836 x: G2Affine::generator().x,
837 y: G2Affine::generator().y,
838 z: Fp2::one(),
839 }
840 }
841
842 pub fn random(mut rng: impl RngCore) -> Self {
844 loop {
845 let x = Fp2::random(&mut rng);
846 let flip_sign = rng.next_u32() % 2 != 0;
847
848 let p = ((x.square() * x) + B).sqrt().map(|y| G2Affine {
849 x,
850 y: if flip_sign { -y } else { y },
851 infinity: 0.into(),
852 });
853
854 if p.is_some().into() {
855 let p_proj = G2Projective::from(p.unwrap());
856 let p_cleared = p_proj.clear_cofactor();
857 if !bool::from(p_cleared.is_identity()) {
858 return p_cleared;
859 }
860 }
861 }
862 }
863
864 #[cfg(feature = "alloc")]
876 pub fn msm_vartime(
877 points: &[G2Affine],
878 scalars: &[Scalar],
879 ) -> Result<Self> {
880 if points.len() != scalars.len() {
881 return Err(Error::Parameter {
882 name: "points/scalars".into(),
883 reason: "Input slices must have the same length".into(),
884 });
885 }
886 Ok(Self::pippenger(points, scalars, true))
887 }
888
889 #[cfg(feature = "alloc")]
897 pub fn msm(
898 points: &[G2Affine],
899 scalars: &[Scalar],
900 ) -> Result<Self> {
901 if points.len() != scalars.len() {
902 return Err(Error::Parameter {
903 name: "points/scalars".into(),
904 reason: "Input slices must have the same length".into(),
905 });
906 }
907 Ok(Self::pippenger(points, scalars, false))
908 }
909
910 #[cfg(feature = "alloc")]
912 fn pippenger(points: &[G2Affine], scalars: &[Scalar], is_vartime: bool) -> Self {
913 if points.is_empty() {
914 return Self::identity();
915 }
916
917 let num_entries = points.len();
918 let scalar_bits = 255; let c = if is_vartime {
923 if num_entries < 32 {
924 3
925 } else {
926 let log2 = (usize::BITS - num_entries.leading_zeros() - 1) as usize;
929 log2 + 2
930 }
931 } else {
932 4
935 };
936
937 let num_windows = (scalar_bits + c - 1) / c;
938 let num_buckets = 1 << c;
939 let mut global_acc = Self::identity();
940
941 for w in (0..num_windows).rev() {
943 let mut window_acc = Self::identity();
944 let mut buckets = vec![Self::identity(); num_buckets];
945
946 for i in 0..num_entries {
948 let scalar_bytes = scalars[i].to_bytes();
949
950 let mut k = 0;
952 for bit_idx in 0..c {
953 let total_bit_idx = w * c + bit_idx;
954 if total_bit_idx < scalar_bits {
955 let byte_idx = total_bit_idx / 8;
956 let inner_bit_idx = total_bit_idx % 8;
957 let byte = scalar_bytes[byte_idx];
958 let bit = (byte >> inner_bit_idx) & 1;
959 k |= (bit as usize) << bit_idx;
960 }
961 }
962
963 if is_vartime {
964 if k > 0 {
965 buckets[k - 1] = buckets[k - 1].add_mixed(&points[i]);
966 }
967 } else {
968 for b in 0..num_buckets {
973 let bucket_idx = b + 1;
974 let choice = k.ct_eq(&bucket_idx);
976
977 let res = buckets[b].add_mixed(&points[i]);
978 buckets[b] = G2Projective::conditional_select(&buckets[b], &res, choice);
979 }
980 }
981 }
982
983 let mut running_sum = Self::identity();
985 for i in (0..num_buckets).rev() {
986 running_sum = running_sum.add(&buckets[i]);
987 window_acc = window_acc.add(&running_sum);
988 }
989
990 global_acc = global_acc.add(&window_acc);
992
993 if w > 0 {
995 for _ in 0..c {
996 global_acc = global_acc.double();
997 }
998 }
999 }
1000
1001 global_acc
1002 }
1003
1004 pub fn double(&self) -> G2Projective {
1010 let t0 = self.y.square();
1011 let z3 = t0 + t0;
1012 let z3 = z3 + z3;
1013 let z3 = z3 + z3;
1014 let t1 = self.y * self.z;
1015 let t2 = self.z.square();
1016 let t2 = mul_by_3b(t2);
1017 let x3 = t2 * z3;
1018 let y3 = t0 + t2;
1019 let z3 = t1 * z3;
1020 let t1 = t2 + t2;
1021 let t2 = t1 + t2;
1022 let t0 = t0 - t2;
1023 let y3 = t0 * y3;
1024 let y3 = x3 + y3;
1025 let t1 = self.x * self.y;
1026 let x3 = t0 * t1;
1027 let x3 = x3 + x3;
1028
1029 let tmp = G2Projective { x: x3, y: y3, z: z3 };
1030 G2Projective::conditional_select(&tmp, &G2Projective::identity(), self.is_identity())
1031 }
1032
1033 pub fn add(&self, rhs: &G2Projective) -> G2Projective {
1035 let t0 = self.x * rhs.x;
1036 let t1 = self.y * rhs.y;
1037 let t2 = self.z * rhs.z;
1038 let t3 = self.x + self.y;
1039 let t4 = rhs.x + rhs.y;
1040 let t3 = t3 * t4;
1041 let t4 = t0 + t1;
1042 let t3 = t3 - t4;
1043 let t4 = self.y + self.z;
1044 let x3 = rhs.y + rhs.z;
1045 let t4 = t4 * x3;
1046 let x3 = t1 + t2;
1047 let t4 = t4 - x3;
1048 let x3 = self.x + self.z;
1049 let y3 = rhs.x + rhs.z;
1050 let x3 = x3 * y3;
1051 let y3 = t0 + t2;
1052 let y3 = x3 - y3;
1053 let x3 = t0 + t0;
1054 let t0 = x3 + t0;
1055 let t2 = mul_by_3b(t2);
1056 let z3 = t1 + t2;
1057 let t1 = t1 - t2;
1058 let y3 = mul_by_3b(y3);
1059 let x3 = t4 * y3;
1060 let t2 = t3 * t1;
1061 let x3 = t2 - x3;
1062 let y3 = y3 * t0;
1063 let t1 = t1 * z3;
1064 let y3 = t1 + y3;
1065 let t0 = t0 * t3;
1066 let z3 = z3 * t4;
1067 let z3 = z3 + t0;
1068
1069 G2Projective { x: x3, y: y3, z: z3 }
1070 }
1071
1072 pub fn add_mixed(&self, rhs: &G2Affine) -> G2Projective {
1074 let t0 = self.x * rhs.x;
1075 let t1 = self.y * rhs.y;
1076 let t3 = rhs.x + rhs.y;
1077 let t4 = self.x + self.y;
1078 let t3 = t3 * t4;
1079 let t4 = t0 + t1;
1080 let t3 = t3 - t4;
1081 let t4 = rhs.y * self.z;
1082 let t4 = t4 + self.y;
1083 let y3 = rhs.x * self.z;
1084 let y3 = y3 + self.x;
1085 let x3 = t0 + t0;
1086 let t0 = x3 + t0;
1087 let t2 = mul_by_3b(self.z);
1088 let z3 = t1 + t2;
1089 let t1 = t1 - t2;
1090 let y3 = mul_by_3b(y3);
1091 let x3 = t4 * y3;
1092 let t2 = t3 * t1;
1093 let x3 = t2 - x3;
1094 let y3 = y3 * t0;
1095 let t1 = t1 * z3;
1096 let y3 = t1 + y3;
1097 let t0 = t0 * t3;
1098 let z3 = z3 * t4;
1099 let z3 = z3 + t0;
1100
1101 let tmp = G2Projective { x: x3, y: y3, z: z3 };
1102 G2Projective::conditional_select(&tmp, self, rhs.is_identity())
1103 }
1104
1105 fn multiply(&self, by: &[u8; 32]) -> G2Projective {
1107 let mut acc = G2Projective::identity();
1108 for &byte in by.iter().rev() {
1109 for i in (0..8).rev() {
1110 acc = acc.double();
1111 let bit = Choice::from((byte >> i) & 1u8);
1112 acc = G2Projective::conditional_select(&acc, &(acc + self), bit);
1113 }
1114 }
1115 acc
1116 }
1117
1118 pub fn clear_cofactor(&self) -> G2Projective {
1120 let t1 = self.mul_by_x();
1121 let t2 = self.psi();
1122 self.double().psi2() + (t1 + t2).mul_by_x() - t1 - t2 - *self
1123 }
1124
1125 fn mul_by_x(&self) -> G2Projective {
1127 let mut xself = G2Projective::identity();
1128 let mut x = super::BLS_X >> 1;
1129 let mut acc = *self;
1130 while x != 0 {
1131 acc = acc.double();
1132 if x % 2 == 1 {
1133 xself += acc;
1134 }
1135 x >>= 1;
1136 }
1137 if super::BLS_X_IS_NEGATIVE {
1138 xself = -xself;
1139 }
1140 xself
1141 }
1142
1143 fn psi(&self) -> G2Projective {
1145 let psi_coeff_x = Fp2 {
1147 c0: Fp::zero(),
1148 c1: Fp::from_raw_unchecked([
1149 0x890d_c9e4_8675_45c3,
1150 0x2af3_2253_3285_a5d5,
1151 0x5088_0866_309b_7e2c,
1152 0xa20d_1b8c_7e88_1024,
1153 0x14e4_f04f_e2db_9068,
1154 0x14e5_6d3f_1564_853a,
1155 ]),
1156 };
1157 let psi_coeff_y = Fp2 {
1159 c0: Fp::from_raw_unchecked([
1160 0x3e2f_585d_a55c_9ad1,
1161 0x4294_213d_86c1_8183,
1162 0x3828_44c8_8b62_3732,
1163 0x92ad_2afd_1910_3e18,
1164 0x1d79_4e4f_ac7c_f0b9,
1165 0x0bd5_92fc_7d82_5ec8,
1166 ]),
1167 c1: Fp::from_raw_unchecked([
1168 0x7bcf_a7a2_5aa3_0fda,
1169 0xdc17_dec1_2a92_7e7c,
1170 0x2f08_8dd8_6b4e_bef1,
1171 0xd1ca_2087_da74_d4a7,
1172 0x2da2_5966_96ce_bc1d,
1173 0x0e2b_7eed_bbfd_87d2,
1174 ]),
1175 };
1176
1177 G2Projective {
1178 x: self.x.frobenius_map() * psi_coeff_x,
1179 y: self.y.frobenius_map() * psi_coeff_y,
1180 z: self.z.frobenius_map(),
1181 }
1182 }
1183
1184 fn psi2(&self) -> G2Projective {
1186 let psi2_coeff_x = Fp2 {
1188 c0: Fp::from_raw_unchecked([
1189 0xcd03_c9e4_8671_f071,
1190 0x5dab_2246_1fcd_a5d2,
1191 0x5870_42af_d385_1b95,
1192 0x8eb6_0ebe_01ba_cb9e,
1193 0x03f9_7d6e_83d0_50d2,
1194 0x18f0_2065_5463_8741,
1195 ]),
1196 c1: Fp::zero(),
1197 };
1198
1199 G2Projective {
1200 x: self.x * psi2_coeff_x,
1201 y: self.y.neg(),
1202 z: self.z,
1203 }
1204 }
1205
1206 pub fn batch_normalize(p: &[Self], q: &mut [G2Affine]) {
1208 assert_eq!(p.len(), q.len());
1209 let mut acc = Fp2::one();
1210 for (p, q) in p.iter().zip(q.iter_mut()) {
1211 q.x = acc;
1212 acc = Fp2::conditional_select(&(acc * p.z), &acc, p.is_identity());
1213 }
1214 acc = acc.invert().unwrap();
1215 for (p, q) in p.iter().rev().zip(q.iter_mut().rev()) {
1216 let skip = p.is_identity();
1217 let tmp = q.x * acc;
1218 acc = Fp2::conditional_select(&(acc * p.z), &acc, skip);
1219 q.x = p.x * tmp;
1220 q.y = p.y * tmp;
1221 q.infinity = Choice::from(0u8);
1222 *q = G2Affine::conditional_select(q, &G2Affine::identity(), skip);
1223 }
1224 }
1225
1226 #[inline]
1228 pub fn is_identity(&self) -> Choice {
1229 self.z.is_zero()
1230 }
1231
1232 pub fn is_on_curve(&self) -> Choice {
1234 (self.y.square() * self.z).ct_eq(&(self.x.square() * self.x + self.z.square() * self.z * B))
1235 | self.z.is_zero()
1236 }
1237
1238 pub fn from_bytes(bytes: &[u8; 96]) -> CtOption<Self> {
1240 G2Affine::from_compressed(bytes).map(G2Projective::from)
1241 }
1242
1243 pub fn from_bytes_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
1245 G2Affine::from_compressed_unchecked(bytes).map(G2Projective::from)
1246 }
1247
1248 pub fn to_bytes(&self) -> [u8; 96] {
1250 G2Affine::from(self).to_compressed()
1251 }
1252}
1253
1254
1255#[cfg(test)]
1256mod tests {
1257 use super::*;
1258
1259 #[test]
1260 fn test_g2_msm() {
1261 let g = G2Affine::generator();
1262 let s1 = Scalar::from(5u64);
1263 let s2 = Scalar::from(6u64);
1264 let s3 = Scalar::from(7u64);
1265
1266 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];
1271 let points = vec![p1, p2, p3];
1272
1273 let expected = G2Projective::from(g) * Scalar::from(110u64);
1275
1276 let naive_result = (p1 * s1) + (p2 * s2) + (p3 * s3);
1278 assert_eq!(G2Affine::from(naive_result), G2Affine::from(expected));
1279
1280 let msm_result_vartime = G2Projective::msm_vartime(&points, &scalars).unwrap();
1282 assert_eq!(G2Affine::from(msm_result_vartime), G2Affine::from(expected));
1283
1284 let msm_result = G2Projective::msm(&points, &scalars).unwrap();
1286 assert_eq!(G2Affine::from(msm_result), G2Affine::from(expected));
1287
1288 let empty_res = G2Projective::msm(&[], &[]).unwrap();
1290 assert_eq!(empty_res, G2Projective::identity());
1291 }
1292}