Computing the Optimal Ate Pairing over the BN254 Curve
The optimal Ate pairing on BN254, step by step: twist, line equations, the Miller loop's last two lines, final exponentiation and Frobenius shortcuts, as implemented in the Polygon zkEVM.
The post BN254 For The Rest Of Us constitutes the base point for this article, so I highly recommend reading it to get a solid background of the BN254 curve. This post will reuse some parts with an emphasy on the computational aspect of the optimal Ate pairing over the BN254 curve.
For those with a poor background on Pairing-Based Cryptography (PBC) but with a decent background on Elliptic-Curve Cryptoraphy (ECC) I recommend reading the following resources in order:
- Pairings For Beginners.
- Pairing-Friendly Elliptic Curves of Prime Order.
- High-Speed Software Implementation of the Optimal Ate Pairing over Barreto–Naehrig Curves.
Only after (and not before) you feel sufficiently comfortable with both PBC and ECC come back to this post and start to make sense out of it.
The implementation in zkASM can be found here.
The Curve
The BN254 is the elliptic curve of the form:
defined over a finite field , where the prime is the following -bit number:
p = 21888242871839275222246405745257275088696311157297823662689037894645226208583
The number of points happens to also be a prime of bits:
r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
where t = 147946756881789318990833708069417712967 is known as the trace of Frobenius.
The point is a point of order , i.e. a generator of the group of points of the curve. In fact, all points in are generators, as Lagrange’s Theorem shows.
The embedding degree of this curve is .
For more information, refer to BN254 For The Rest Of Us or the EIPs 196 and 197.
Tower of Extension Fields
To represent we use the following tower of extension fields: fields:
where is not a quadratic residue in and is neither a quadratic residue or a cubic residue in .
In the particular case of the BN254, we have and and therefore:
from which we can extract the identities , , and consequently the idenity .
Using the latter identity, we can also write:
These two representations of will allow us to apply some optimizations:
- Writing any element as , with implies 1 . Thus, computing the -th power of any element in is computationally “free”.
- Now, if we write and where ,,,,, we have: which will allow us to compute and (needed for the final exponentiation) very efficiently.
Twist
BN curves admits a sextic twist defined over of the form:
or more specifically:
(y')² = (x')³ + (19485874751759354771024239261021720505790618469301721065564631296452457478373 + 266929791119991161246907387137283842545076965332900288569378510910307636690·u)
This means that pairing computations can be restricted to points and and avoid computations over entirely.
The number of points of is:
which concrete to:
#E' = 479095176016622842441988045216678740799252316531100822436447802254070093686356349204969212544220033486413271283566945264650845755880805213916963058350733
c = 21888242871839275222246405745257275088844257914179612981679871602714643921549
The mapping
defines a group homomorphism from to and we are going to use it to send points from the twisted curve to the curve (but not the other way around).
The Pairing
The optimal Ate pairing over the BN254 curve is defined by:
where:
-
is the only subgroup of the -torsion of over .
-
is the only subgroup of the -torsion of over .
-
is the set of -th roots of unity over .
-
x = 4965661367192848881and therefore6x+2 = 29793968203157093288, which is a number of bits that can be expressed in the base as follows:2^3 + 2^5 - 2^7 + 2^10 - 2^11 + 2^14 + 2^17 + 2^18 - 2^20 + 2^23 - 2^25 + 2^30 + 2^31 + 2^32 - 2^35 + 2^38 - 2^44 + 2^47 + 2^48 - 2^51 + 2^55 + 2^56 - 2^58 + 2^61 + 2^63 + 2^64 [0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1] 0001010-1001-100100110-10010-1000011100-100100000-1001100-1000110-1001011which has a Hamming weight of 26.
We prefer base over base because
6x+2expressed in the latter is:2^3 + 2^5 + 2^7 + 2^8 + 2^9 + 2^11 + 2^12 + 2^13 + 2^17 + 2^18 + 2^20 + 2^21 + 2^22 + 2^25 + 2^26 + 2^27 + 2^28 + 2^29 + 2^31 + 2^32 + 2^35 + 2^36 + 2^37 + 2^44 + 2^45 + 2^46 + 2^48 + 2^51 + 2^52 + 2^53 + 2^54 + 2^56 + 2^58 + 2^59 + 2^60 + 2^63 + 2^64 [0,0,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,1,1,0,1,1,1,0,0,1,1,1,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,1,0,0,1,1,1,1,0,1,0,1,1,1,0,0,1,1] 00010101110111000110111001111101100111000000111010011110101110011which has a Hamming weigth of 37.
I moved from base to base by using the identity2 that holds for any such that . In words, it is unpacking groups of ‘s of any size to a single and in the binary decomposition.
- , for any and , is a rational function on that is computed using Miller’s “double-and-add”-style algorithm: starting with .
- denotes the equation of a line passing through and while denotes the equation of a vertical line passing through . However, due to the final exponentiation, the value of remains unchanged if we omit the division by the vertical lines, so we will not care about such computation.
- is known as the Frobenius operator.
Therefore, what we want to compute is the following:
bound = [0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 0, -1,
0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0,
0, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0,
1, 1]
1101111010011011000001001001000111011101011100001011001111110111111100000111110100101101000001011101000011111001111110101000110
# This is 6x+2 in base {-1,0,1}, which has a Hamming weight of 26
def e(P,Q):
assert(subgroup_check_G1(P))
assert(subgroup_check_G2(Q))
if ((P == 0) or (Q == 0)) return 1 # Here, 0 is the identity element of E
R = Q
f = 1
for i in range(len(bound)-2,-1,-1): # len(bound)=65
f = f * f * line(twist(R),twist(R),P)
R = 2 * R
if bound[i] == 1:
f = f * line(twist(R),twist(Q),P)
R = R + Q
elif bound[i] == -1:
f = f * line(twist(R),twist(-Q),P)
R = R - Q
Qp = FrobEndo(Q); # Q'
f = f * line(twist(R), twist(Qp), P);
R = R + Qp;
Qpp = -FrobEndo(Qp); # Q''
f = f * line(twist(R), twist(Qpp), P);
return final_exponentiation(f)
In what follows we explain how to compute each of the components of the previous pseudocode snippet.
Subgroup Checks
To summary BN254 For The Rest Of Us, we have:
-
if and only if . That is, if we write then we simply need to ensure that the equation holds over .
Costs:
-
A point belongs to if and only if:
where is defined as , where .
This was proven in 2022/348 and it is clearly much faster than the naive check , since .
Costs:
Line Equations
Different Points
Given two points and in the twisted curve such that and and a point in the curve , the evaluation at of the line passing through and is given by:
Costs:
The Same Points
Given a point in the twisted curve and a point in the curve , the evaluation at of the line passing through is given by:
Costs:
The Last two Lines
Now we explain some tricks for the computation of the lines:
- For the first line notice that if , then: where are precomputed.
The conjugate of an element in in is .
Moreover, due to $\Psi$ being an homomorphism we have that $[n]\Psi(Q) = \Psi([n]Q)$ for all $n \in \mathbb{F}_r$. Consequently, we compute $\ell_{\Psi([6x+2]Q),\Psi(Q')}(P)$ as in the previous section, with $Q' = ({\gamma_{1,2}}\bar{x}',\gamma_{1,3}\bar{y}') = (x_1,y_1)$ (it's a good exercise to check that $Q'$ belongs to $E$).
**Costs:** $\underbrace{2\tilde{c} + 2\tilde{m}}_{Q'} + \ell_{\text{diff}}$
I don’t include the cost of computing , since it is obtained in the Miller loop.
-
For the second line we similarly have:
Again, due to the homomorphic property of , we compute as in the previous section, with (again, check that belongs to ).
Costs:
Hence, in both cases, the Frobenius operator comes for free.
Final Exponentiation
In the final exponentiation, we raise an element to the power .
First, divide the exponent as follows:
The Easy Part
Let’s start with the easy part of the easy part, when we first attempt to compute . But since, , we have , just one conjugate, one inversion and one multiplication in .
The conjugate of an element in in is . Hence, if we write we have:
To finish the easy part, we first compute which is the Frobenius operator applied to and then multiply the result by to finally obtain .
Importantly, after the computation of the easy part, the resulting field element becomes a member of the cyclotomic subgroup , which means that inversion from now on can be computed by simply conjugation. Moreover, when an element belongs to , one can compute using fewer multiplications and therefore the overall costs of performing exponentiations (see this section).
Costs:
The Hard Part
Following Section 5 of this 2008/490, we can write:
where:
- .
- .
- .
- .
So we just need to compute:
and then multiply them all.
In what follows, remember that
x = 4965661367192848881, which is a number of bits that can be expressed in the base as follows:1 - 2^4 + 2^9 + 2^11 + 2^16 + 2^19 + 2^21 + 2^22 + 2^25 + 2^27 + 2^30 + 2^34 + 2^36 + 2^37 + 2^39 + 2^41 + 2^44 + 2^47 + 2^48 + 2^51 - 2^53 + 2^56 + 2^58 + 2^62 [1,0,0,0,-1,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,-1,0,0,1,0,1,0,0,0,1] 1000-1000010100001001011001010010001011010100100110010-1001010001which has a Hamming weight of 24.
We prefer base over base because
xexpressed in the latter is:1 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^11 + 2^16 + 2^19 + 2^21 + 2^22 + 2^25 + 2^27 + 2^30 + 2^34 + 2^36 + 2^37 + 2^39 + 2^41 + 2^44 + 2^47 + 2^48 + 2^51 + 2^53 + 2^54 + 2^55 + 2^58 + 2^62 [1,0,0,0,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,1,0,0,1,0,0,0,1] 100011111001000010010110010100100010110101001001100101110010001which has a Hamming weigth of 28.
We proceed as follows:
-
We start by computing .
-
Then, compute (use the Frobenius operator).
-
Next, we group the previous elements as follows:
(recall that at this point computing the conjugate is the same as computing the inverse)
-
Finally, compute the product:
Expand for correctness
$$
\begin{aligned}
&y_0 \cdot y_1^2 \cdot y_2^6 \cdot y_3^{12} \cdot y_4^{18} \cdot y_5^{30} \cdot y_6^{36} = \\
&(m^p \cdot m^{p^2} \cdot m^{p^3}) \cdot \left(\frac{1}{m}\right)^2 \cdot (m^{x^2p^2})^6 \cdot \left(\frac{1}{m^{xp}}\right)^{12} \cdot \left(\frac{1}{m^{x}m^{x^2p}}\right)^{18} \cdot \left(\frac{1}{m^{x^2}}\right)^{30} \cdot \left(\frac{1}{m^{x^3}m^{x^3p}}\right)^{36} \\
&= \underbrace{\left(\frac{1}{m}\right)^2 \cdot \left(\frac{1}{m^{x}}\right)^{18}\left(\frac{1}{m^{x^2}}\right)^{30}\left(\frac{1}{m^{x^3}}\right)^{36}}_{m^{\lambda_0}}\cdot \underbrace{m^p \cdot \left(\frac{1}{m^{xp}}\right)^{12} \cdot \left(\frac{1}{m^{x^2p}}\right)^{18} \cdot \left(\frac{1}{m^{x^3p}}\right)^{36}}_{m^{\lambda_1p}} \cdot \underbrace{m^{p^2} \cdot (m^{x^2p^2})^6}_{m^{\lambda_2p^2}} \cdot \underbrace{m^{p^3}}_{m^{\lambda_3p^3}} \\
&= m^{\lambda_0} \cdot m^{\lambda_1p} \cdot m^{\lambda_2p^2} \cdot m^{\lambda_3p^3} = m^{\lambda_0 + \lambda_1p + \lambda_2p^2 + \lambda_3p^3} = m^{\frac{p^4-p^2+1}{r}}
\end{aligned}
$$
To compute this product as efficient as possible, we use the vectorial addition chain technique as explained in the last part of Section 5 of [2008/490](https://eprint.iacr.org/2008/490.pdf):
which requires only multiplications and squarings.
Costs:
Frobenius Operator
As we have shown, in the final exponentation we must compute the first, second and third Frobenius operator over an element in . Recalling that , a naive implementation would take -operations, but we will do it much better.
Recall that we can write any element as:
where and with and .
Expand to see the proof
We will now show that raising an -element over any power of is almost cost free and therefore so is .
- Take with . Then, for Lagrange theorem. Similarly, .
- Notice and therefore , where .
Using all the previous observations, we have:
which can be computed using a few multiplications and a few conjugations, assuming each is pre-computed for .
Similarly, notice and therefore , where .
Lastly, we can use the identity to show that and therefore , where .
Then, we have:
with , and . Hence, assuming the precomputation of for , we can compute or almost for free.
Costs:
Speeding up Computations in the Cyclotomic Subgroup
I follow 2010/542 closely for this section.
Recall that:
and also:
For this optimitzation, we will further need the following representation:
so that for , we can equivalently write .
This optimization is due to “compression” and “decompression” technique, which exploits the algebraic relationships arising from elements belonging to the cyclotomic subgroup .
Compression and Decompression
If then the compression function is:
and the decompression function is:
where:
Compressed Squaring
Now, on input we will be able to compute its square on compressed form. That is, , where :
Exponentiation in the Cyclotomic Subgroup
Given and , the idea is to compute using the squaring formula in compressed form.
Represent in binary as with and define . Then:
Therefore, we can use the square-and-multiply algorithm to compute such product. Since we are going to be squaring in compressed form, we start at rather than the standard in such algorithm.
def exp_cyclo(f,e):
Cf = comp(f);
result = 1;
for i in range(len(e)):
if (e[i] == 1) {
result = decomp(Cf) * result;
}
Cf = square_comp(Cf);
}
return result;
Appendix A: Field Isomorphisms
Recall that:
We use two additional representations of .
The first one is used to efficiently compute the Frobenius operator and is as follows:
The second one is used to speed up the squares and exponentations in the hard part of the final exponentiation:
Isomorphism between A and B
We start with and , where we notice that if we take , we can use the identity to rewrite it as:
This relationship induces the following field isomorphism and its inverse :
Exercise: Check that is a field isomorphism between and and that for all and it is true that and .
Isomorphism between B and C
We continue with and , for which we notice that can be equivalently written as .
This relationship induces the following field isomorphism and its inverse :
Exercise: Check that is a field isomorphism between and and that for all and it is true that and .
Appendix B: Finite Field Arithmetic
Fp2 Arithmetic
Addition
# INPUT: (a = a1 + a2·u), (b = b1 + b2·u) ∈ Fp2, where ai,bi ∈ Fp
# OUTPUT: (c1 + c2·u) = a + b ∈ Fp
c1 = a1 + b1
c2 = a2 + b2
Subtraction
# INPUT: (a = a1 + a2·u), (b = b1 + b2·u) ∈ Fp2, where ai,bi ∈ Fp
# OUTPUT: (c1 + c2·u) = a - b ∈ Fp
c1 = a1 - b1
c2 = a2 - b2
Multiplication
# INPUT: (a = a1 + a2·u), (b = b1 + b2·u) ∈ Fp2, where ai,bi ∈ Fp
# OUTPUT: (c1 + c2·u) = a·b ∈ Fp
c1 = a1·b1 - a2·b2
c2 = a1·b2 + a2·b1
Scalar Multiplication
# INPUT: b ∈ Fp, (a = a1 + a2·u) ∈ Fp2, where ai ∈ Fp
# OUTPUT: (c1 + c2·u) = a·b ∈ Fp
c1 = b·a1
c2 = b·a2
Square
# INPUT: (a = a1 + a2·u) ∈ Fp2, where ai ∈ Fp
# OUTPUT: (c1 + c2·u) = a² ∈ Fp
c1 = (a1 - a2)·(a1 + a2)
c2 = 2·a1·a2
Inverse
# INPUT: (a = a1 + a2·u) ∈ Fp2, where ai ∈ Fp
# OUTPUT: (c1 + c2·u) = a⁻¹ ∈ Fp
c1 = a1·(a1² + a2²)⁻¹
c2 = -a2·(a1² + a2²)⁻¹
Fp4 Arithmetic
Square
# INPUT: (a = a1 + a2·V) ∈ Fp4, where ai ∈ Fp2
# OUTPUT: (c1 + c2·V) = a² ∈ Fp4
c1 = a2²·(9 + u) + a1²
c2 = (a1 + a2)² - a1² - a2²
Fp6 Arithmetic
Addition
# INPUT: (a = a1 + a2·v + a3·v²),(b = b1 + b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a + b ∈ Fp6
c1 = a1 + b1
c2 = a2 + b2
c3 = a3 + b3
Subtraction
# INPUT: (a = a1 + a2·v + a3·v²),(b = b1 + b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a - b ∈ Fp6
c1 = a1 - b1
c2 = a2 - b2
c3 = a3 - b3
Multiplication
# INPUT: (a = a1 + a2·v + a3·v²),(b = b1 + b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a·b ∈ Fp6
c1 = [(a2+a3)·(b2+b3) - a2·b2 - a3·b3]·(9+u) + a1·b1
c2 = (a1+a2)·(b1+b2) - a1·b1 - a2·b2 + (9+u)·(a3·b3)
c3 = (a1+a3)·(b1+b3) - a1·b1 + a2·b2 - a3·b3
Scalar Multiplication
# INPUT: b ∈ Fp, (a = a1 + a2·v + a3·v²) ∈ Fp6, where ai ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a·b ∈ Fp6
c1 = b·a1
c1 = b·a2
c1 = b·a3
The following three algorithms help to compute the line equations. See the sparse multiplications algorithms of next section for a full understanding.
Sparse Multiplication A
# INPUT: (a = a1 + a2·v + a3·v²),b = b2·v ∈ Fp6, where ai,b2 ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a·b ∈ Fp6
c1 = b2·a3·(9+u)
c2 = b2·a1
c3 = b2·a2
Sparse Multiplication B
# INPUT: (a = a1 + a2·v + a3·v²),(b = b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a·b ∈ Fp6
c1 = [(a2 + a3)·(b2 + b3) - a2·b2 - a3·b3]·(9+u)
c2 = a1·b2 + a3·b3·(9+u)
c3 = (a1 + a3)·b3 - a3·b3 + a2·b2
Sparse Multiplication C
# INPUT: (a = a1 + a2·v + a3·v²),(b = b1 + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a·b ∈ Fp6
c1 = a1·b1 + a2·b3·(9+u)
c2 = a2·b1 + a3·b3·(9+u)
c3 = (a1 + a3)·(b1 + b3) - a1·b1 - a3·b3
Square
# INPUT: (a = a1 + a2·v + a3·v²) ∈ Fp6, where ai ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a² ∈ Fp6
c1 = 2·a2·a3·(9 + u) + a1²
c2 = a3²·(9 + u) + 2·a1·a2
c3 = 2·a1·a2 - a3² + (a1 - a2 + a3)² + 2·a2·a3 - a1²
Inverse
# INPUT: (a = a1 + a2·v + a3·v²) ∈ Fp6, where ai ∈ Fp2
# OUTPUT: (c1 + c2·v + c3·v²) = a⁻¹ ∈ Fp6
c1mid = a1² - (9 + u)·(a2·a3)
c2mid = (9 + u)·a3² - (a1·a2)
c3mid = a2² - (a1·a3)
c1 = (a1² - (9 + u)·(a2·a3))·(a1·c1mid + xi·(a3·c2mid + a2·c3mid))⁻¹
c2 = ((9 + u)·a3² - (a1·a2))·(a1·c1mid + xi·(a3·c2mid + a2·c3mid))⁻¹
c3 = (a2²-a1·a3)·(a1·c1mid + xi·(a3·c2mid + a2·c3mid))⁻¹
Fp12 Arithmetic
Addition
# INPUT: (a = a1 + a2·w),(b = b1 + b2·w) ∈ Fp12, where ai,bi ∈ Fp6
# OUTPUT: (c1 + c2·w) = a + b ∈ Fp12
c1 = a1 + b1
c2 = a2 + b2
Subtraction
# INPUT: (a = a1 + a2·w),(b = b1 + b2·w) ∈ Fp12, where ai,bi ∈ Fp6
# OUTPUT: (c1 + c2·w) = a - b ∈ Fp12
c1 = a1 - b1
c2 = a2 - b2
Multiplication
# INPUT: (a = a1 + a2·w),(b = b1 + b2·w) ∈ Fp12, where ai,bi ∈ Fp6
# OUTPUT: (c1 + c2·w) = a·b ∈ Fp12
c1 = a1·b1 + a2·b2·v
c2 = (a1+a2)·(b1+b2) - a1·b1 - a2·b2
The following two algorithms are used to compute the line equations avoiding all multiplications by zero that arise from the sparisity of such equations.
Sparse Multiplication A
# INPUT: (a = a1 + a2·w),(b = b1 + b2·w) ∈ Fp12, where ai ∈ Fp6, b1 = b12·v and b2 = b22·v + b23·v², with b12,b22,b23 ∈ Fp2
# OUTPUT: (c1 + c2·w) = a·b ∈ Fp12
c1 = a1·b1 + a2·b2·v
c2 = (a1+a2)·[(b12+b22)·v + b23·v²] - a1·b1 - a2·b2
Sparse Multiplication B
# INPUT: (a = a1 + a2·w),(b = b1 + b2·w) ∈ Fp12, where ai ∈ Fp6, b1 = b11 + b13·v² and b2 = b22·v, with b11,b13,b22 ∈ Fp2
# OUTPUT: (c1 + c2·w) = a·b ∈ Fp12
c1 = a1·b1 + a2·b2·v
c2 = (a1+a2)·(b11 + b22·v + b13·v²) - a1·b1 - a2·b2
Square
# INPUT: (a = a1 + a2·w) ∈ Fp12, where ai ∈ Fp6
# OUTPUT: (c1 + c2·w) = a² ∈ Fp12
c1 = (a1-a2)·(a1-a2·v) + a1·a2 + a1·a2·v
c2 = 2·a1·a2
Inverse
# INPUT: (a = a1 + a2·w) ∈ Fp12, where ai ∈ Fp6
# OUTPUT: (c1 + c2·w) = a⁻¹ ∈ Fp12
c1 = a1·(a1² - a2²·v)⁻¹
c2 = -a2·(a1² - a2²·v)⁻¹
First Frobenius Operator
# INPUT: (a = a1 + a2·w) = ((a11 + a12v + a13v²) + (a21 + a22v + a23v²)) ∈ Fp12, where ai ∈ Fp6 and aij ∈ Fp2
# OUTPUT: (c1 + c2·w) = a^p ∈ Fp12
c1 = a̅11 + a̅12·γ12·v + a̅13·γ14·v²
c2 = a̅21·γ11 + a̅22·γ13·v + a̅23·γ15·v²
Second Frobenius Operator
# INPUT: (a = a1 + a2·w) = ((a11 + a12v + a13v²) + (a21 + a22v + a23v²)) ∈ Fp12, where ai ∈ Fp6 and aij ∈ Fp2
# OUTPUT: (c1 + c2·w) = a^p² ∈ Fp12
c1 = a11 + a12·γ22·v + a13·γ24·v²
c2 = a21·γ21 + a22·γ23·v + a23·γ25·v²
Third Frobenius Operator
# INPUT: (a = a1 + a2·w) = ((a11 + a12v + a13v²) + (a21 + a22v + a23v²)) ∈ Fp12, where ai ∈ Fp6 and aij ∈ Fp2
# OUTPUT: (c1 + c2·w) = a^p³ ∈ Fp12
c1 = a̅11 + a̅12·γ32·v + a̅13·γ34·v²
c2 = a̅21·γ31 + a̅22·γ33·v + a̅23·γ35·v²
The following two algorithms are used for computing squarings and exponentiations over the cyclotomic subgroup . Luckily for us, this is the case after performing the easy part of the final exponentiation.
Fast Squaring
# INPUT: (a = a1 + a2·w) ∈ GΦ6(p²), where ai ∈ Fp6
# OUTPUT: ((c11 + c12·v + c13·v²) + (c21 + c22·v + c23·v²)·w) = a² ∈ GΦ6(p²)
[t11,t22] = (a11 + a22·V)²
[t23,t12] = (a21 + a13·V)²
[t13,aux] = (a12 + a23·V)²
t21 = aux·(9+u)
c11 = -2·a11 + 3·t11
c12 = -2·a12 + 3·t23
c13 = -2·a13 + 3·t13
c21 = 2·a21 + 3·t21
c22 = 2·a22 + 3·t22
c23 = 2·a23 + 3·t12
Fast Exponentatiation
# INPUT: e, (a = a1 + a2·w) ∈ GΦ6(p²), where e ∈ [0,p¹²-2] ai ∈ Fp6
# OUTPUT: (c = c1 + c2·w) = a^e ∈ GΦ6(p²)
c = a
for i in range(L-2,-1,-1): # L is log2(e)
c = c² # Use previous algorithm
if e[i] == 1:
c = c·a
return c
Footnotes
-
if you don’t know why, make sure to review Galois theory. Start by noticing that Galois group is a cyclic group of order generated by the Frobenius endomorphism . ↩
-
I recently discoverd that this is just a particular case of the more generic non-adjacent form (NAF) of a number. ↩