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 rand_core::RngCore;
9use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
10
11use super::field::fp::Fp;
12use super::Scalar;
13
14#[derive(Copy, Clone, Debug)]
16pub struct G1Affine {
17 pub(crate) x: Fp,
18 pub(crate) y: Fp,
19 infinity: Choice,
20}
21
22impl Default for G1Affine {
23 fn default() -> G1Affine {
24 G1Affine::identity()
25 }
26}
27
28#[cfg(feature = "zeroize")]
29impl zeroize::DefaultIsZeroes for G1Affine {}
30
31impl fmt::Display for G1Affine {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 write!(f, "{:?}", self)
34 }
35}
36
37impl<'a> From<&'a G1Projective> for G1Affine {
38 fn from(p: &'a G1Projective) -> G1Affine {
39 let zinv = p.z.invert().unwrap_or(Fp::zero());
40 let x = p.x * zinv;
41 let y = p.y * zinv;
42
43 let tmp = G1Affine {
44 x,
45 y,
46 infinity: Choice::from(0u8),
47 };
48
49 G1Affine::conditional_select(&tmp, &G1Affine::identity(), zinv.is_zero())
50 }
51}
52
53impl From<G1Projective> for G1Affine {
54 fn from(p: G1Projective) -> G1Affine {
55 G1Affine::from(&p)
56 }
57}
58
59impl ConstantTimeEq for G1Affine {
60 fn ct_eq(&self, other: &Self) -> Choice {
61 (self.infinity & other.infinity)
62 | ((!self.infinity)
63 & (!other.infinity)
64 & self.x.ct_eq(&other.x)
65 & self.y.ct_eq(&other.y))
66 }
67}
68
69impl ConditionallySelectable for G1Affine {
70 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
71 G1Affine {
72 x: Fp::conditional_select(&a.x, &b.x, choice),
73 y: Fp::conditional_select(&a.y, &b.y, choice),
74 infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice),
75 }
76 }
77}
78
79impl Eq for G1Affine {}
80impl PartialEq for G1Affine {
81 #[inline]
82 fn eq(&self, other: &Self) -> bool {
83 bool::from(self.ct_eq(other))
84 }
85}
86
87impl<'a> Neg for &'a G1Affine {
88 type Output = G1Affine;
89
90 #[inline]
91 fn neg(self) -> G1Affine {
92 G1Affine {
93 x: self.x,
94 y: Fp::conditional_select(&-self.y, &Fp::one(), self.infinity),
95 infinity: self.infinity,
96 }
97 }
98}
99
100impl Neg for G1Affine {
101 type Output = G1Affine;
102
103 #[inline]
104 fn neg(self) -> G1Affine {
105 -&self
106 }
107}
108
109impl<'a, 'b> Add<&'b G1Projective> for &'a G1Affine {
110 type Output = G1Projective;
111
112 #[inline]
113 fn add(self, rhs: &'b G1Projective) -> G1Projective {
114 rhs.add_mixed(self)
115 }
116}
117
118impl<'a, 'b> Add<&'b G1Affine> for &'a G1Projective {
119 type Output = G1Projective;
120
121 #[inline]
122 fn add(self, rhs: &'b G1Affine) -> G1Projective {
123 self.add_mixed(rhs)
124 }
125}
126
127impl<'a, 'b> Sub<&'b G1Projective> for &'a G1Affine {
128 type Output = G1Projective;
129
130 #[inline]
131 fn sub(self, rhs: &'b G1Projective) -> G1Projective {
132 self + &(-rhs)
133 }
134}
135
136impl<'a, 'b> Sub<&'b G1Affine> for &'a G1Projective {
137 type Output = G1Projective;
138
139 #[inline]
140 fn sub(self, rhs: &'b G1Affine) -> G1Projective {
141 self + &(-rhs)
142 }
143}
144
145impl<T> Sum<T> for G1Projective
146where
147 T: Borrow<G1Projective>,
148{
149 fn sum<I>(iter: I) -> Self
150 where
151 I: Iterator<Item = T>,
152 {
153 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
154 }
155}
156
157impl<'b> Add<&'b G1Affine> for G1Projective {
159 type Output = G1Projective;
160 #[inline]
161 fn add(self, rhs: &'b G1Affine) -> G1Projective {
162 &self + rhs
163 }
164}
165impl<'a> Add<G1Affine> for &'a G1Projective {
166 type Output = G1Projective;
167 #[inline]
168 fn add(self, rhs: G1Affine) -> G1Projective {
169 self + &rhs
170 }
171}
172impl Add<G1Affine> for G1Projective {
173 type Output = G1Projective;
174 #[inline]
175 fn add(self, rhs: G1Affine) -> G1Projective {
176 &self + &rhs
177 }
178}
179impl<'b> Sub<&'b G1Affine> for G1Projective {
180 type Output = G1Projective;
181 #[inline]
182 fn sub(self, rhs: &'b G1Affine) -> G1Projective {
183 &self - rhs
184 }
185}
186impl<'a> Sub<G1Affine> for &'a G1Projective {
187 type Output = G1Projective;
188 #[inline]
189 fn sub(self, rhs: G1Affine) -> G1Projective {
190 self - &rhs
191 }
192}
193impl Sub<G1Affine> for G1Projective {
194 type Output = G1Projective;
195 #[inline]
196 fn sub(self, rhs: G1Affine) -> G1Projective {
197 &self - &rhs
198 }
199}
200impl SubAssign<G1Affine> for G1Projective {
201 #[inline]
202 fn sub_assign(&mut self, rhs: G1Affine) {
203 *self = &*self - &rhs;
204 }
205}
206impl AddAssign<G1Affine> for G1Projective {
207 #[inline]
208 fn add_assign(&mut self, rhs: G1Affine) {
209 *self = &*self + &rhs;
210 }
211}
212impl<'b> SubAssign<&'b G1Affine> for G1Projective {
213 #[inline]
214 fn sub_assign(&mut self, rhs: &'b G1Affine) {
215 *self = &*self - rhs;
216 }
217}
218impl<'b> AddAssign<&'b G1Affine> for G1Projective {
219 #[inline]
220 fn add_assign(&mut self, rhs: &'b G1Affine) {
221 *self = &*self + rhs;
222 }
223}
224
225impl<'b> Add<&'b G1Projective> for G1Affine {
227 type Output = G1Projective;
228 #[inline]
229 fn add(self, rhs: &'b G1Projective) -> G1Projective {
230 &self + rhs
231 }
232}
233impl<'a> Add<G1Projective> for &'a G1Affine {
234 type Output = G1Projective;
235 #[inline]
236 fn add(self, rhs: G1Projective) -> G1Projective {
237 self + &rhs
238 }
239}
240impl Add<G1Projective> for G1Affine {
241 type Output = G1Projective;
242 #[inline]
243 fn add(self, rhs: G1Projective) -> G1Projective {
244 &self + &rhs
245 }
246}
247impl<'b> Sub<&'b G1Projective> for G1Affine {
248 type Output = G1Projective;
249 #[inline]
250 fn sub(self, rhs: &'b G1Projective) -> G1Projective {
251 &self - rhs
252 }
253}
254impl<'a> Sub<G1Projective> for &'a G1Affine {
255 type Output = G1Projective;
256 #[inline]
257 fn sub(self, rhs: G1Projective) -> G1Projective {
258 self - &rhs
259 }
260}
261impl Sub<G1Projective> for G1Affine {
262 type Output = G1Projective;
263 #[inline]
264 fn sub(self, rhs: G1Projective) -> G1Projective {
265 &self - &rhs
266 }
267}
268
269const B: Fp = Fp::from_raw_unchecked([
271 0xaa27_0000_000c_fff3,
272 0x53cc_0032_fc34_000a,
273 0x478f_e97a_6b0a_807f,
274 0xb1d3_7ebe_e6ba_24d7,
275 0x8ec9_733b_bf78_ab2f,
276 0x09d6_4551_3d83_de7e,
277]);
278
279pub const BETA: Fp = Fp::from_raw_unchecked([
281 0x30f1_361b_798a_64e8,
282 0xf3b8_ddab_7ece_5a2a,
283 0x16a8_ca3a_c615_77f7,
284 0xc26a_2ff8_74fd_029b,
285 0x3636_b766_6070_1c6e,
286 0x051b_a4ab_241b_6160,
287]);
288
289fn endomorphism(p: &G1Affine) -> G1Affine {
290 let mut res = *p;
291 res.x *= BETA;
292 res
293}
294
295impl G1Affine {
296 pub fn identity() -> G1Affine {
298 G1Affine {
299 x: Fp::zero(),
300 y: Fp::one(),
301 infinity: Choice::from(1u8),
302 }
303 }
304
305 pub fn generator() -> G1Affine {
307 G1Affine {
308 x: Fp::from_raw_unchecked([
309 0x5cb3_8790_fd53_0c16,
310 0x7817_fc67_9976_fff5,
311 0x154f_95c7_143b_a1c1,
312 0xf0ae_6acd_f3d0_e747,
313 0xedce_6ecc_21db_f440,
314 0x1201_7741_9e0b_fb75,
315 ]),
316 y: Fp::from_raw_unchecked([
317 0xbaac_93d5_0ce7_2271,
318 0x8c22_631a_7918_fd8e,
319 0xdd59_5f13_5707_25ce,
320 0x51ac_5829_5040_5194,
321 0x0e1c_8c3f_ad00_59c0,
322 0x0bbc_3efc_5008_a26a,
323 ]),
324 infinity: Choice::from(0u8),
325 }
326 }
327
328 #[inline]
330 pub fn is_identity(&self) -> Choice {
331 self.infinity
332 }
333
334 pub fn is_on_curve(&self) -> Choice {
336 (self.y.square() - (self.x.square() * self.x)).ct_eq(&B) | self.infinity
337 }
338
339 pub fn is_torsion_free(&self) -> Choice {
341 let minus_x_squared_times_p = G1Projective::from(self).mul_by_x().mul_by_x().neg();
342 let endomorphism_p = endomorphism(self);
343 minus_x_squared_times_p.ct_eq(&G1Projective::from(endomorphism_p))
344 }
345
346 pub fn to_compressed(&self) -> [u8; 48] {
348 let mut res = Fp::conditional_select(&self.x, &Fp::zero(), self.infinity).to_bytes();
349 res[0] |= 1u8 << 7; res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity); res[0] |= u8::conditional_select(
352 &0u8,
353 &(1u8 << 5),
354 (!self.infinity) & self.y.lexicographically_largest(), );
356 res
357 }
358
359 pub fn to_uncompressed(&self) -> [u8; 96] {
361 let mut res = [0; 96];
362 res[0..48].copy_from_slice(
363 &Fp::conditional_select(&self.x, &Fp::zero(), self.infinity).to_bytes()[..],
364 );
365 res[48..96].copy_from_slice(
366 &Fp::conditional_select(&self.y, &Fp::zero(), self.infinity).to_bytes()[..],
367 );
368 res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity);
369 res
370 }
371
372 pub fn from_uncompressed(bytes: &[u8; 96]) -> CtOption<Self> {
374 Self::from_uncompressed_unchecked(bytes)
375 .and_then(|p| CtOption::new(p, p.is_on_curve() & p.is_torsion_free()))
376 }
377
378 pub fn from_uncompressed_unchecked(bytes: &[u8; 96]) -> CtOption<Self> {
380 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
381 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
382 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
383 let x = {
384 let mut tmp = [0; 48];
385 tmp.copy_from_slice(&bytes[0..48]);
386 tmp[0] &= 0b0001_1111;
387 Fp::from_bytes(&tmp)
388 };
389 let y = Fp::from_bytes(<&[u8; 48]>::try_from(&bytes[48..96]).unwrap());
390
391 x.and_then(|x| {
392 y.and_then(|y| {
393 let p = G1Affine::conditional_select(
394 &G1Affine { x, y, infinity: infinity_flag_set },
395 &G1Affine::identity(),
396 infinity_flag_set,
397 );
398 CtOption::new(
399 p,
400 ((!infinity_flag_set) | (infinity_flag_set & x.is_zero() & y.is_zero())) &
401 (!compression_flag_set) &
402 (!sort_flag_set),
403 )
404 })
405 })
406 }
407
408 pub fn from_compressed(bytes: &[u8; 48]) -> Result<Self> {
410 Self::from_compressed_unchecked(bytes)
411 .into_option() .ok_or_else(|| Error::Parameter {
413 name: "compressed_bytes".into(),
414 reason: "invalid G1 point encoding".into(),
415 })
416 .and_then(|p| {
417 if !bool::from(p.is_torsion_free()) {
418 Err(Error::param("point", "not in correct subgroup"))
419 } else {
420 Ok(p)
421 }
422 })
423 }
424
425 pub(crate) fn from_compressed_unchecked(bytes: &[u8; 48]) -> CtOption<Self> {
427 let compression_flag_set = Choice::from((bytes[0] >> 7) & 1);
428 let infinity_flag_set = Choice::from((bytes[0] >> 6) & 1);
429 let sort_flag_set = Choice::from((bytes[0] >> 5) & 1);
430 let x = {
431 let mut tmp = *bytes;
432 tmp[0] &= 0b0001_1111;
433 Fp::from_bytes(&tmp)
434 };
435
436 x.and_then(|x| {
437 CtOption::new(
438 G1Affine::identity(),
439 infinity_flag_set & compression_flag_set & (!sort_flag_set) & x.is_zero(),
440 )
441 .or_else(|| {
442 ((x.square() * x) + B).sqrt().and_then(|y| {
443 let y = Fp::conditional_select(
444 &y,
445 &-y,
446 y.lexicographically_largest() ^ sort_flag_set,
447 );
448 CtOption::new(
449 G1Affine { x, y, infinity: infinity_flag_set },
450 (!infinity_flag_set) & compression_flag_set,
451 )
452 })
453 })
454 })
455 }
456}
457
458#[derive(Copy, Clone, Debug)]
460pub struct G1Projective {
461 pub(crate) x: Fp,
462 pub(crate) y: Fp,
463 pub(crate) z: Fp,
464}
465
466impl Default for G1Projective {
467 fn default() -> G1Projective {
468 G1Projective::identity()
469 }
470}
471
472#[cfg(feature = "zeroize")]
473impl zeroize::DefaultIsZeroes for G1Projective {}
474
475impl fmt::Display for G1Projective {
476 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
477 write!(f, "{:?}", self)
478 }
479}
480
481impl<'a> From<&'a G1Affine> for G1Projective {
482 fn from(p: &'a G1Affine) -> G1Projective {
483 G1Projective {
484 x: p.x,
485 y: p.y,
486 z: Fp::conditional_select(&Fp::one(), &Fp::zero(), p.infinity),
487 }
488 }
489}
490
491impl From<G1Affine> for G1Projective {
492 fn from(p: G1Affine) -> G1Projective {
493 G1Projective::from(&p)
494 }
495}
496
497impl ConstantTimeEq for G1Projective {
498 fn ct_eq(&self, other: &Self) -> Choice {
499 let x1 = self.x * other.z;
500 let x2 = other.x * self.z;
501 let y1 = self.y * other.z;
502 let y2 = other.y * self.z;
503 let self_is_zero = self.z.is_zero();
504 let other_is_zero = other.z.is_zero();
505
506 (self_is_zero & other_is_zero) | ((!self_is_zero) & (!other_is_zero) & x1.ct_eq(&x2) & y1.ct_eq(&y2))
507 }
508}
509
510impl ConditionallySelectable for G1Projective {
511 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
512 G1Projective {
513 x: Fp::conditional_select(&a.x, &b.x, choice),
514 y: Fp::conditional_select(&a.y, &b.y, choice),
515 z: Fp::conditional_select(&a.z, &b.z, choice),
516 }
517 }
518}
519
520impl Eq for G1Projective {}
521impl PartialEq for G1Projective {
522 #[inline]
523 fn eq(&self, other: &Self) -> bool {
524 bool::from(self.ct_eq(other))
525 }
526}
527
528impl<'a> Neg for &'a G1Projective {
529 type Output = G1Projective;
530
531 #[inline]
532 fn neg(self) -> G1Projective {
533 G1Projective {
534 x: self.x,
535 y: -self.y,
536 z: self.z,
537 }
538 }
539}
540
541impl Neg for G1Projective {
542 type Output = G1Projective;
543
544 #[inline]
545 fn neg(self) -> G1Projective {
546 -&self
547 }
548}
549
550impl<'a, 'b> Add<&'b G1Projective> for &'a G1Projective {
551 type Output = G1Projective;
552
553 #[inline]
554 fn add(self, rhs: &'b G1Projective) -> G1Projective {
555 self.add(rhs)
556 }
557}
558
559impl<'a, 'b> Sub<&'b G1Projective> for &'a G1Projective {
560 type Output = G1Projective;
561
562 #[inline]
563 fn sub(self, rhs: &'b G1Projective) -> G1Projective {
564 self + &(-rhs)
565 }
566}
567
568impl<'a, 'b> Mul<&'b Scalar> for &'a G1Projective {
569 type Output = G1Projective;
570
571 fn mul(self, other: &'b Scalar) -> Self::Output {
572 self.multiply(&other.to_bytes())
573 }
574}
575
576impl<'a, 'b> Mul<&'b G1Projective> for &'a Scalar {
577 type Output = G1Projective;
578
579 #[inline]
580 fn mul(self, rhs: &'b G1Projective) -> Self::Output {
581 rhs * self
582 }
583}
584
585impl<'a, 'b> Mul<&'b Scalar> for &'a G1Affine {
586 type Output = G1Projective;
587
588 fn mul(self, other: &'b Scalar) -> Self::Output {
589 G1Projective::from(self).multiply(&other.to_bytes())
590 }
591}
592
593impl<'a, 'b> Mul<&'b G1Affine> for &'a Scalar {
594 type Output = G1Projective;
595
596 #[inline]
597 fn mul(self, rhs: &'b G1Affine) -> Self::Output {
598 rhs * self
599 }
600}
601
602impl<'b> Add<&'b G1Projective> for G1Projective {
604 type Output = G1Projective;
605 #[inline]
606 fn add(self, rhs: &'b G1Projective) -> G1Projective {
607 &self + rhs
608 }
609}
610impl<'a> Add<G1Projective> for &'a G1Projective {
611 type Output = G1Projective;
612 #[inline]
613 fn add(self, rhs: G1Projective) -> G1Projective {
614 self + &rhs
615 }
616}
617impl Add<G1Projective> for G1Projective {
618 type Output = G1Projective;
619 #[inline]
620 fn add(self, rhs: G1Projective) -> G1Projective {
621 &self + &rhs
622 }
623}
624impl<'b> Sub<&'b G1Projective> for G1Projective {
625 type Output = G1Projective;
626 #[inline]
627 fn sub(self, rhs: &'b G1Projective) -> G1Projective {
628 &self - rhs
629 }
630}
631impl<'a> Sub<G1Projective> for &'a G1Projective {
632 type Output = G1Projective;
633 #[inline]
634 fn sub(self, rhs: G1Projective) -> G1Projective {
635 self - &rhs
636 }
637}
638impl Sub<G1Projective> for G1Projective {
639 type Output = G1Projective;
640 #[inline]
641 fn sub(self, rhs: G1Projective) -> G1Projective {
642 &self - &rhs
643 }
644}
645impl SubAssign<G1Projective> for G1Projective {
646 #[inline]
647 fn sub_assign(&mut self, rhs: G1Projective) {
648 *self = &*self - &rhs;
649 }
650}
651impl AddAssign<G1Projective> for G1Projective {
652 #[inline]
653 fn add_assign(&mut self, rhs: G1Projective) {
654 *self = &*self + &rhs;
655 }
656}
657impl<'b> SubAssign<&'b G1Projective> for G1Projective {
658 #[inline]
659 fn sub_assign(&mut self, rhs: &'b G1Projective) {
660 *self = &*self - rhs;
661 }
662}
663impl<'b> AddAssign<&'b G1Projective> for G1Projective {
664 #[inline]
665 fn add_assign(&mut self, rhs: &'b G1Projective) {
666 *self = &*self + rhs;
667 }
668}
669
670impl<'b> Mul<&'b Scalar> for G1Projective {
672 type Output = G1Projective;
673 #[inline]
674 fn mul(self, rhs: &'b Scalar) -> G1Projective {
675 &self * rhs
676 }
677}
678impl<'a> Mul<Scalar> for &'a G1Projective {
679 type Output = G1Projective;
680 #[inline]
681 fn mul(self, rhs: Scalar) -> G1Projective {
682 self * &rhs
683 }
684}
685impl Mul<Scalar> for G1Projective {
686 type Output = G1Projective;
687 #[inline]
688 fn mul(self, rhs: Scalar) -> G1Projective {
689 &self * &rhs
690 }
691}
692impl MulAssign<Scalar> for G1Projective {
693 #[inline]
694 fn mul_assign(&mut self, rhs: Scalar) {
695 *self = &*self * &rhs;
696 }
697}
698impl<'b> MulAssign<&'b Scalar> for G1Projective {
699 #[inline]
700 fn mul_assign(&mut self, rhs: &'b Scalar) {
701 *self = &*self * rhs;
702 }
703}
704
705impl<'b> Mul<&'b Scalar> for G1Affine {
707 type Output = G1Projective;
708 #[inline]
709 fn mul(self, rhs: &'b Scalar) -> G1Projective {
710 &self * rhs
711 }
712}
713impl<'a> Mul<Scalar> for &'a G1Affine {
714 type Output = G1Projective;
715 #[inline]
716 fn mul(self, rhs: Scalar) -> G1Projective {
717 self * &rhs
718 }
719}
720impl Mul<Scalar> for G1Affine {
721 type Output = G1Projective;
722 #[inline]
723 fn mul(self, rhs: Scalar) -> G1Projective {
724 &self * &rhs
725 }
726}
727
728impl<'b> Mul<&'b G1Affine> for Scalar {
730 type Output = G1Projective;
731 #[inline]
732 fn mul(self, rhs: &'b G1Affine) -> G1Projective {
733 &self * rhs
734 }
735}
736impl<'a> Mul<G1Affine> for &'a Scalar {
737 type Output = G1Projective;
738 #[inline]
739 fn mul(self, rhs: G1Affine) -> G1Projective {
740 self * &rhs
741 }
742}
743impl Mul<G1Affine> for Scalar {
744 type Output = G1Projective;
745 #[inline]
746 fn mul(self, rhs: G1Affine) -> G1Projective {
747 &self * &rhs
748 }
749}
750
751impl<'b> Mul<&'b G1Projective> for Scalar {
753 type Output = G1Projective;
754 #[inline]
755 fn mul(self, rhs: &'b G1Projective) -> G1Projective {
756 &self * rhs
757 }
758}
759impl<'a> Mul<G1Projective> for &'a Scalar {
760 type Output = G1Projective;
761 #[inline]
762 fn mul(self, rhs: G1Projective) -> G1Projective {
763 self * &rhs
764 }
765}
766impl Mul<G1Projective> for Scalar {
767 type Output = G1Projective;
768 #[inline]
769 fn mul(self, rhs: G1Projective) -> G1Projective {
770 &self * &rhs
771 }
772}
773
774#[inline(always)]
775fn mul_by_3b(a: Fp) -> Fp {
776 let a = a + a; let a = a + a; a + a + a }
780
781impl G1Projective {
782 pub fn identity() -> G1Projective {
784 G1Projective {
785 x: Fp::zero(),
786 y: Fp::one(),
787 z: Fp::zero(),
788 }
789 }
790
791 pub fn generator() -> G1Projective {
793 G1Projective {
794 x: G1Affine::generator().x,
795 y: G1Affine::generator().y,
796 z: Fp::one(),
797 }
798 }
799
800 pub fn random(mut rng: impl RngCore) -> Self {
802 loop {
803 let x = Fp::random(&mut rng);
804 let flip_sign = rng.next_u32() % 2 != 0;
805
806 let p = ((x.square() * x) + B).sqrt().map(|y| G1Affine {
807 x,
808 y: if flip_sign { -y } else { y },
809 infinity: 0.into(),
810 });
811
812 if p.is_some().into() {
813 let p_proj = G1Projective::from(p.unwrap());
814 let p_cleared = p_proj.clear_cofactor();
815 if !bool::from(p_cleared.is_identity()) {
816 return p_cleared;
817 }
818 }
819 }
820 }
821
822 pub fn msm_vartime(
834 points: &[G1Affine],
835 scalars: &[Scalar],
836 ) -> Result<Self> {
837 if points.len() != scalars.len() {
838 return Err(Error::Parameter {
839 name: "points/scalars".into(),
840 reason: "Input slices must have the same length".into(),
841 });
842 }
843 Ok(Self::pippenger(points, scalars, true))
844 }
845
846 pub fn msm(
854 points: &[G1Affine],
855 scalars: &[Scalar],
856 ) -> Result<Self> {
857 if points.len() != scalars.len() {
858 return Err(Error::Parameter {
859 name: "points/scalars".into(),
860 reason: "Input slices must have the same length".into(),
861 });
862 }
863 Ok(Self::pippenger(points, scalars, false))
864 }
865
866 fn pippenger(points: &[G1Affine], scalars: &[Scalar], is_vartime: bool) -> Self {
868 if points.is_empty() {
869 return Self::identity();
870 }
871
872 let num_entries = points.len();
873 let scalar_bits = 255; let c = if num_entries < 32 {
877 3
878 } else {
879 (num_entries as f64).log2() as usize + 2
880 };
881
882 let num_windows = (scalar_bits + c - 1) / c;
883 let num_buckets = 1 << c;
884 let mut global_acc = Self::identity();
885
886 for w in (0..num_windows).rev() {
888 let mut window_acc = Self::identity();
889 let mut buckets = vec![Self::identity(); num_buckets];
890
891 for i in 0..num_entries {
893 let scalar_bytes = scalars[i].to_bytes();
894
895 let mut k = 0;
897 for bit_idx in 0..c {
898 let total_bit_idx = w * c + bit_idx;
899 if total_bit_idx < scalar_bits {
900 let byte_idx = total_bit_idx / 8;
901 let inner_bit_idx = total_bit_idx % 8;
902 if (scalar_bytes[byte_idx] >> inner_bit_idx) & 1 == 1 {
903 k |= 1 << bit_idx;
904 }
905 }
906 }
907
908 if k > 0 {
909 buckets[k - 1] = buckets[k - 1].add_mixed(&points[i]);
912 }
913 }
914
915 let mut running_sum = Self::identity();
917 for i in (0..num_buckets).rev() {
918 running_sum = running_sum.add(&buckets[i]);
919 window_acc = window_acc.add(&running_sum);
920 }
921
922 global_acc = global_acc.add(&window_acc);
924
925 if w > 0 {
927 for _ in 0..c {
928 global_acc = global_acc.double();
929 }
930 }
931 }
932
933 if !is_vartime {
937 }
939
940 global_acc
941 }
942
943 pub fn double(&self) -> G1Projective {
950 let t0 = self.y.square();
952 let z3 = t0 + t0;
953 let z3 = z3 + z3;
954 let z3 = z3 + z3;
955 let t1 = self.y * self.z;
956 let t2 = self.z.square();
957 let t2 = mul_by_3b(t2);
958 let x3 = t2 * z3;
959 let y3 = t0 + t2;
960 let z3 = t1 * z3;
961 let t1 = t2 + t2;
962 let t2 = t1 + t2;
963 let t0 = t0 - t2;
964 let y3 = t0 * y3;
965 let y3 = x3 + y3;
966 let t1 = self.x * self.y;
967 let x3 = t0 * t1;
968 let x3 = x3 + x3;
969
970 let tmp = G1Projective { x: x3, y: y3, z: z3 };
971 G1Projective::conditional_select(&tmp, &G1Projective::identity(), self.is_identity())
972 }
973
974 pub fn add(&self, rhs: &G1Projective) -> G1Projective {
976 let t0 = self.x * rhs.x;
978 let t1 = self.y * rhs.y;
979 let t2 = self.z * rhs.z;
980 let t3 = self.x + self.y;
981 let t4 = rhs.x + rhs.y;
982 let t3 = t3 * t4;
983 let t4 = t0 + t1;
984 let t3 = t3 - t4;
985 let t4 = self.y + self.z;
986 let x3 = rhs.y + rhs.z;
987 let t4 = t4 * x3;
988 let x3 = t1 + t2;
989 let t4 = t4 - x3;
990 let x3 = self.x + self.z;
991 let y3 = rhs.x + rhs.z;
992 let x3 = x3 * y3;
993 let y3 = t0 + t2;
994 let y3 = x3 - y3;
995 let x3 = t0 + t0;
996 let t0 = x3 + t0;
997 let t2 = mul_by_3b(t2);
998 let z3 = t1 + t2;
999 let t1 = t1 - t2;
1000 let y3 = mul_by_3b(y3);
1001 let x3 = t4 * y3;
1002 let t2 = t3 * t1;
1003 let x3 = t2 - x3;
1004 let y3 = y3 * t0;
1005 let t1 = t1 * z3;
1006 let y3 = t1 + y3;
1007 let t0 = t0 * t3;
1008 let z3 = z3 * t4;
1009 let z3 = z3 + t0;
1010
1011 G1Projective { x: x3, y: y3, z: z3 }
1012 }
1013
1014 pub fn add_mixed(&self, rhs: &G1Affine) -> G1Projective {
1016 let t0 = self.x * rhs.x;
1018 let t1 = self.y * rhs.y;
1019 let t3 = rhs.x + rhs.y;
1020 let t4 = self.x + self.y;
1021 let t3 = t3 * t4;
1022 let t4 = t0 + t1;
1023 let t3 = t3 - t4;
1024 let t4 = rhs.y * self.z;
1025 let t4 = t4 + self.y;
1026 let y3 = rhs.x * self.z;
1027 let y3 = y3 + self.x;
1028 let x3 = t0 + t0;
1029 let t0 = x3 + t0;
1030 let t2 = mul_by_3b(self.z);
1031 let z3 = t1 + t2;
1032 let t1 = t1 - t2;
1033 let y3 = mul_by_3b(y3);
1034 let x3 = t4 * y3;
1035 let t2 = t3 * t1;
1036 let x3 = t2 - x3;
1037 let y3 = y3 * t0;
1038 let t1 = t1 * z3;
1039 let y3 = t1 + y3;
1040 let t0 = t0 * t3;
1041 let z3 = z3 * t4;
1042 let z3 = z3 + t0;
1043
1044 let tmp = G1Projective { x: x3, y: y3, z: z3 };
1045 G1Projective::conditional_select(&tmp, self, rhs.is_identity())
1046 }
1047
1048 fn multiply(&self, by: &[u8; 32]) -> G1Projective {
1049 let mut acc = G1Projective::identity();
1050 for &byte in by.iter().rev() {
1051 for i in (0..8).rev() {
1052 acc = acc.double();
1053 let bit = Choice::from((byte >> i) & 1u8);
1054 acc = G1Projective::conditional_select(&acc, &(acc + self), bit);
1055 }
1056 }
1057 acc
1058 }
1059
1060 fn mul_by_x(&self) -> G1Projective {
1061 let mut xself = G1Projective::identity();
1062 let mut x = super::BLS_X >> 1;
1063 let mut tmp = *self;
1064 while x != 0 {
1065 tmp = tmp.double();
1066 if x % 2 == 1 {
1067 xself += tmp;
1068 }
1069 x >>= 1;
1070 }
1071 if super::BLS_X_IS_NEGATIVE {
1072 xself = -xself;
1073 }
1074 xself
1075 }
1076
1077 pub fn clear_cofactor(&self) -> G1Projective {
1079 self - &self.mul_by_x()
1080 }
1081
1082 pub fn batch_normalize(p: &[Self], q: &mut [G1Affine]) {
1084 assert_eq!(p.len(), q.len());
1085
1086 let mut acc = Fp::one();
1087 for (p, q) in p.iter().zip(q.iter_mut()) {
1088 q.x = acc;
1089 acc = Fp::conditional_select(&(acc * p.z), &acc, p.is_identity());
1090 }
1091
1092 acc = acc.invert().unwrap();
1093
1094 for (p, q) in p.iter().rev().zip(q.iter_mut().rev()) {
1095 let skip = p.is_identity();
1096 let tmp = q.x * acc;
1097 acc = Fp::conditional_select(&(acc * p.z), &acc, skip);
1098 q.x = p.x * tmp;
1099 q.y = p.y * tmp;
1100 q.infinity = Choice::from(0u8);
1101 *q = G1Affine::conditional_select(q, &G1Affine::identity(), skip);
1102 }
1103 }
1104
1105 #[inline]
1107 pub fn is_identity(&self) -> Choice {
1108 self.z.is_zero()
1109 }
1110
1111 pub fn is_on_curve(&self) -> Choice {
1113 (self.y.square() * self.z).ct_eq(&(self.x.square() * self.x + self.z.square() * self.z * B))
1114 | self.z.is_zero()
1115 }
1116
1117 pub fn from_bytes(bytes: &[u8; 48]) -> CtOption<Self> {
1119 G1Affine::from_compressed_unchecked(bytes).map(G1Projective::from)
1120 }
1121
1122 pub fn from_bytes_unchecked(bytes: &[u8; 48]) -> CtOption<Self> {
1124 G1Affine::from_compressed_unchecked(bytes).map(G1Projective::from)
1125 }
1126
1127 pub fn from_bytes_validated(bytes: &[u8]) -> Result<Self> {
1129 validate::length("G1Projective::from_bytes", bytes.len(), 48)?;
1131
1132 let mut array = [0u8; 48];
1133 array.copy_from_slice(bytes);
1134
1135 Self::from_bytes_unchecked(&array)
1136 .into_option() .ok_or_else(|| Error::Processing {
1138 operation: "G1 deserialization",
1139 details: "invalid point encoding",
1140 })
1141 .and_then(|p| {
1142 validate::parameter(
1143 bool::from(p.is_on_curve()),
1144 "point",
1145 "not on curve"
1146 )?;
1147 Ok(p)
1148 })
1149 }
1150
1151 pub fn to_bytes(&self) -> [u8; 48] {
1153 G1Affine::from(self).to_compressed()
1154 }
1155}
1156
1157
1158#[cfg(test)]
1159mod tests {
1160 use super::*;
1161
1162 #[test]
1163 fn test_g1_msm() {
1164 let g = G1Affine::generator();
1165 let s1 = Scalar::from(2u64);
1166 let s2 = Scalar::from(3u64);
1167 let s3 = Scalar::from(4u64);
1168
1169 let p1 = G1Affine::from(G1Projective::from(g) * s1); let p2 = G1Affine::from(G1Projective::from(g) * s2); let p3 = G1Affine::from(G1Projective::from(g) * s3); let scalars = vec![s1, s2, s3];
1174 let points = vec![p1, p2, p3];
1175
1176 let expected = G1Projective::from(g) * Scalar::from(29u64);
1178
1179 let naive_result = (p1 * s1) + (p2 * s2) + (p3 * s3);
1181 assert_eq!(G1Affine::from(naive_result), G1Affine::from(expected));
1182
1183 let msm_result_vartime = G1Projective::msm_vartime(&points, &scalars).unwrap();
1185 assert_eq!(G1Affine::from(msm_result_vartime), G1Affine::from(expected));
1186
1187 let msm_result = G1Projective::msm(&points, &scalars).unwrap();
1189 assert_eq!(G1Affine::from(msm_result), G1Affine::from(expected));
1190
1191 let empty_res = G1Projective::msm(&[], &[]).unwrap();
1193 assert_eq!(empty_res, G1Projective::identity());
1194 }
1195}