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