Within elliptic curves, we can have a scalar value (\(a\)) and a base point on the curve (\(G\)). We then perform an add operation to produce another point on the curve as \(aG\). This is the equivalent operation of adding the point \(G\) for \(a\) times. Normally we would define \(aG\) as a public key point, and \(a\) as a private key scalar value. Typically these operations are done within a finite field defined by prime number (\(p\)). With Boneh–Lynn–Shacham (BLS) curves we actually have two generator groups: \(\mathbb{G}_1\) and \(\mathbb{G}_2\). Generally the data within \(\mathbb{G}_2\) is twice the size of 𝔾1 and where there are slower operations. We also place the signature and the public keys to be in different group, such as placing a public key in \(\mathbb{G}_2\) and the signature in \(\mathbb{G}_1\). These curves can be used for crypto pairing, and in creating short signatures. In this case we will compute \(aG\) for different values of \(a\) on the BLS12-377 curve. The "377" part comes from the size of the prime number used. The BLS12-381 curve is used in Ethereum, zkSnarks and Zcash, and gives 128-bit security. More details on crypto pairing [here][Pairing friendly curves]. Crypto pairing is now used in many applications including short signatures, blind signatures, multi-signatures, aggregated signatures, verifiable encryption, ring signatures and threshold signatures.
BLS12 curve for ECC with Kryptology |
Method
With Boneh–Lynn–Shacham (BLS) curves we actually have two groups (\(\mathbb{G}_1\) and \(\mathbb{G}_2\)) and which can be used for crypto pairing. The use the form of \(y^2 = x^3 + b \pmod p\). In this case we will compute \(aG\) for different values of \(a\) on the BLS12-377 curve. The first group has one base point, while the second group has two. The points on \(\mathbb{G}_1\) are encoded with 128 bytes, and on \(\mathbb{G}_2\) they are encoded in 256 bytes.
The BLS12-377 curve has the following parameters [here]:
Base field modulus = 0x01ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001 B coefficient = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 Main subgroup order = 0x12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001 Extension tower: Fp2 construction: Fp quadratic non-residue = 0x01ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508bffffffffffc Fp6/Fp12 construction: Fp2 cubic non-residue c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Fp2 cubic non-residue c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 Twist parameters: Twist type: D B coefficient for twist c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 B coefficient for twist c1 = 0x010222f6db0fd6f343bd03737460c589dc7b4f91cd5fd889129207b63c6bf8000dd39e5c1ccccccd1c9ed9999999999a Generators: G1: X = 0x008848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef Y = 0x01914a69c5102eff1f674f5d30afeec4bd7fb348ca3e52d96d182ad44fb82305c2fe3d3634a9591afd82de55559c8ea6 G2: X c0 = 0x018480be71c785fec89630a2a3841d01c565f071203e50317ea501f557db6b9b71889f52bb53540274e3e48f7c005196 X c1 = 0x00ea6040e700403170dc5a51b1b140d5532777ee6651cecbe7223ece0799c9de5cf89984bff76fe6b26bfefa6ea16afe Y c0 = 0x00690d665d446f7bd960736bcbb2efb4de03ed7274b49a58e458c282f832d204f2cf88886d8c7c2ef094094409fd4ddf Y c1 = 0x00f8169fd28355189e549da3151a70aa61ef11ac3d591bf12463b01acee304c24279b83f5e52270bd9a1cdd185eb8f93 Pairing parameters: |x| (miller loop scalar) = 0x8508c00000000001 x is negative = false
and for BLS12-381 [here]:
Base field modulus = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab B coefficient = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 Main subgroup order = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 Extension tower Fp2 construction: Fp quadratic non-residue = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa Fp6/Fp12 construction: Fp2 cubic non-residue c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 Fp2 cubic non-residue c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 Twist parameters: Twist type: M B coefficient for twist c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 B coefficient for twist c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 Generators: G1: X = 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb Y = 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 G2: X c0 = 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 X c1 = 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e Y c0 = 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 Y c1 = 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be Pairing parameters: |x| (miller loop scalar) = 0xd201000000010000 x is negative = true
Implementation
The following is an implementation for the supported curves (Ed25519, BLS 12377, sepc256k1, P256 and Pallas):
package main import ( "fmt" "os" "strconv" "github.com/coinbase/kryptology/pkg/core/curves" ) func main() { val1 := 1 argCount := len(os.Args[1:]) if argCount > 0 { val1, _ = strconv.Atoi(os.Args[1]) } curve := curves.BLS12377G1() x := curve.Scalar.New(val1) G := curve.Point.Generator() xG := curve.Point.Generator().Mul(x) fmt.Printf("a=%d\n", val1) fmt.Printf("=== BLS12 377 G1:\n\nG=%x\n\nxG=%x\n\nxG(x,y)=%x\n", G.ToAffineCompressed(), xG.ToAffineCompressed(), xG.ToAffineUncompressed()) fmt.Printf(" x=%x, y=%x\n \n", xG.ToAffineUncompressed()[0:49], xG.ToAffineUncompressed()[49:]) curve = curves.BLS12377G2() x = curve.Scalar.New(val1) G = curve.Point.Generator() xG = curve.Point.Generator().Mul(x) fmt.Printf("=== BLS12 377 G2:\n\nG=%x\n\nxG=%x\n\nxG(x,y)=%x\n", G.ToAffineCompressed(), xG.ToAffineCompressed(), xG.ToAffineUncompressed()) fmt.Printf("\nx1=%x\nx2=%x\n \n", xG.ToAffineUncompressed()[0:48], xG.ToAffineUncompressed()[48:96]) fmt.Printf("y1=%x\ny2=%x\n \n", xG.ToAffineUncompressed()[96:144], xG.ToAffineUncompressed()[144:]) curve = curves.BLS12381G1() x = curve.Scalar.New(val1) G = curve.Point.Generator() xG = curve.Point.Generator().Mul(x) fmt.Printf("=== BLS12 381 G1:\n\nG=%x\n\nxG=%x\n\nxG(x,y)=%x\n", G.ToAffineCompressed(), xG.ToAffineCompressed(), xG.ToAffineUncompressed()) fmt.Printf("x=%x\ny=%x\n \n", xG.ToAffineUncompressed()[0:48], xG.ToAffineUncompressed()[48:]) curve = curves.BLS12381G2() x = curve.Scalar.New(val1) G = curve.Point.Generator() xG = curve.Point.Generator().Mul(x) fmt.Printf("=== BLS12 381 G2:\n\nG=%x\n\nxG=%x\n\nxG(x,y)=%x\n", G.ToAffineCompressed(), xG.ToAffineCompressed(), xG.ToAffineUncompressed()) fmt.Printf("\nx1=%x\nx2=%x\n \n", xG.ToAffineUncompressed()[0:48], xG.ToAffineUncompressed()[48:96]) fmt.Printf("y1=%x\ny2=%x\n \n", xG.ToAffineUncompressed()[96:144], xG.ToAffineUncompressed()[144:]) }
A sample run:
a=1 === BLS12 377 G1: G=a08848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef xG=a08848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef xG(x,y)=008848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef01914a69c5102eff1f674f5d30afeec4bd7fb348ca3e52d96d182ad44fb82305c2fe3d3634a9591afd82de55559c8ea6 x=008848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef01, y=914a69c5102eff1f674f5d30afeec4bd7fb348ca3e52d96d182ad44fb82305c2fe3d3634a9591afd82de55559c8ea6 === BLS12 377 G2: G=a0ea6040e700403170dc5a51b1b140d5532777ee6651cecbe7223ece0799c9de5cf89984bff76fe6b26bfefa6ea16afe018480be71c785fec89630a2a3841d01c565f071203e50317ea501f557db6b9b71889f52bb53540274e3e48f7c005196 xG=a0ea6040e700403170dc5a51b1b140d5532777ee6651cecbe7223ece0799c9de5cf89984bff76fe6b26bfefa6ea16afe018480be71c785fec89630a2a3841d01c565f071203e50317ea501f557db6b9b71889f52bb53540274e3e48f7c005196 xG(x,y)=00ea6040e700403170dc5a51b1b140d5532777ee6651cecbe7223ece0799c9de5cf89984bff76fe6b26bfefa6ea16afe018480be71c785fec89630a2a3841d01c565f071203e50317ea501f557db6b9b71889f52bb53540274e3e48f7c00519600f8169fd28355189e549da3151a70aa61ef11ac3d591bf12463b01acee304c24279b83f5e52270bd9a1cdd185eb8f9300690d665d446f7bd960736bcbb2efb4de03ed7274b49a58e458c282f832d204f2cf88886d8c7c2ef094094409fd4ddf x1=00ea6040e700403170dc5a51b1b140d5532777ee6651cecbe7223ece0799c9de5cf89984bff76fe6b26bfefa6ea16afe x2=018480be71c785fec89630a2a3841d01c565f071203e50317ea501f557db6b9b71889f52bb53540274e3e48f7c005196 y1=00f8169fd28355189e549da3151a70aa61ef11ac3d591bf12463b01acee304c24279b83f5e52270bd9a1cdd185eb8f93 y2=00690d665d446f7bd960736bcbb2efb4de03ed7274b49a58e458c282f832d204f2cf88886d8c7c2ef094094409fd4ddf === BLS12 381 G1: G=97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb xG=97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb xG(x,y)=17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 x=17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb y=08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 === BLS12 381 G2: G=93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 xG=93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 xG(x,y)=13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 x1=13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e x2=024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 y1=0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be y2=0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801