1use super::super::{Bls12, Fq, Fq12, Fq2, FqRepr, Fr, FrRepr};
2use super::g1::G1Affine;
3use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
4use std::fmt;
5use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError, SubgroupCheck};
6
7curve_impl!(
8 "G2",
9 G2,
10 G2Affine,
11 G2Prepared,
12 Fq2,
13 Fr,
14 G2Uncompressed,
15 G2Compressed,
16 G1Affine
17);
18
19#[derive(Copy, Clone)]
20pub struct G2Uncompressed([u8; 192]);
21
22impl AsRef<[u8]> for G2Uncompressed {
23 fn as_ref(&self) -> &[u8] {
24 &self.0
25 }
26}
27
28impl AsMut<[u8]> for G2Uncompressed {
29 fn as_mut(&mut self) -> &mut [u8] {
30 &mut self.0
31 }
32}
33
34impl fmt::Debug for G2Uncompressed {
35 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
36 self.0[..].fmt(formatter)
37 }
38}
39
40impl EncodedPoint for G2Uncompressed {
41 type Affine = G2Affine;
42
43 fn empty() -> Self {
44 G2Uncompressed([0; 192])
45 }
46 fn size() -> usize {
47 192
48 }
49 fn into_affine(&self) -> Result<G2Affine, GroupDecodingError> {
50 let affine = self.into_affine_unchecked()?;
51
52 if !affine.is_on_curve() {
53 Err(GroupDecodingError::NotOnCurve)
54 } else if !affine.in_subgroup() {
55 Err(GroupDecodingError::NotInSubgroup)
56 } else {
57 Ok(affine)
58 }
59 }
60 fn into_affine_unchecked(&self) -> Result<G2Affine, GroupDecodingError> {
61 let mut copy = self.0;
63
64 if copy[0] & (1 << 7) != 0 {
65 return Err(GroupDecodingError::UnexpectedCompressionMode);
67 }
68
69 if copy[0] & (1 << 6) != 0 {
70 copy[0] &= 0x3f;
74
75 if copy.iter().all(|b| *b == 0) {
76 Ok(G2Affine::zero())
77 } else {
78 Err(GroupDecodingError::UnexpectedInformation)
79 }
80 } else {
81 if copy[0] & (1 << 5) != 0 {
82 return Err(GroupDecodingError::UnexpectedInformation);
85 }
86
87 copy[0] &= 0x1f;
89
90 let mut x_c0 = FqRepr([0; 6]);
91 let mut x_c1 = FqRepr([0; 6]);
92 let mut y_c0 = FqRepr([0; 6]);
93 let mut y_c1 = FqRepr([0; 6]);
94
95 {
96 let mut reader = ©[..];
97
98 x_c1.read_be(&mut reader).unwrap();
99 x_c0.read_be(&mut reader).unwrap();
100 y_c1.read_be(&mut reader).unwrap();
101 y_c0.read_be(&mut reader).unwrap();
102 }
103
104 Ok(G2Affine {
105 x: Fq2 {
106 c0: Fq::from_repr(x_c0).map_err(|e| {
107 GroupDecodingError::CoordinateDecodingError("x coordinate (c0)", e)
108 })?,
109 c1: Fq::from_repr(x_c1).map_err(|e| {
110 GroupDecodingError::CoordinateDecodingError("x coordinate (c1)", e)
111 })?,
112 },
113 y: Fq2 {
114 c0: Fq::from_repr(y_c0).map_err(|e| {
115 GroupDecodingError::CoordinateDecodingError("y coordinate (c0)", e)
116 })?,
117 c1: Fq::from_repr(y_c1).map_err(|e| {
118 GroupDecodingError::CoordinateDecodingError("y coordinate (c1)", e)
119 })?,
120 },
121 infinity: false,
122 })
123 }
124 }
125 fn from_affine(affine: G2Affine) -> Self {
126 let mut res = Self::empty();
127
128 if affine.is_zero() {
129 res.0[0] |= 1 << 6;
132 } else {
133 let mut writer = &mut res.0[..];
134
135 affine.x.c1.into_repr().write_be(&mut writer).unwrap();
136 affine.x.c0.into_repr().write_be(&mut writer).unwrap();
137 affine.y.c1.into_repr().write_be(&mut writer).unwrap();
138 affine.y.c0.into_repr().write_be(&mut writer).unwrap();
139 }
140
141 res
142 }
143}
144
145#[derive(Copy, Clone)]
146pub struct G2Compressed([u8; 96]);
147
148impl AsRef<[u8]> for G2Compressed {
149 fn as_ref(&self) -> &[u8] {
150 &self.0
151 }
152}
153
154impl AsMut<[u8]> for G2Compressed {
155 fn as_mut(&mut self) -> &mut [u8] {
156 &mut self.0
157 }
158}
159
160impl fmt::Debug for G2Compressed {
161 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
162 self.0[..].fmt(formatter)
163 }
164}
165
166impl EncodedPoint for G2Compressed {
167 type Affine = G2Affine;
168
169 fn empty() -> Self {
170 G2Compressed([0; 96])
171 }
172 fn size() -> usize {
173 96
174 }
175 fn into_affine(&self) -> Result<G2Affine, GroupDecodingError> {
176 let affine = self.into_affine_unchecked()?;
177
178 if !affine.in_subgroup() {
181 Err(GroupDecodingError::NotInSubgroup)
182 } else {
183 Ok(affine)
184 }
185 }
186 fn into_affine_unchecked(&self) -> Result<G2Affine, GroupDecodingError> {
187 let mut copy = self.0;
189
190 if copy[0] & (1 << 7) == 0 {
191 return Err(GroupDecodingError::UnexpectedCompressionMode);
193 }
194
195 if copy[0] & (1 << 6) != 0 {
196 copy[0] &= 0x3f;
200
201 if copy.iter().all(|b| *b == 0) {
202 Ok(G2Affine::zero())
203 } else {
204 Err(GroupDecodingError::UnexpectedInformation)
205 }
206 } else {
207 let greatest = copy[0] & (1 << 5) != 0;
210
211 copy[0] &= 0x1f;
213
214 let mut x_c1 = FqRepr([0; 6]);
215 let mut x_c0 = FqRepr([0; 6]);
216
217 {
218 let mut reader = ©[..];
219
220 x_c1.read_be(&mut reader).unwrap();
221 x_c0.read_be(&mut reader).unwrap();
222 }
223
224 let x = Fq2 {
226 c0: Fq::from_repr(x_c0).map_err(|e| {
227 GroupDecodingError::CoordinateDecodingError("x coordinate (c0)", e)
228 })?,
229 c1: Fq::from_repr(x_c1).map_err(|e| {
230 GroupDecodingError::CoordinateDecodingError("x coordinate (c1)", e)
231 })?,
232 };
233
234 G2Affine::get_point_from_x(x, greatest).ok_or(GroupDecodingError::NotOnCurve)
235 }
236 }
237 fn from_affine(affine: G2Affine) -> Self {
238 let mut res = Self::empty();
239
240 if affine.is_zero() {
241 res.0[0] |= 1 << 6;
244 } else {
245 {
246 let mut writer = &mut res.0[..];
247
248 affine.x.c1.into_repr().write_be(&mut writer).unwrap();
249 affine.x.c0.into_repr().write_be(&mut writer).unwrap();
250 }
251
252 let mut negy = affine.y;
253 negy.negate();
254
255 if affine.y > negy {
258 res.0[0] |= 1 << 5;
259 }
260 }
261
262 res.0[0] |= 1 << 7;
264
265 res
266 }
267}
268
269impl G2Affine {
270 fn get_generator() -> Self {
271 G2Affine {
272 x: Fq2 {
273 c0: super::super::fq::G2_GENERATOR_X_C0,
274 c1: super::super::fq::G2_GENERATOR_X_C1,
275 },
276 y: Fq2 {
277 c0: super::super::fq::G2_GENERATOR_Y_C0,
278 c1: super::super::fq::G2_GENERATOR_Y_C1,
279 },
280 infinity: false,
281 }
282 }
283
284 fn get_coeff_b() -> Fq2 {
285 Fq2 {
286 c0: super::super::fq::B_COEFF,
287 c1: super::super::fq::B_COEFF,
288 }
289 }
290
291 fn scale_by_cofactor(&self) -> G2 {
292 let cofactor = BitIterator::new([
295 0xcf1c38e31c7238e5,
296 0x1616ec6e786f0c70,
297 0x21537e293a6691ae,
298 0xa628f1cb4d9e82ef,
299 0xa68a205b2e5a7ddf,
300 0xcd91de4547085aba,
301 0x91d50792876a202,
302 0x5d543a95414e7f1,
303 ]);
304 self.mul_bits(cofactor)
305 }
306
307 fn perform_pairing(&self, other: &G1Affine) -> Fq12 {
308 super::super::Bls12::pairing(*other, *self)
309 }
310}
311
312impl G2 {
313 fn empirical_recommended_wnaf_for_scalar(scalar: FrRepr) -> usize {
314 let num_bits = scalar.num_bits() as usize;
315
316 if num_bits >= 103 {
317 4
318 } else if num_bits >= 37 {
319 3
320 } else {
321 2
322 }
323 }
324
325 fn empirical_recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
326 const RECOMMENDATIONS: [usize; 11] = [1, 3, 8, 20, 47, 126, 260, 826, 1501, 4555, 84071];
327
328 let mut ret = 4;
329 for r in &RECOMMENDATIONS {
330 if num_scalars > *r {
331 ret += 1;
332 } else {
333 break;
334 }
335 }
336
337 ret
338 }
339}
340
341#[derive(Clone, Debug)]
342pub struct G2Prepared {
343 pub(crate) coeffs: Vec<(Fq2, Fq2, Fq2)>,
344 pub(crate) infinity: bool,
345}
346
347mod subgroup_check {
348 use super::G2Affine;
349 #[cfg(test)]
350 use rand_core::SeedableRng;
351 #[cfg(test)]
352 use CurveAffine;
353 use SubgroupCheck;
354
355 impl SubgroupCheck for G2Affine {
356 fn in_subgroup(&self) -> bool {
357 self.is_on_curve() && self.is_in_correct_subgroup_assuming_on_curve()
358 }
359 }
360
361 #[test]
362 fn test_g2_subgroup_check() {
363 use bls12_381::{ClearH, G2};
364 use CurveProjective;
365 let mut rng = rand_xorshift::XorShiftRng::from_seed([
366 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
367 0xbc, 0xe5,
368 ]);
369
370 for _ in 0..32 {
371 let p = G2::random(&mut rng).into_affine();
372 assert_eq!(
373 p.in_subgroup(),
374 p.is_in_correct_subgroup_assuming_on_curve()
375 );
376
377 let mut pp = p.into_projective();
378 pp.clear_h();
379 let p = pp.into_affine();
380 assert!(p.in_subgroup() && p.is_in_correct_subgroup_assuming_on_curve());
381 }
382 }
383}
384
385#[test]
386fn g2_generator() {
387 use SqrtField;
388
389 let mut x = Fq2::zero();
390 let mut i = 0;
391 loop {
392 let mut rhs = x;
394 rhs.square();
395 rhs.mul_assign(&x);
396 rhs.add_assign(&G2Affine::get_coeff_b());
397
398 if let Some(y) = rhs.sqrt() {
399 let mut negy = y;
400 negy.negate();
401
402 let p = G2Affine {
403 x,
404 y: if y < negy { y } else { negy },
405 infinity: false,
406 };
407
408 assert!(!p.in_subgroup());
409
410 let g2 = p.scale_by_cofactor();
411 if !g2.is_zero() {
412 assert_eq!(i, 2);
413 let g2 = G2Affine::from(g2);
414
415 assert!(g2.in_subgroup());
416 assert_eq!(g2, G2Affine::one());
417 break;
418 }
419 }
420
421 i += 1;
422 x.add_assign(&Fq2::one());
423 }
424}
425
426#[test]
427fn g2_test_is_valid() {
428 {
430 let p = G2Affine {
431 x: Fq2 {
432 c0: Fq::from_repr(FqRepr([
433 0xa757072d9fa35ba9,
434 0xae3fb2fb418f6e8a,
435 0xc1598ec46faa0c7c,
436 0x7a17a004747e3dbe,
437 0xcc65406a7c2e5a73,
438 0x10b8c03d64db4d0c,
439 ]))
440 .unwrap(),
441 c1: Fq::from_repr(FqRepr([
442 0xd30e70fe2f029778,
443 0xda30772df0f5212e,
444 0x5b47a9ff9a233a50,
445 0xfb777e5b9b568608,
446 0x789bac1fec71a2b9,
447 0x1342f02e2da54405,
448 ]))
449 .unwrap(),
450 },
451 y: Fq2 {
452 c0: Fq::from_repr(FqRepr([
453 0xfe0812043de54dca,
454 0xe455171a3d47a646,
455 0xa493f36bc20be98a,
456 0x663015d9410eb608,
457 0x78e82a79d829a544,
458 0x40a00545bb3c1e,
459 ]))
460 .unwrap(),
461 c1: Fq::from_repr(FqRepr([
462 0x4709802348e79377,
463 0xb5ac4dc9204bcfbd,
464 0xda361c97d02f42b2,
465 0x15008b1dc399e8df,
466 0x68128fd0548a3829,
467 0x16a613db5c873aaa,
468 ]))
469 .unwrap(),
470 },
471 infinity: false,
472 };
473 assert!(!p.is_on_curve());
474 }
475
476 {
478 let p = G2Affine {
479 x: Fq2 {
480 c0: Fq::from_repr(FqRepr([
481 0xf4fdfe95a705f917,
482 0xc2914df688233238,
483 0x37c6b12cca35a34b,
484 0x41abba710d6c692c,
485 0xffcc4b2b62ce8484,
486 0x6993ec01b8934ed,
487 ]))
488 .unwrap(),
489 c1: Fq::from_repr(FqRepr([
490 0xb94e92d5f874e26,
491 0x44516408bc115d95,
492 0xe93946b290caa591,
493 0xa5a0c2b7131f3555,
494 0x83800965822367e7,
495 0x10cf1d3ad8d90bfa,
496 ]))
497 .unwrap(),
498 },
499 y: Fq2 {
500 c0: Fq::from_repr(FqRepr([
501 0xbf00334c79701d97,
502 0x4fe714f9ff204f9a,
503 0xab70b28002f3d825,
504 0x5a9171720e73eb51,
505 0x38eb4fd8d658adb7,
506 0xb649051bbc1164d,
507 ]))
508 .unwrap(),
509 c1: Fq::from_repr(FqRepr([
510 0x9225814253d7df75,
511 0xc196c2513477f887,
512 0xe05e2fbd15a804e0,
513 0x55f2b8efad953e04,
514 0x7379345eda55265e,
515 0x377f2e6208fd4cb,
516 ]))
517 .unwrap(),
518 },
519 infinity: false,
520 };
521 assert!(!p.is_on_curve());
522 assert!(!p.in_subgroup());
523 }
524
525 {
528 let p = G2Affine {
529 x: Fq2 {
530 c0: Fq::from_repr(FqRepr([
531 0x262cea73ea1906c,
532 0x2f08540770fabd6,
533 0x4ceb92d0a76057be,
534 0x2199bc19c48c393d,
535 0x4a151b732a6075bf,
536 0x17762a3b9108c4a7,
537 ]))
538 .unwrap(),
539 c1: Fq::from_repr(FqRepr([
540 0x26f461e944bbd3d1,
541 0x298f3189a9cf6ed6,
542 0x74328ad8bc2aa150,
543 0x7e147f3f9e6e241,
544 0x72a9b63583963fff,
545 0x158b0083c000462,
546 ]))
547 .unwrap(),
548 },
549 y: Fq2 {
550 c0: Fq::from_repr(FqRepr([
551 0x91fb0b225ecf103b,
552 0x55d42edc1dc46ba0,
553 0x43939b11997b1943,
554 0x68cad19430706b4d,
555 0x3ccfb97b924dcea8,
556 0x1660f93434588f8d,
557 ]))
558 .unwrap(),
559 c1: Fq::from_repr(FqRepr([
560 0xaaed3985b6dcb9c7,
561 0xc1e985d6d898d9f4,
562 0x618bd2ac3271ac42,
563 0x3940a2dbb914b529,
564 0xbeb88137cf34f3e7,
565 0x1699ee577c61b694,
566 ]))
567 .unwrap(),
568 },
569 infinity: false,
570 };
571 assert!(p.is_on_curve());
572 assert!(!p.in_subgroup());
573 }
574}
575
576#[test]
577fn test_g2_addition_correctness() {
578 let mut p = G2 {
579 x: Fq2 {
580 c0: Fq::from_repr(FqRepr([
581 0x6c994cc1e303094e,
582 0xf034642d2c9e85bd,
583 0x275094f1352123a9,
584 0x72556c999f3707ac,
585 0x4617f2e6774e9711,
586 0x100b2fe5bffe030b,
587 ]))
588 .unwrap(),
589 c1: Fq::from_repr(FqRepr([
590 0x7a33555977ec608,
591 0xe23039d1fe9c0881,
592 0x19ce4678aed4fcb5,
593 0x4637c4f417667e2e,
594 0x93ebe7c3e41f6acc,
595 0xde884f89a9a371b,
596 ]))
597 .unwrap(),
598 },
599 y: Fq2 {
600 c0: Fq::from_repr(FqRepr([
601 0xe073119472e1eb62,
602 0x44fb3391fe3c9c30,
603 0xaa9b066d74694006,
604 0x25fd427b4122f231,
605 0xd83112aace35cae,
606 0x191b2432407cbb7f,
607 ]))
608 .unwrap(),
609 c1: Fq::from_repr(FqRepr([
610 0xf68ae82fe97662f5,
611 0xe986057068b50b7d,
612 0x96c30f0411590b48,
613 0x9eaa6d19de569196,
614 0xf6a03d31e2ec2183,
615 0x3bdafaf7ca9b39b,
616 ]))
617 .unwrap(),
618 },
619 z: Fq2::one(),
620 };
621
622 p.add_assign(&G2 {
623 x: Fq2 {
624 c0: Fq::from_repr(FqRepr([
625 0xa8c763d25910bdd3,
626 0x408777b30ca3add4,
627 0x6115fcc12e2769e,
628 0x8e73a96b329ad190,
629 0x27c546f75ee1f3ab,
630 0xa33d27add5e7e82,
631 ]))
632 .unwrap(),
633 c1: Fq::from_repr(FqRepr([
634 0x93b1ebcd54870dfe,
635 0xf1578300e1342e11,
636 0x8270dca3a912407b,
637 0x2089faf462438296,
638 0x828e5848cd48ea66,
639 0x141ecbac1deb038b,
640 ]))
641 .unwrap(),
642 },
643 y: Fq2 {
644 c0: Fq::from_repr(FqRepr([
645 0xf5d2c28857229c3f,
646 0x8c1574228757ca23,
647 0xe8d8102175f5dc19,
648 0x2767032fc37cc31d,
649 0xd5ee2aba84fd10fe,
650 0x16576ccd3dd0a4e8,
651 ]))
652 .unwrap(),
653 c1: Fq::from_repr(FqRepr([
654 0x4da9b6f6a96d1dd2,
655 0x9657f7da77f1650e,
656 0xbc150712f9ffe6da,
657 0x31898db63f87363a,
658 0xabab040ddbd097cc,
659 0x11ad236b9ba02990,
660 ]))
661 .unwrap(),
662 },
663 z: Fq2::one(),
664 });
665
666 let p = G2Affine::from(p);
667
668 assert_eq!(
669 p,
670 G2Affine {
671 x: Fq2 {
672 c0: Fq::from_repr(FqRepr([
673 0xcde7ee8a3f2ac8af,
674 0xfc642eb35975b069,
675 0xa7de72b7dd0e64b7,
676 0xf1273e6406eef9cc,
677 0xababd760ff05cb92,
678 0xd7c20456617e89
679 ]))
680 .unwrap(),
681 c1: Fq::from_repr(FqRepr([
682 0xd1a50b8572cbd2b8,
683 0x238f0ac6119d07df,
684 0x4dbe924fe5fd6ac2,
685 0x8b203284c51edf6b,
686 0xc8a0b730bbb21f5e,
687 0x1a3b59d29a31274
688 ]))
689 .unwrap(),
690 },
691 y: Fq2 {
692 c0: Fq::from_repr(FqRepr([
693 0x9e709e78a8eaa4c9,
694 0xd30921c93ec342f4,
695 0x6d1ef332486f5e34,
696 0x64528ab3863633dc,
697 0x159384333d7cba97,
698 0x4cb84741f3cafe8
699 ]))
700 .unwrap(),
701 c1: Fq::from_repr(FqRepr([
702 0x242af0dc3640e1a4,
703 0xe90a73ad65c66919,
704 0x2bd7ca7f4346f9ec,
705 0x38528f92b689644d,
706 0xb6884deec59fb21f,
707 0x3c075d3ec52ba90
708 ]))
709 .unwrap(),
710 },
711 infinity: false,
712 }
713 );
714}
715
716#[test]
717fn test_g2_doubling_correctness() {
718 let mut p = G2 {
719 x: Fq2 {
720 c0: Fq::from_repr(FqRepr([
721 0x6c994cc1e303094e,
722 0xf034642d2c9e85bd,
723 0x275094f1352123a9,
724 0x72556c999f3707ac,
725 0x4617f2e6774e9711,
726 0x100b2fe5bffe030b,
727 ]))
728 .unwrap(),
729 c1: Fq::from_repr(FqRepr([
730 0x7a33555977ec608,
731 0xe23039d1fe9c0881,
732 0x19ce4678aed4fcb5,
733 0x4637c4f417667e2e,
734 0x93ebe7c3e41f6acc,
735 0xde884f89a9a371b,
736 ]))
737 .unwrap(),
738 },
739 y: Fq2 {
740 c0: Fq::from_repr(FqRepr([
741 0xe073119472e1eb62,
742 0x44fb3391fe3c9c30,
743 0xaa9b066d74694006,
744 0x25fd427b4122f231,
745 0xd83112aace35cae,
746 0x191b2432407cbb7f,
747 ]))
748 .unwrap(),
749 c1: Fq::from_repr(FqRepr([
750 0xf68ae82fe97662f5,
751 0xe986057068b50b7d,
752 0x96c30f0411590b48,
753 0x9eaa6d19de569196,
754 0xf6a03d31e2ec2183,
755 0x3bdafaf7ca9b39b,
756 ]))
757 .unwrap(),
758 },
759 z: Fq2::one(),
760 };
761
762 p.double();
763
764 let p = G2Affine::from(p);
765
766 assert_eq!(
767 p,
768 G2Affine {
769 x: Fq2 {
770 c0: Fq::from_repr(FqRepr([
771 0x91ccb1292727c404,
772 0x91a6cb182438fad7,
773 0x116aee59434de902,
774 0xbcedcfce1e52d986,
775 0x9755d4a3926e9862,
776 0x18bab73760fd8024
777 ]))
778 .unwrap(),
779 c1: Fq::from_repr(FqRepr([
780 0x4e7c5e0a2ae5b99e,
781 0x96e582a27f028961,
782 0xc74d1cf4ef2d5926,
783 0xeb0cf5e610ef4fe7,
784 0x7b4c2bae8db6e70b,
785 0xf136e43909fca0
786 ]))
787 .unwrap(),
788 },
789 y: Fq2 {
790 c0: Fq::from_repr(FqRepr([
791 0x954d4466ab13e58,
792 0x3ee42eec614cf890,
793 0x853bb1d28877577e,
794 0xa5a2a51f7fde787b,
795 0x8b92866bc6384188,
796 0x81a53fe531d64ef
797 ]))
798 .unwrap(),
799 c1: Fq::from_repr(FqRepr([
800 0x4c5d607666239b34,
801 0xeddb5f48304d14b3,
802 0x337167ee6e8e3cb6,
803 0xb271f52f12ead742,
804 0x244e6c2015c83348,
805 0x19e2deae6eb9b441
806 ]))
807 .unwrap(),
808 },
809 infinity: false,
810 }
811 );
812}
813
814#[test]
815fn g2_curve_tests() {
816 ::tests::curve::curve_tests::<G2>();
817}