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