pairing_plus/bls12_381/
mod.rs1mod 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
40const 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 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 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 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 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}