Computing the Optimal Ate Pairing over the BLS12-381 Curve
A computation-first walkthrough of the optimal Ate pairing on BLS12-381: the extension-field tower, line equations, final exponentiation and cyclotomic tricks behind our zkASM implementation.
· 12 min read · Pairings, Elliptic Curves, Polygon zkEVM
The post BLS12-381 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 BLS12-381 curve. This post will reuse some parts with an emphasy on the computational aspect of the optimal Ate pairing over such 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:
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 full list of consulted resources can be found at the end of this post.
The implementation in zkASM has been done in this PR.
The Curve
The BLS12-381 is the elliptic curve E of the form:
y2=x3+4
defined over a finite field Fp, where the prime p is the following 381-bit number:
p = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
The number of points #E(Fp)=p+1−t can be factorized as follows:
where t = x + 1 = -15132376222941642751 is known as the trace of Frobenius and x is the BLS-family parameter that generates this specific curve.
Therefore, its 255-bit prime factor:
r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
is the only one with sufficiently size for cryptographic purposes.
The point P∈E(Fp) with coordinates:
x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
is a point of order r, i.e. a generator of the subgroup of size r of the curve.
The embedding degree k of this curve is 12.
Tower of Extension Fields
To represent Fp12 we use the following tower of extension fields:
fields:
from which we can extract the identities u2=−1, w2=v, v3=1+u and consequently the idenity w6=1+u.
Using the latter identity, we can also write:
Fp12=Fp2[w]/(w6−(1+u))
These two representations of Fp12 will allow us to apply some optimizations:
Writing any element f∈Fp12 as f=g+hw, with g,h∈Fp6 implies fp6=fˉ=g−hw. Thus, computing the p6-th power of any element in Fp12 is computationally “free”.
Now, if we write g=g0+g1v+g2v2 and h=h0+h1v+h2v2 where g0,g1,g2,h0,h1,h2∈Fp2 we have:
f=g0+h0w+g1w2+h1w3+g2w4+h2w5,
which will allow us to compute fp and fp2 (needed for the final exponentiation) very efficiently.
Twist
BLS curves admits a sextic twist E′ defined over Fp2 of the form:
y′2=x′3+4⋅(1+u).
This means that pairing computations can be restricted to points P∈E(Fp) and Q∈E′(Fp2) and avoid computations over Fp12 entirely.
The point P∈E′(Fp2) with coordinates:
x = 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 + 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758·uy = 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 + 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582·u
is a point of order r, i.e. a generator of the subgroup of size r of the curve.
defines a group isomorphism from E′(Fp2)[r] to E(Fp12)[r]∩Ker(πp−[p]) and we are going to use it to convert points from the twisted curve E′ to the curve E only whenever required.
The inverse mapping, the twist, is defined as:
φ−1(x′,y′)=(x′w2,y′w3).
The Pairing
The optimal Ate pairing e:G1×G2→GT over the BLS12-381 curve is defined by:
e(P,Q)=f∣x∣,Q(P)rp12−1
where:
G1=E(Fp)[r] is the only subgroup of the r-torsion of E over Fp.
G2=E(Fp12)[r]∩Ker(πp−[p]), represented for point arithmetic efficiency by E′(Fp2)[r]. The former is the trace zero subgroup of the r-torsion of E over Fp12, whereas the latter is the only subgroup of the r-torsion of E′ over Fp2.
GT=μr is the set of r-th roots of unity over Fp12∗.
x = -15132376222941642752, which is a number of 64 bits that can be expressed in binary as:
The conjugate of an element in f=a+bw in Fp12 is fˉ=a−bw. Hence, if we write f=g0+h0w+g1w2+h1w3+g2w4+h2w5 we have:
fˉ=g0−h0w+g1w2−h1w3+g2w4−h2w5.
Therefore, what we want to compute is the following:
def e(P,Q): assert(subgroup_check_G1(P)) assert(subgroup_check_G2(Q)) if ((P == 0) or (Q == 0)) return 1 # Here, 0 represents the # point at infinity R = Q f = 1 for i in range(len(x)-2,-1,-1): f = f * f * line(untwist(R),untwist(R),P) R = 2 * R if x[i] == 1: f = f * line(untwist(R),untwist(Q),P) R = R + Q return final_exponentiation(conjugate(f))
In what follows we explain how to compute each of the components of the previous pseudocode snippet.
This is clearly much cheaper than the naive scalar multiplication by r, since its main cost is the scalar multiplication by (x2−1)/3, which is half the size of r and has low Hamming weight.
A point Q∈E′(Fp2) belongs to G2=E′(Fp2)[r] if and only if:
[x]ψ3(Q)+Q=ψ2(Q)
where ψ:E′(Fp2)→E′(Fp2) is the untwist-Frobenius-twist endomorphism, i.e., ψ:=φ−1πpφ.
Again, this is much cheaper than the naive scalar multiplication by r, since its main cost is the scalar multiplication by x, which is roughly a fourth the size of r.
Line Equations
Different Points
Given two points Q1=(x1′,y1′) and Q2=(x2′,y2′) in the twisted curve E′(Fp2) such that x1′=y1′ and x2′=y2′ and a point P=(x,y) in the curve E(Fp), the evaluation at P of the line passing through φ(Q1) and φ(Q2) is given by:
Given a point Q=(x′,y′) in the twisted curve E′(Fp2) and a point P=(x,y) in the curve E(Fp), the evaluation at P of the line passing through φ(Q) is given by:
ℓφ(Q),φ(Q)(P)=w(3x′3−2y′2)+w3(−3xx′2)+w4(2yy′)
Final Exponentiation
In the final exponentiation, we raise an element f∈Fp12 to the power (p12−1)/r.
Let’s start with the easy part of the easy part, when we first attempt to compute fp6−1. But since, fp6=fˉ, we have fp6−1=fˉ⋅f−1, just one conjugate, one inversion and one multiplication in Fp12.
To finish the easy part, we first compute (f(p6−1))p2 which is the Frobenius operator applied to fp6−1 and then multiply the result by fp6−1 to finally obtain m:=f(p6−1)(p2+1)∈Fp12.
Importantly, after the computation of the easy part, the resulting field element becomes a member of the cyclotomic subgroup Gϕ6(p2)=Gϕ12(p)={a∈Fp12∣aϕ12(p)=ap4−p2+1=ap6+1=1}, which means that inversion from now on can be computed by simply conjugation. Moreover, when an element a belongs to Gϕ6(p2), one can compute a2 using fewer multiplications and therefore the overall costs of performing exponentiations (see this section).
The Hard Part
Following Section 5 of this 2020/875, we can write:
(recall that, at this point, computing the conjugate is the same as computing the inverse)
Frobenius Operator
As we have shown, in the final exponentation we must compute the first and second Frobenius operator πp,πp2 over an element in Fp12. Recalling that πpi(x)=xpi, a naive implementation would take O(logp)Fp12-operations, but we will do it much better.
Recall that we can write any element f∈Fp12 as:
f=g+hw=g0+h0w+g1w2+h1w3+g2w4+h2w5
where g=g0+g1v+g2v2 and h=h0+h1v+h2v2 with g,h∈Fp6 and gi,hi∈Fp2.
For this optimitzation, it will be useful to introduce Fp4 and represent Fp12 as a degree-3 extension of Fp4:
Fp4Fp12=Fp2[V]/(V2−(1+u)),=Fp4[w]/(w3−V),
where V=w3; so that an element f in Fp12 can be written as f=(g0+g1V)+(g2+g3V)w+(g4+g5V)w2. We can equivalently write f=g0+g2w+g4w2+g1w3+g3w4+g5w5.
These optimizations are due to “compression” and “decompression” techniques, which exploits the algebraic relationships arising from elements belonging to the cyclotomic subgroup Gϕ6(p2).
Compression and Decompression
If f=g0+g2w+g4w2+g1w3+g3w4+g5w5∈Gϕ6(p2) then the compression function C is:
Now, on input f∈Gϕ6(p2) we will be able to compute its square on compressed form. That is, C(f2)=[h2,h3,h4,h5], where h=f2=h0+h2w+h4w2+h1w3+h3w4+h5w5:
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 C(f) rather than the standard f 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;