# How does Ethereum BLS signature verification works?

I am implementing BLS signature verification on smart contracts and I have a question regarding the way that Ethereum verifies the signature. Recall that bls signature works as

• $$e(P_2,H(m)_1)_T=e(G_2, S_1)_T$$ where $$_2$$ and $$_1$$ denote points of $$G_2$$ and $$G_1$$, and $$_T$$ for $$G_T$$.
• Off-chain, you take your secret $$x$$ , and do $$x\,G_2\to P_2$$ (your public key).
• You then provide your public key $$P_2$$ to the on-chain contract.
• You then generate your signature, $$x\,H(m)_1\to S_1$$.
• You provide signature to on-chain contract.
• It verifies $$e(P_2,H(m)_1)_T=e(G_2, S_1)_T$$.

However, Ethereum verifies the equality little differently than the last line. Specifically they check if:

$$e(A_2,B_1)*e(C_2,D_1)==1_T$$

The pseudo-code that does all this can be written by

from py_ecc.bn128 import *
p = curve_order
x = randint(1, p-1) # out secret key
H_m = multiply(G1, randint(1, p-1)) # lets pretend it's HashToPoint
P = multiply(G2, x) # our public key in G2
S = multiply(H_m, x) # our signature in G1
a = pairing(P, H_m)
b = pairing(G2, S)
assert a == b # Verify signature


To use equivalent of ECPAIRING, you’d then do:

c = pairing(G2, neg(S))
assert a * c == FQ12.one()


What I don't understand is how $$e(A_2,B_1)*e(C_2,D_1)==1_T$$. I far as I know the neg stands for negation operation. The ECPAIRING is the opcode they named. Can someone help me to see what I am missing?

Moderator's note: some of this question matches that post

It all comes down to the properties of the pairing operation (commonly denoted as $$e$$, called pairing in the code).

$$e$$ is a function that takes two elliptic curve points as inputs, and generates a value for which multiplication and exponentiation makes sense (in practice, it is an element within an 'extension field', however you don't need to worry what that means)

One property that $$e$$ has is this identity:

$$e(aG, bH) = e(G,H)^{ab}$$

This identity is true for any integers $$a, b$$, and any two points $$G, H$$.

The BLS signature verification logic relies on this: if the public key is $$P_2 = xG_2$$ (and $$G_2$$ is also known by the verifier), and the message is mapped to a point $$H(m)_1$$, and the signature is $$S_1 = xH(m)_1$$, then the standard BLS verify (assuming a valid signature) computes the two pairings:

$$e(P_2, H(m)_1) = e(xG_2, H(m)_1) = e(G_2, H(m)_1)^x$$

$$e(G_2, S_1) = e(G_2, xH(m)_1) = e(G_2, H(m)_1)^x$$

If the signature is invalid, the second equation evaluates to something else.

If $$S_1$$ is in fact $$xH(m)_1$$ (that is, if the signature is valid, these two values are the same.

Now, the Ethereum BLS verification logic is equivalent, but works slightly differently: it instead computes (again, if the signature is valid):

$$e(G_2, -S_1) = e(G_2, -xH(m)_1) = e(G_2, H(m)_1)^{-x}$$

Remember, negating a point is the same as multiplying it by -1.

And again, if the signature is invalid, it evaluates to something else.

And so, if the signature is valid, the verifier has just computed the two values $$e(G_2, H(m)_1)^x$$ and $$e(G_2, H(m)_1)^{-x}$$; these are multiplicative inverses of each other, and so multiplying them together evaluates to one.

• This was great explanation. Thank you! Oct 25, 2022 at 13:47