Crypto Pairing By Example

I am fascinated by cryptography pairing (pairing-friendly curve cryptography) within elliptic curves, and the potential it gives for…

Crypto Pairing By Example

I am fascinated by cryptography pairing (pairing-friendly curve cryptography) within elliptic curves, and the potential it gives for signing, anonymisation and zero-knowledge proofs. So let’s show the potential, and demonstrate these with examples. I will be using the MIRACL Go libary, and which is a super fast implementation of crypto pairing [here].

With pair-based cryptography we have two cyclic groups (G1 and G2), and which are of an order of a prime number (n). A pairing on (G1,G2,GT) defines the function e:GG2→GT, and where g1 is a generator for G1 and g2 is a generator for G2. If we have the points of U1 and U2 on G1 and V1 and V2 on G2, we get the bilinear mapping of:

e(U1+U2,V1)=e(U1,V1)×e(U2,V1)

e(U1,V1+V2)=e(U1,V1)×e(U1,V2)

If U is a point on G1, and V is a point on G2, we get:

e(aU,bV)=e(U,V)^{ab}

In this example, we will prove these mappings for a pairing for e(aU,bV)=e(U,V)^{ab}. The outline coding using the library from the MIRACL library [here] is [here]:

package main
import (
"os"
"fmt"
"github.com/miracl/core/go/core/BN254"
"strconv"
)
func main() {
	argCount := len(os.Args[1:])
a1:=5
b1:=10
        if (argCount>0) {a1,_= strconv.Atoi(os.Args[1])}
if (argCount>1) {b1,_= strconv.Atoi(os.Args[2])}

   	a := BN254.NewBIGint(a1)
b := BN254.NewBIGint(b1)
ab := BN254.NewBIGint(a1*b1)

U := BN254.ECP_generator()
V := BN254.ECP2_generator()
	aval:=BN254.G1mul(U,a)
bval:=BN254.G2mul(V,b)

	p1 := BN254.Ate(bval,aval)	
p1 = BN254.Fexp(p1)
	aval2:=BN254.G1mul(U,BN254.NewBIGint(1))
bval2:=BN254.G2mul(V,BN254.NewBIGint(1))

	p2 := BN254.Ate(bval2,aval2)
p2 = BN254.Fexp(p2)
p2 = p2.Pow(ab)

	fmt.Printf("a=%d, b=%d\n",a1,b1)
fmt.Printf("Pairing: e(aU,bV)=e(U,V)^{ab}\n")
	fmt.Printf("\nPairing: %s\n",p1.ToString())

	if p1.Equals(p2) { fmt.Printf("\nPairing 1 [e(aU,bV)] is equal to Pairing 2 [e(U,V)^{ab}]")}	
    
}

A sample run [here]:

a=10, b=50
Pairing: e(aU,bV)=e(U,V)^{ab}
Pairing: [[[179ce13fbae0790fbe950c7ddc30022b21546157c1914ad427471573b56d261a,086e1f8bfd90a98081f32c80a78d5cda818ca5489ad1ec74727596e89ee9e872],[0a717cedabe82e50076be7ccaddba089f5ae2e37df96a0f33415d1d774173716,03bd5047eb80fdf0833ae2af947c14f6d9da5a9c90ce2b7ede31ef2c35db4c4d]],[[1de5331e039efbe6083067a9998eaaf843c14fcfbff5a479c49e736ecc1e134b,0320c31bdf277cbd8d8a06c3d6a4f86ab88f52b5fcd251db0b63b4b532278f93],[22fc417eee2ef1db9d9c1ad7a94cca6eea05a4d9c0388a807ce9b46b835d6301,22595df50a840cb7b903132780ed41a078d7424c9c187651707595c1f37ebb95]],[[000b1ad0b9f06cdfaa63611adc554dc9d2c3fbae4ddbb2698af426a2d460eb0e,079ef43d92f299e1db16990eb12ae9c20cc9fd37decf597fed087d15a2154599],[2450da2a41f32159a5b32a769921b1ab8c8ef1a84d682ee539ad60077b4d835b,24ecae1301df4bbbc32eb1d76bcb06772fea7f523412ca455b5eb6b60965ab7a]]]
Pairing 1 [e(aU,bV)] is equal to Pairing 2 [e(U,V)^{ab}]

Now we will prove: e(aU,bV)=e(abU,V). The outline coding using the library from the MIRACL library [here] is [here]:

package main
import (
"os"
"fmt"
"github.com/miracl/core/go/core/BN254"
"strconv"
)
func main() {
	argCount := len(os.Args[1:])
a1:=5
b1:=10
        if (argCount>0) {a1,_= strconv.Atoi(os.Args[1])}
if (argCount>1) {b1,_= strconv.Atoi(os.Args[2])}

   	a := BN254.NewBIGint(a1)
b := BN254.NewBIGint(b1)
 
U := BN254.ECP_generator()
V := BN254.ECP2_generator()
	aval:=BN254.G1mul(U,a)
bval:=BN254.G2mul(V,b)

	p1 := BN254.Ate(bval,aval)	
p1 = BN254.Fexp(p1)
	aval2:=BN254.G1mul(U,BN254.NewBIGint(a1*b1))
bval2:=BN254.G2mul(V,BN254.NewBIGint(1))

	p2 := BN254.Ate(bval2,aval2)	
p2 = BN254.Fexp(p2)

	fmt.Printf("a=%d, b=%d\n",a1,b1)
fmt.Printf("Pairing: e(aU,bV)=e(abU,V)\n")
	fmt.Printf("\nPairing: %s\n",p1.ToString())

	if p1.Equals(p2) { fmt.Printf("\nPairing 1 [e(aU,bV)] is equal to Pairing 2 [e(abU,V)]")}	
    
}

