pairing_ce/bls12_381/
mod.rs

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