1use super::super::{Bls12, Fq, Fq12, FqRepr, Fr, FrRepr};
2use super::g2::G2Affine;
3use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
4use std::fmt;
5use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError, SubgroupCheck};
6curve_impl!(
7 "G1",
8 G1,
9 G1Affine,
10 G1Prepared,
11 Fq,
12 Fr,
13 G1Uncompressed,
14 G1Compressed,
15 G2Affine
16);
17
18#[derive(Copy, Clone)]
19pub struct G1Uncompressed([u8; 96]);
20
21impl AsRef<[u8]> for G1Uncompressed {
22 fn as_ref(&self) -> &[u8] {
23 &self.0
24 }
25}
26
27impl AsMut<[u8]> for G1Uncompressed {
28 fn as_mut(&mut self) -> &mut [u8] {
29 &mut self.0
30 }
31}
32
33impl fmt::Debug for G1Uncompressed {
34 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
35 self.0[..].fmt(formatter)
36 }
37}
38
39impl EncodedPoint for G1Uncompressed {
40 type Affine = G1Affine;
41
42 fn empty() -> Self {
43 G1Uncompressed([0; 96])
44 }
45 fn size() -> usize {
46 96
47 }
48 fn into_affine(&self) -> Result<G1Affine, GroupDecodingError> {
49 let affine = self.into_affine_unchecked()?;
50
51 if !affine.is_on_curve() {
52 Err(GroupDecodingError::NotOnCurve)
53 } else if !affine.in_subgroup() {
54 Err(GroupDecodingError::NotInSubgroup)
55 } else {
56 Ok(affine)
57 }
58 }
59 fn into_affine_unchecked(&self) -> Result<G1Affine, GroupDecodingError> {
60 let mut copy = self.0;
62
63 if copy[0] & (1 << 7) != 0 {
64 return Err(GroupDecodingError::UnexpectedCompressionMode);
66 }
67
68 if copy[0] & (1 << 6) != 0 {
69 copy[0] &= 0x3f;
73
74 if copy.iter().all(|b| *b == 0) {
75 Ok(G1Affine::zero())
76 } else {
77 Err(GroupDecodingError::UnexpectedInformation)
78 }
79 } else {
80 if copy[0] & (1 << 5) != 0 {
81 return Err(GroupDecodingError::UnexpectedInformation);
84 }
85
86 copy[0] &= 0x1f;
88
89 let mut x = FqRepr([0; 6]);
90 let mut y = FqRepr([0; 6]);
91
92 {
93 let mut reader = ©[..];
94
95 x.read_be(&mut reader).unwrap();
96 y.read_be(&mut reader).unwrap();
97 }
98
99 Ok(G1Affine {
100 x: Fq::from_repr(x)
101 .map_err(|e| GroupDecodingError::CoordinateDecodingError("x coordinate", e))?,
102 y: Fq::from_repr(y)
103 .map_err(|e| GroupDecodingError::CoordinateDecodingError("y coordinate", e))?,
104 infinity: false,
105 })
106 }
107 }
108 fn from_affine(affine: G1Affine) -> Self {
109 let mut res = Self::empty();
110
111 if affine.is_zero() {
112 res.0[0] |= 1 << 6;
115 } else {
116 let mut writer = &mut res.0[..];
117
118 affine.x.into_repr().write_be(&mut writer).unwrap();
119 affine.y.into_repr().write_be(&mut writer).unwrap();
120 }
121
122 res
123 }
124}
125
126#[derive(Copy, Clone)]
127pub struct G1Compressed([u8; 48]);
128
129impl AsRef<[u8]> for G1Compressed {
130 fn as_ref(&self) -> &[u8] {
131 &self.0
132 }
133}
134
135impl AsMut<[u8]> for G1Compressed {
136 fn as_mut(&mut self) -> &mut [u8] {
137 &mut self.0
138 }
139}
140
141impl fmt::Debug for G1Compressed {
142 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
143 self.0[..].fmt(formatter)
144 }
145}
146
147impl EncodedPoint for G1Compressed {
148 type Affine = G1Affine;
149
150 fn empty() -> Self {
151 G1Compressed([0; 48])
152 }
153 fn size() -> usize {
154 48
155 }
156 fn into_affine(&self) -> Result<G1Affine, GroupDecodingError> {
157 let affine = self.into_affine_unchecked()?;
158
159 if !affine.in_subgroup() {
162 Err(GroupDecodingError::NotInSubgroup)
163 } else {
164 Ok(affine)
165 }
166 }
167 fn into_affine_unchecked(&self) -> Result<G1Affine, GroupDecodingError> {
168 let mut copy = self.0;
170
171 if copy[0] & (1 << 7) == 0 {
172 return Err(GroupDecodingError::UnexpectedCompressionMode);
174 }
175
176 if copy[0] & (1 << 6) != 0 {
177 copy[0] &= 0x3f;
181
182 if copy.iter().all(|b| *b == 0) {
183 Ok(G1Affine::zero())
184 } else {
185 Err(GroupDecodingError::UnexpectedInformation)
186 }
187 } else {
188 let greatest = copy[0] & (1 << 5) != 0;
191
192 copy[0] &= 0x1f;
194
195 let mut x = FqRepr([0; 6]);
196
197 {
198 let mut reader = ©[..];
199
200 x.read_be(&mut reader).unwrap();
201 }
202
203 let x = Fq::from_repr(x)
205 .map_err(|e| GroupDecodingError::CoordinateDecodingError("x coordinate", e))?;
206
207 G1Affine::get_point_from_x(x, greatest).ok_or(GroupDecodingError::NotOnCurve)
208 }
209 }
210 fn from_affine(affine: G1Affine) -> Self {
211 let mut res = Self::empty();
212
213 if affine.is_zero() {
214 res.0[0] |= 1 << 6;
217 } else {
218 {
219 let mut writer = &mut res.0[..];
220
221 affine.x.into_repr().write_be(&mut writer).unwrap();
222 }
223
224 let mut negy = affine.y;
225 negy.negate();
226
227 if affine.y > negy {
230 res.0[0] |= 1 << 5;
231 }
232 }
233
234 res.0[0] |= 1 << 7;
236
237 res
238 }
239}
240
241impl G1Affine {
242 fn scale_by_cofactor(&self) -> G1 {
243 let cofactor = BitIterator::new([0x8c00aaab0000aaab, 0x396c8c005555e156]);
245 self.mul_bits(cofactor)
246 }
247
248 fn get_generator() -> Self {
249 G1Affine {
250 x: super::super::fq::G1_GENERATOR_X,
251 y: super::super::fq::G1_GENERATOR_Y,
252 infinity: false,
253 }
254 }
255
256 fn get_coeff_b() -> Fq {
257 super::super::fq::B_COEFF
258 }
259
260 fn perform_pairing(&self, other: &G2Affine) -> Fq12 {
261 super::super::Bls12::pairing(*self, *other)
262 }
263}
264
265impl G1 {
266 fn empirical_recommended_wnaf_for_scalar(scalar: FrRepr) -> usize {
267 let num_bits = scalar.num_bits() as usize;
268
269 if num_bits >= 130 {
270 4
271 } else if num_bits >= 34 {
272 3
273 } else {
274 2
275 }
276 }
277
278 fn empirical_recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
279 const RECOMMENDATIONS: [usize; 12] =
280 [1, 3, 7, 20, 43, 120, 273, 563, 1630, 3128, 7933, 62569];
281
282 let mut ret = 4;
283 for r in &RECOMMENDATIONS {
284 if num_scalars > *r {
285 ret += 1;
286 } else {
287 break;
288 }
289 }
290
291 ret
292 }
293}
294
295#[derive(Clone, Debug)]
296pub struct G1Prepared(pub(crate) G1Affine);
297
298impl G1Prepared {
299 pub fn is_zero(&self) -> bool {
300 self.0.is_zero()
301 }
302
303 pub fn from_affine(p: G1Affine) -> Self {
304 G1Prepared(p)
305 }
306}
307
308mod subgroup_check {
309
310 use super::G1Affine;
311 #[cfg(test)]
312 use super::G1;
313 #[cfg(test)]
314 use rand_core::SeedableRng;
315 use SubgroupCheck;
316 #[cfg(test)]
317 use {CurveAffine, CurveProjective};
318
319 impl SubgroupCheck for G1Affine {
320 fn in_subgroup(&self) -> bool {
321 self.is_on_curve() && self.is_in_correct_subgroup_assuming_on_curve()
322 }
323 }
324
325 #[test]
326 fn test_g1_subgroup_check() {
327 use bls12_381::ClearH;
328 let mut rng = rand_xorshift::XorShiftRng::from_seed([
329 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
330 0xbc, 0xe5,
331 ]);
332
333 for _ in 0..32 {
334 let p = G1::random(&mut rng).into_affine();
335 assert_eq!(
336 p.in_subgroup(),
337 p.is_in_correct_subgroup_assuming_on_curve()
338 );
339
340 let mut pp = p.into_projective();
341 pp.clear_h();
342 let p = pp.into_affine();
343 assert!(p.in_subgroup() && p.is_in_correct_subgroup_assuming_on_curve());
344 }
345 }
346}
347
348#[test]
349fn g1_generator() {
350 use SqrtField;
351
352 let mut x = Fq::zero();
353 let mut i = 0;
354 loop {
355 let mut rhs = x;
357 rhs.square();
358 rhs.mul_assign(&x);
359 rhs.add_assign(&G1Affine::get_coeff_b());
360
361 if let Some(y) = rhs.sqrt() {
362 let yrepr = y.into_repr();
363 let mut negy = y;
364 negy.negate();
365 let negyrepr = negy.into_repr();
366
367 let p = G1Affine {
368 x,
369 y: if yrepr < negyrepr { y } else { negy },
370 infinity: false,
371 };
372 assert!(!p.in_subgroup());
373
374 let g1 = p.scale_by_cofactor();
375 if !g1.is_zero() {
376 assert_eq!(i, 4);
377 let g1 = G1Affine::from(g1);
378
379 assert!(g1.in_subgroup());
380
381 assert_eq!(g1, G1Affine::one());
382 break;
383 }
384 }
385
386 i += 1;
387 x.add_assign(&Fq::one());
388 }
389}
390
391#[test]
392fn g1_test_is_valid() {
393 {
395 let p = G1Affine {
396 x: Fq::from_repr(FqRepr([
397 0xc58d887b66c035dc,
398 0x10cbfd301d553822,
399 0xaf23e064f1131ee5,
400 0x9fe83b1b4a5d648d,
401 0xf583cc5a508f6a40,
402 0xc3ad2aefde0bb13,
403 ]))
404 .unwrap(),
405 y: Fq::from_repr(FqRepr([
406 0x60aa6f9552f03aae,
407 0xecd01d5181300d35,
408 0x8af1cdb8aa8ce167,
409 0xe760f57922998c9d,
410 0x953703f5795a39e5,
411 0xfe3ae0922df702c,
412 ]))
413 .unwrap(),
414 infinity: false,
415 };
416 assert!(!p.is_on_curve());
417 }
418
419 {
421 let p = G1Affine {
422 x: Fq::from_repr(FqRepr([
423 0xee6adf83511e15f5,
424 0x92ddd328f27a4ba6,
425 0xe305bd1ac65adba7,
426 0xea034ee2928b30a8,
427 0xbd8833dc7c79a7f7,
428 0xe45c9f0c0438675,
429 ]))
430 .unwrap(),
431 y: Fq::from_repr(FqRepr([
432 0x3b450eb1ab7b5dad,
433 0xa65cb81e975e8675,
434 0xaa548682b21726e5,
435 0x753ddf21a2601d20,
436 0x532d0b640bd3ff8b,
437 0x118d2c543f031102,
438 ]))
439 .unwrap(),
440 infinity: false,
441 };
442 assert!(!p.is_on_curve());
443 assert!(!p.in_subgroup());
444 }
445
446 {
449 let p = G1Affine {
450 x: Fq::from_repr(FqRepr([
451 0x76e1c971c6db8fe8,
452 0xe37e1a610eff2f79,
453 0x88ae9c499f46f0c0,
454 0xf35de9ce0d6b4e84,
455 0x265bddd23d1dec54,
456 0x12a8778088458308,
457 ]))
458 .unwrap(),
459 y: Fq::from_repr(FqRepr([
460 0x8a22defa0d526256,
461 0xc57ca55456fcb9ae,
462 0x1ba194e89bab2610,
463 0x921beef89d4f29df,
464 0x5b6fda44ad85fa78,
465 0xed74ab9f302cbe0,
466 ]))
467 .unwrap(),
468 infinity: false,
469 };
470 assert!(p.is_on_curve());
471 assert!(!p.in_subgroup());
472 }
473}
474
475#[test]
476fn test_g1_addition_correctness() {
477 let mut p = G1 {
478 x: Fq::from_repr(FqRepr([
479 0x47fd1f891d6e8bbf,
480 0x79a3b0448f31a2aa,
481 0x81f3339e5f9968f,
482 0x485e77d50a5df10d,
483 0x4c6fcac4b55fd479,
484 0x86ed4d9906fb064,
485 ]))
486 .unwrap(),
487 y: Fq::from_repr(FqRepr([
488 0xd25ee6461538c65,
489 0x9f3bbb2ecd3719b9,
490 0xa06fd3f1e540910d,
491 0xcefca68333c35288,
492 0x570c8005f8573fa6,
493 0x152ca696fe034442,
494 ]))
495 .unwrap(),
496 z: Fq::one(),
497 };
498
499 p.add_assign(&G1 {
500 x: Fq::from_repr(FqRepr([
501 0xeec78f3096213cbf,
502 0xa12beb1fea1056e6,
503 0xc286c0211c40dd54,
504 0x5f44314ec5e3fb03,
505 0x24e8538737c6e675,
506 0x8abd623a594fba8,
507 ]))
508 .unwrap(),
509 y: Fq::from_repr(FqRepr([
510 0x6b0528f088bb7044,
511 0x2fdeb5c82917ff9e,
512 0x9a5181f2fac226ad,
513 0xd65104c6f95a872a,
514 0x1f2998a5a9c61253,
515 0xe74846154a9e44,
516 ]))
517 .unwrap(),
518 z: Fq::one(),
519 });
520
521 let p = G1Affine::from(p);
522
523 assert_eq!(
524 p,
525 G1Affine {
526 x: Fq::from_repr(FqRepr([
527 0x6dd3098f22235df,
528 0xe865d221c8090260,
529 0xeb96bb99fa50779f,
530 0xc4f9a52a428e23bb,
531 0xd178b28dd4f407ef,
532 0x17fb8905e9183c69
533 ]))
534 .unwrap(),
535 y: Fq::from_repr(FqRepr([
536 0xd0de9d65292b7710,
537 0xf6a05f2bcf1d9ca7,
538 0x1040e27012f20b64,
539 0xeec8d1a5b7466c58,
540 0x4bc362649dce6376,
541 0x430cbdc5455b00a
542 ]))
543 .unwrap(),
544 infinity: false,
545 }
546 );
547}
548
549#[test]
550fn test_g1_doubling_correctness() {
551 let mut p = G1 {
552 x: Fq::from_repr(FqRepr([
553 0x47fd1f891d6e8bbf,
554 0x79a3b0448f31a2aa,
555 0x81f3339e5f9968f,
556 0x485e77d50a5df10d,
557 0x4c6fcac4b55fd479,
558 0x86ed4d9906fb064,
559 ]))
560 .unwrap(),
561 y: Fq::from_repr(FqRepr([
562 0xd25ee6461538c65,
563 0x9f3bbb2ecd3719b9,
564 0xa06fd3f1e540910d,
565 0xcefca68333c35288,
566 0x570c8005f8573fa6,
567 0x152ca696fe034442,
568 ]))
569 .unwrap(),
570 z: Fq::one(),
571 };
572
573 p.double();
574
575 let p = G1Affine::from(p);
576
577 assert_eq!(
578 p,
579 G1Affine {
580 x: Fq::from_repr(FqRepr([
581 0xf939ddfe0ead7018,
582 0x3b03942e732aecb,
583 0xce0e9c38fdb11851,
584 0x4b914c16687dcde0,
585 0x66c8baf177d20533,
586 0xaf960cff3d83833
587 ]))
588 .unwrap(),
589 y: Fq::from_repr(FqRepr([
590 0x3f0675695f5177a8,
591 0x2b6d82ae178a1ba0,
592 0x9096380dd8e51b11,
593 0x1771a65b60572f4e,
594 0x8b547c1313b27555,
595 0x135075589a687b1e
596 ]))
597 .unwrap(),
598 infinity: false,
599 }
600 );
601}
602
603#[test]
604fn test_g1_same_y() {
605 let a = G1Affine {
613 x: Fq::from_repr(FqRepr([
614 0xea431f2cc38fc94d,
615 0x3ad2354a07f5472b,
616 0xfe669f133f16c26a,
617 0x71ffa8021531705,
618 0x7418d484386d267,
619 0xd5108d8ff1fbd6,
620 ]))
621 .unwrap(),
622 y: Fq::from_repr(FqRepr([
623 0xa776ccbfe9981766,
624 0x255632964ff40f4a,
625 0xc09744e650b00499,
626 0x520f74773e74c8c3,
627 0x484c8fc982008f0,
628 0xee2c3d922008cc6,
629 ]))
630 .unwrap(),
631 infinity: false,
632 };
633
634 let b = G1Affine {
635 x: Fq::from_repr(FqRepr([
636 0xe06cdb156b6356b6,
637 0xd9040b2d75448ad9,
638 0xe702f14bb0e2aca5,
639 0xc6e05201e5f83991,
640 0xf7c75910816f207c,
641 0x18d4043e78103106,
642 ]))
643 .unwrap(),
644 y: Fq::from_repr(FqRepr([
645 0xa776ccbfe9981766,
646 0x255632964ff40f4a,
647 0xc09744e650b00499,
648 0x520f74773e74c8c3,
649 0x484c8fc982008f0,
650 0xee2c3d922008cc6,
651 ]))
652 .unwrap(),
653 infinity: false,
654 };
655
656 let c = G1Affine {
660 x: Fq::from_repr(FqRepr([
661 0xef4f05bdd10c8aa8,
662 0xad5bf87341a2df9,
663 0x81c7424206b78714,
664 0x9676ff02ec39c227,
665 0x4c12c15d7e55b9f3,
666 0x57fd1e317db9bd,
667 ]))
668 .unwrap(),
669 y: Fq::from_repr(FqRepr([
670 0x1288334016679345,
671 0xf955cd68615ff0b5,
672 0xa6998dbaa600f18a,
673 0x1267d70db51049fb,
674 0x4696deb9ab2ba3e7,
675 0xb1e4e11177f59d4,
676 ]))
677 .unwrap(),
678 infinity: false,
679 };
680
681 assert!(a.is_on_curve() && a.in_subgroup());
682 assert!(b.is_on_curve() && b.in_subgroup());
683 assert!(c.is_on_curve() && c.in_subgroup());
684
685 let mut tmp1 = a.into_projective();
686 tmp1.add_assign(&b.into_projective());
687 assert_eq!(tmp1.into_affine(), c);
688 assert_eq!(tmp1, c.into_projective());
689
690 let mut tmp2 = a.into_projective();
691 tmp2.add_assign_mixed(&b);
692 assert_eq!(tmp2.into_affine(), c);
693 assert_eq!(tmp2, c.into_projective());
694}
695
696#[test]
697fn g1_curve_tests() {
698 ::tests::curve::curve_tests::<G1>();
699}