A sample run [here]:

a=10, b=50
Pairing: e(aU,bV)=e(abU,V)
Pairing: [[[179ce13fbae0790fbe950c7ddc30022b21546157c1914ad427471573b56d261a,086e1f8bfd90a98081f32c80a78d5cda818ca5489ad1ec74727596e89ee9e872],[0a717cedabe82e50076be7ccaddba089f5ae2e37df96a0f33415d1d774173716,03bd5047eb80fdf0833ae2af947c14f6d9da5a9c90ce2b7ede31ef2c35db4c4d]],[[1de5331e039efbe6083067a9998eaaf843c14fcfbff5a479c49e736ecc1e134b,0320c31bdf277cbd8d8a06c3d6a4f86ab88f52b5fcd251db0b63b4b532278f93],[22fc417eee2ef1db9d9c1ad7a94cca6eea05a4d9c0388a807ce9b46b835d6301,22595df50a840cb7b903132780ed41a078d7424c9c187651707595c1f37ebb95]],[[000b1ad0b9f06cdfaa63611adc554dc9d2c3fbae4ddbb2698af426a2d460eb0e,079ef43d92f299e1db16990eb12ae9c20cc9fd37decf597fed087d15a2154599],[2450da2a41f32159a5b32a769921b1ab8c8ef1a84d682ee539ad60077b4d835b,24ecae1301df4bbbc32eb1d76bcb06772fea7f523412ca455b5eb6b60965ab7a]]]
Pairing 1 [e(aU,bV)] is equal to Pairing 2 [e(abU,V)]

Now we prove e(U1+U2,V) =e(U1,V)*e(U2,V) [here]:

package main
import (
	"fmt"
"github.com/miracl/core/go/core/BN254"
)
func main() {
 
U1 := BN254.ECP_generator()
U2 := BN254.ECP_generator()

	V := BN254.ECP2_generator()
	p2 := BN254.Ate(V,U1)	
p2 = BN254.Fexp(p2)
	p3 := BN254.Ate(V,U2)	
p3 = BN254.Fexp(p3)
	p3.Mul(p2)

	U1.Add(U2)
p1 := BN254.Ate(V,U1)
p1 = BN254.Fexp(p1)

	fmt.Printf("U1=%s\nU2=%s\n",U1.ToString(),U2.ToString())
fmt.Printf("Pairing: e(U1+U2,V)=e(U1,V)*e(U2,V)\n")
	fmt.Printf("\nPairing: %s\n",p1.ToString())

	if p1.Equals(p3) { fmt.Printf("\nPairing 1 [e(U1+U2,V)] is equal to Pairing 2 [e(U1,V)*{e(U2,V)]")}	
}

A sample run [here]:

U1=(0948d920900000006e8d1360000000021848400000000004e9c0000000000009,17361ed1680000011460b070000000053cb4a0000000000c4860000000000003)
U2=(2523648240000001ba344d80000000086121000000000013a700000000000012,0000000000000000000000000000000000000000000000000000000000000001)
Pairing: e(U1+U2,V)=e(U1,V)*e(U2,V)
Pairing: [[[1958eeeb60db1c8c2a63ad94e5f646dc8e94fdc32f11d8d02d26ddc8af9b0c06,0bc61719e86ad825f16d9d1f34aeb236fafcdd3ff466841424597ace9aa67872],[105d0c40559d5116162718c78586ffb7ca442170bd869176cb24cfbbd5225534,1d8e6c0d1f8404ba675711786a51599498981c0ff11d3462a1f0e191b37b150b]],[[139e5c34b4e2a31f3a1ac5bce7cb6782959a297d52682fb053aa115c1934941f,1f551b6ff6358b15a0cff575834549100c29de2911c78f008f633d34b9546c36],[24b3bd14fb0f222fe26755eea0de06935c6efef27ebb9153a27a74a1dab1d68b,033f1a5f2b484c0619eb14138cdc0b6d84ad24ba846cca766afe61857661c843]],[[01b5d285f3595e47bf663d15a1a6cd5601b9b104543228390742090c6fbe3e5f,088c77265783aabd1e2f4196826444f52463ff642e51813131e8a23551770d51],[022e2e6d26fc832deafa732e9a78af49e1fc0be44c1a86cab5e7b90ddaedf800,239243673bfb2cbde4da1cd9f957e3b7f2a3f21995eb69a382c085be4a18a6c2]]]
Pairing 1 [e(U1+U2,V)] is equal to Pairing 2 [e(U1,V)*e(U2,V)]

Conclusions

And there you go … crypto magic!