pairing_plus/bls12_381/
mod.rs

1mod cofactor;
2mod ec;
3mod fq;
4mod fq12;
5mod fq2;
6mod fq6;
7mod fr;
8mod isogeny;
9mod osswu_map;
10
11#[cfg(test)]
12mod tests;
13
14pub(crate) use self::cofactor::ClearH;
15pub use self::ec::{
16    G1Affine, G1Compressed, G1Prepared, G1Uncompressed, G2Affine, G2Compressed, G2Prepared,
17    G2Uncompressed, G1, G2,
18};
19pub use self::fq::{Fq, FqRepr};
20pub use self::fq12::Fq12;
21pub use self::fq2::Fq2;
22pub use self::fq6::Fq6;
23pub use self::fr::{Fr, FrRepr};
24pub(crate) use self::isogeny::IsogenyMap;
25pub(crate) use self::osswu_map::OSSWUMap;
26
27pub mod transmute {
28    pub use super::ec::g1::transmute_affine as g1_affine;
29    pub use super::ec::g1::transmute_projective as g1_projective;
30    pub use super::ec::g2::transmute_affine as g2_affine;
31    pub use super::ec::g2::transmute_projective as g2_projective;
32    pub use super::fq::transmute as fq;
33    pub use super::fr::transmute as fr;
34}
35
36use super::{CurveAffine, Engine};
37
38use ff::{BitIterator, Field, ScalarEngine};
39
40// The BLS parameter x for BLS12-381 is -0xd201000000010000
41const BLS_X: u64 = 0xd201000000010000;
42const BLS_X_IS_NEGATIVE: bool = true;
43
44#[derive(Clone, Debug)]
45pub struct Bls12;
46
47impl ScalarEngine for Bls12 {
48    type Fr = Fr;
49}
50
51impl Engine for Bls12 {
52    type G1 = G1;
53    type G1Affine = G1Affine;
54    type G2 = G2;
55    type G2Affine = G2Affine;
56    type Fq = Fq;
57    type Fqe = Fq2;
58    type Fqk = Fq12;
59
60    fn miller_loop<'a, I>(i: I) -> Self::Fqk
61    where
62        I: IntoIterator<
63            Item = &'a (
64                &'a <Self::G1Affine as CurveAffine>::Prepared,
65                &'a <Self::G2Affine as CurveAffine>::Prepared,
66            ),
67        >,
68    {
69        let mut pairs = vec![];
70        for &(p, q) in i {
71            if !p.is_zero() && !q.is_zero() {
72                pairs.push((p, q.coeffs.iter()));
73            }
74        }
75
76        // Twisting isomorphism from E to E'
77        fn ell(f: &mut Fq12, coeffs: &(Fq2, Fq2, Fq2), p: &G1Affine) {
78            let mut c0 = coeffs.0;
79            let mut c1 = coeffs.1;
80
81            c0.c0.mul_assign(&p.y);
82            c0.c1.mul_assign(&p.y);
83
84            c1.c0.mul_assign(&p.x);
85            c1.c1.mul_assign(&p.x);
86
87            // Sparse multiplication in Fq12
88            f.mul_by_014(&coeffs.2, &c1, &c0);
89        }
90
91        let mut f = Fq12::one();
92
93        let mut found_one = false;
94        for i in BitIterator::new(&[BLS_X >> 1]) {
95            if !found_one {
96                found_one = i;
97                continue;
98            }
99
100            for &mut (p, ref mut coeffs) in &mut pairs {
101                ell(&mut f, coeffs.next().unwrap(), &p.0);
102            }
103
104            if i {
105                for &mut (p, ref mut coeffs) in &mut pairs {
106                    ell(&mut f, coeffs.next().unwrap(), &p.0);
107                }
108            }
109
110            f.square();
111        }
112
113        for &mut (p, ref mut coeffs) in &mut pairs {
114            ell(&mut f, coeffs.next().unwrap(), &p.0);
115        }
116
117        if BLS_X_IS_NEGATIVE {
118            f.conjugate();
119        }
120
121        f
122    }
123
124    fn final_exponentiation(r: &Fq12) -> Option<Fq12> {
125        let mut f1 = *r;
126        f1.conjugate();
127
128        match r.inverse() {
129            Some(mut f2) => {
130                let mut r = f1;
131                r.mul_assign(&f2);
132                f2 = r;
133                r.frobenius_map(2);
134                r.mul_assign(&f2);
135
136                fn exp_by_x(f: &mut Fq12, x: u64) {
137                    *f = f.pow(&[x]);
138                    if BLS_X_IS_NEGATIVE {
139                        f.conjugate();
140                    }
141                }
142
143                let mut x = BLS_X;
144                let mut y0 = r;
145                y0.square();
146                let mut y1 = y0;
147                exp_by_x(&mut y1, x);
148                x >>= 1;
149                let mut y2 = y1;
150                exp_by_x(&mut y2, x);
151                x <<= 1;
152                let mut y3 = r;
153                y3.conjugate();
154                y1.mul_assign(&y3);
155                y1.conjugate();
156                y1.mul_assign(&y2);
157                y2 = y1;
158                exp_by_x(&mut y2, x);
159                y3 = y2;
160                exp_by_x(&mut y3, x);
161                y1.conjugate();
162                y3.mul_assign(&y1);
163                y1.conjugate();
164                y1.frobenius_map(3);
165                y2.frobenius_map(2);
166                y1.mul_assign(&y2);
167                y2 = y3;
168                exp_by_x(&mut y2, x);
169                y2.mul_assign(&y0);
170                y2.mul_assign(&r);
171                y1.mul_assign(&y2);
172                y2 = y3;
173                y2.frobenius_map(1);
174                y1.mul_assign(&y2);
175
176                Some(y1)
177            }
178            None => None,
179        }
180    }
181}
182
183impl G2Prepared {
184    pub fn is_zero(&self) -> bool {
185        self.infinity
186    }
187
188    pub fn from_affine(q: G2Affine) -> Self {
189        if q.is_zero() {
190            return G2Prepared {
191                coeffs: vec![],
192                infinity: true,
193            };
194        }
195
196        fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
197            // Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
198            let mut tmp0 = r.x;
199            tmp0.square();
200
201            let mut tmp1 = r.y;
202            tmp1.square();
203
204            let mut tmp2 = tmp1;
205            tmp2.square();
206
207            let mut tmp3 = tmp1;
208            tmp3.add_assign(&r.x);
209            tmp3.square();
210            tmp3.sub_assign(&tmp0);
211            tmp3.sub_assign(&tmp2);
212            tmp3.double();
213
214            let mut tmp4 = tmp0;
215            tmp4.double();
216            tmp4.add_assign(&tmp0);
217
218            let mut tmp6 = r.x;
219            tmp6.add_assign(&tmp4);
220
221            let mut tmp5 = tmp4;
222            tmp5.square();
223
224            let mut zsquared = r.z;
225            zsquared.square();
226
227            r.x = tmp5;
228            r.x.sub_assign(&tmp3);
229            r.x.sub_assign(&tmp3);
230
231            r.z.add_assign(&r.y);
232            r.z.square();
233            r.z.sub_assign(&tmp1);
234            r.z.sub_assign(&zsquared);
235
236            r.y = tmp3;
237            r.y.sub_assign(&r.x);
238            r.y.mul_assign(&tmp4);
239
240            tmp2.double();
241            tmp2.double();
242            tmp2.double();
243
244            r.y.sub_assign(&tmp2);
245
246            tmp3 = tmp4;
247            tmp3.mul_assign(&zsquared);
248            tmp3.double();
249            tmp3.negate();
250
251            tmp6.square();
252            tmp6.sub_assign(&tmp0);
253            tmp6.sub_assign(&tmp5);
254
255            tmp1.double();
256            tmp1.double();
257
258            tmp6.sub_assign(&tmp1);
259
260            tmp0 = r.z;
261            tmp0.mul_assign(&zsquared);
262            tmp0.double();
263
264            (tmp0, tmp3, tmp6)
265        }
266
267        fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
268            // Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
269            let mut zsquared = r.z;
270            zsquared.square();
271
272            let mut ysquared = q.y;
273            ysquared.square();
274
275            let mut t0 = zsquared;
276            t0.mul_assign(&q.x);
277
278            let mut t1 = q.y;
279            t1.add_assign(&r.z);
280            t1.square();
281            t1.sub_assign(&ysquared);
282            t1.sub_assign(&zsquared);
283            t1.mul_assign(&zsquared);
284
285            let mut t2 = t0;
286            t2.sub_assign(&r.x);
287
288            let mut t3 = t2;
289            t3.square();
290
291            let mut t4 = t3;
292            t4.double();
293            t4.double();
294
295            let mut t5 = t4;
296            t5.mul_assign(&t2);
297
298            let mut t6 = t1;
299            t6.sub_assign(&r.y);
300            t6.sub_assign(&r.y);
301
302            let mut t9 = t6;
303            t9.mul_assign(&q.x);
304
305            let mut t7 = t4;
306            t7.mul_assign(&r.x);
307
308            r.x = t6;
309            r.x.square();
310            r.x.sub_assign(&t5);
311            r.x.sub_assign(&t7);
312            r.x.sub_assign(&t7);
313
314            r.z.add_assign(&t2);
315            r.z.square();
316            r.z.sub_assign(&zsquared);
317            r.z.sub_assign(&t3);
318
319            let mut t10 = q.y;
320            t10.add_assign(&r.z);
321
322            let mut t8 = t7;
323            t8.sub_assign(&r.x);
324            t8.mul_assign(&t6);
325
326            t0 = r.y;
327            t0.mul_assign(&t5);
328            t0.double();
329
330            r.y = t8;
331            r.y.sub_assign(&t0);
332
333            t10.square();
334            t10.sub_assign(&ysquared);
335
336            let mut ztsquared = r.z;
337            ztsquared.square();
338
339            t10.sub_assign(&ztsquared);
340
341            t9.double();
342            t9.sub_assign(&t10);
343
344            t10 = r.z;
345            t10.double();
346
347            t6.negate();
348
349            t1 = t6;
350            t1.double();
351
352            (t10, t1, t9)
353        }
354
355        let mut coeffs = vec![];
356        let mut r: G2 = q.into();
357
358        let mut found_one = false;
359        for i in BitIterator::new([BLS_X >> 1]) {
360            if !found_one {
361                found_one = i;
362                continue;
363            }
364
365            coeffs.push(doubling_step(&mut r));
366
367            if i {
368                coeffs.push(addition_step(&mut r, &q));
369            }
370        }
371
372        coeffs.push(doubling_step(&mut r));
373
374        G2Prepared {
375            coeffs,
376            infinity: false,
377        }
378    }
379}
380
381#[test]
382fn bls12_engine_tests() {
383    ::tests::engine::engine_tests::<Bls12>();
384}