ark-curves-cherry-picked/cp6_782/src/curves/mod.rs
cp6_782/src/curves/mod.rsRaw
1use ark_ec::{models::short_weierstrass::SWCurveConfig, PairingEngine};
2use ark_ff::{
3 biginteger::BigInteger832,
4 fields::{BitIteratorBE, Field},
5 BigInt, One,
6};
7
8use crate::{Fq, Fq3, Fq6, Fr};
9
10pub mod g1;
11pub use self::g1::{G1Affine, G1Projective};
12
13pub mod g2;
14pub use self::g2::{G2Affine, G2Projective};
15
16#[cfg(test)]
17mod tests;
18
19pub type GT = Fq6;
20
21#[derive(Copy, Clone, Debug, PartialEq, Eq)]
22pub struct CP6_782;
23
24impl PairingEngine for CP6_782 {
25 type Fr = Fr;
26 type G1Projective = G1Projective;
27 type G1Affine = G1Affine;
28 type G1Prepared = G1Affine;
29 type G2Projective = G2Projective;
30 type G2Affine = G2Affine;
31 type G2Prepared = G2Affine;
32 type Fq = Fq;
33 type Fqe = Fq3;
34 type Fqk = Fq6;
35
36 fn miller_loop<'a, I>(i: I) -> Self::Fqk
37 where
38 I: IntoIterator<Item = &'a (Self::G1Prepared, Self::G2Prepared)>,
39 {
40 let mut result = Self::Fqk::one();
41 for &(ref p, ref q) in i {
42 result *= &CP6_782::ate_miller_loop(p, q);
43 }
44 result
45 }
46
47 fn final_exponentiation(r: &Self::Fqk) -> Option<Self::Fqk> {
48 Some(CP6_782::final_exponentiation(r))
49 }
50}
51
52impl CP6_782 {
53 pub fn ate_pairing(p: &G1Affine, q: &G2Affine) -> GT {
54 CP6_782::final_exponentiation(&CP6_782::ate_miller_loop(p, q))
55 }
56
57 fn ate_miller_loop(p: &G1Affine, q: &G2Affine) -> Fq6 {
58 let px = p.x;
59 let py = p.y;
60 let qx = q.x;
61 let qy = q.y;
62 let mut py_twist_squared = TWIST.square();
63 py_twist_squared.mul_assign_by_fp(&py);
64
65 let mut old_rx;
66 let mut old_ry;
67 let mut rx = qx;
68 let mut ry = qy;
69 let mut f = Fq6::one();
70
71 // The for loop is executed for all bits (EXCEPT the MSB itself) of
72 // cp6_782_param_p (skipping leading zeros) in MSB to LSB order
73 for bit in BitIteratorBE::without_leading_zeros(ATE_LOOP_COUNT).skip(1) {
74 old_rx = rx;
75 old_ry = ry;
76
77 let old_rx_square = old_rx.square();
78 let old_rx_square_3 = old_rx_square.double() + &old_rx_square;
79 let old_rx_square_3_a = old_rx_square_3 + &g2::Parameters::COEFF_A;
80 let old_ry_double_inverse = old_ry.double().inverse().unwrap();
81
82 let gamma = old_rx_square_3_a * &old_ry_double_inverse;
83 let gamma_twist = gamma * &TWIST;
84 let gamma_old_rx = gamma * &old_rx;
85 let mut gamma_twist_px = gamma_twist;
86 gamma_twist_px.mul_assign_by_fp(&px);
87
88 let x = py_twist_squared;
89 let y = gamma_old_rx - &old_ry - &gamma_twist_px;
90 let ell_rr_at_p: Fq6 = Fq6::new(x, y);
91
92 rx = gamma.square() - &old_rx.double();
93 ry = gamma * &(old_rx - &rx) - &old_ry;
94 f = f.square() * &ell_rr_at_p;
95
96 if bit {
97 old_rx = rx;
98 old_ry = ry;
99
100 let gamma = (old_ry - &qy) * &((old_rx - &qx).inverse().unwrap());
101 let gamma_twist = gamma * &TWIST;
102 let gamma_qx = gamma * &qx;
103 let mut gamma_twist_px = gamma_twist;
104 gamma_twist_px.mul_assign_by_fp(&px);
105
106 let x = py_twist_squared;
107 let y = gamma_qx - &qy - &gamma_twist_px;
108 let ell_rq_at_p: Fq6 = Fq6::new(x, y);
109
110 rx = gamma.square() - &old_rx - &qx;
111 ry = gamma * &(old_rx - &rx) - &old_ry;
112 f = f * &ell_rq_at_p;
113 }
114 }
115 f
116 }
117
118 fn final_exponentiation(value: &Fq6) -> GT {
119 let value_inv = value.inverse().unwrap();
120 let value_to_first_chunk = CP6_782::final_exponentiation_first(value, &value_inv);
121 let value_inv_to_first_chunk = CP6_782::final_exponentiation_first(&value_inv, value);
122 CP6_782::final_exponentiation_last(&value_to_first_chunk, &value_inv_to_first_chunk)
123 }
124
125 fn final_exponentiation_first(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
126 // (q^3-1)*(q+1)
127
128 // elt_q3 = elt^(q^3)
129 let mut elt_q3 = elt.clone();
130 elt_q3.frobenius_map(3);
131 // elt_q3_over_elt = elt^(q^3-1)
132 let elt_q3_over_elt = elt_q3 * elt_inv;
133 // alpha = elt^((q^3-1) * q)
134 let mut alpha = elt_q3_over_elt.clone();
135 alpha.frobenius_map(1);
136 // beta = elt^((q^3-1)*(q+1)
137 alpha * &elt_q3_over_elt
138 }
139
140 fn final_exponentiation_last(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
141 let mut elt_q = elt.clone();
142 elt_q.frobenius_map(1);
143
144 let w1_part = elt_q.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_W1);
145 let w0_part = if FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG {
146 elt_inv.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0)
147 } else {
148 elt.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0)
149 };
150
151 w1_part * &w0_part
152 }
153}
154
155/// TWIST = (0, 1, 0)
156pub const TWIST: Fq3 = Fq3::new(Fq::ZERO, Fq::ONE, Fq::ZERO);
157
158/// ATE_IS_LOOP_COUNT_NEG = false
159pub const ATE_IS_LOOP_COUNT_NEG: bool = false;
160
161/// ATE_LOOP_COUNT =
162/// 506464946133393486072777102926336625944849939610982267859828541006717966526573193706126370441346337661774335955699621
163pub const ATE_LOOP_COUNT: [u64; 13] = [
164 0x55c5b9b57b942ae8,
165 0x3d52287d3dfd424a,
166 0xcf1ff9d6a543deb7,
167 0x820c9c5711ceeebc,
168 0x549a2d44305d20fe,
169 0x50f5c131afd70235,
170 0xab3596c8617c5792,
171 0x830c728d80f9d78b,
172 0x6a7223ee72023d07,
173 0xbc5d176b746af026,
174 0xe959283d8f526663,
175 0xc4d2263babf8941f,
176 0x3848,
177];
178
179/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
180pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
181
182/// FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0 =
183/// 7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033
184pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt::new([
185 0xb62ef36af72855d1,
186 0x676b5cef49d290fa,
187 0xd17fcf3c60947427,
188 0x5b93d992bc1b2849,
189 0x2171887cecd072cb,
190 0x879a2873f1516f4a,
191 0x8cc6856bd2cdf24e,
192 0xbff4fb6644d01993,
193 0x5dcbeea3e31ea667,
194 0x5f256f47681649f3,
195 0x2355a2b0839967fe,
196 0x144ed,
197 0x0,
198]);
199
200/// FINAL_EXPONENT_LAST_CHUNK_W1 =
201/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986
202pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt::new([
203 0x5657b9b57b942aea,
204 0x84f9a65f3bd54eaf,
205 0x5ea4214e35cd127,
206 0xe3cbcbc14ec1501d,
207 0xf196cb845a3092ab,
208 0x7e14627ad0e19017,
209 0x217db4,
210 0x0,
211 0x0,
212 0x0,
213 0x0,
214 0x0,
215 0x0,
216]);