Skip to main content

Test Vectors

Official test vectors for validating BLS12-381 implementations.

Source

Ethereum Consensus Specs - BLS Test Vectors

Point Encoding

G1 Generator (Uncompressed)

x: 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
y: 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1

G2 Generator (Uncompressed)

x.c0: 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
x.c1: 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e
y.c0: 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801
y.c1: 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be

Signature Verification

Test Vector 1

Private Key:
0x0000000000000000000000000000000000000000000000000000000000000001
Public Key (G2):
0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1
Message:
0x0000000000000000000000000000000000000000000000000000000000000000
Signature (G1):
0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55

Hash-to-Curve

Test vectors for hash-to-G1 and hash-to-G2 (RFC 9380).

Hash-to-G1

Domain Separation Tag:
"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_"
Input Message:
"abc"
Expected G1 Point:
x: 0x...
y: 0x...

Pairing

Test Vector: e(G1, G2) ≠ 1

const g1 = G1_GENERATOR;
const g2 = G2_GENERATOR;

const result = await pairing(g1, g2);
// Should NOT equal identity in GT

Test Vector: e(aG1, bG2) = e(G1, G2)^(ab)

const a = 5;
const b = 7;
const ab = 35;

const e1 = await pairing(mul(G1_GEN, a), mul(G2_GEN, b));
const e2 = pow(await pairing(G1_GEN, G2_GEN), ab);

// e1 should equal e2

Edge Cases

Point at Infinity

const infinity_g1 = new Uint8Array(128); // All zeros
const infinity_g2 = new Uint8Array(256); // All zeros

// Adding infinity should return the other point
const result = await g1Add(point, infinity_g1);
// result === point

Subgroup Checks

Invalid G2 point (on curve but not in prime-order subgroup):
x.c0: 0x...
x.c1: 0x...
y.c0: 0x...
y.c1: 0x...

// Should be rejected by g2Add/g2Mul

Aggregation

Aggregate Signature Test

const privkeys = [1, 2, 3, 4, 5];
const message = hash("test message");

const signatures = privkeys.map(sk => sign(sk, message));
const aggregated = await aggregateSignatures(signatures);

const pubkeys = privkeys.map(sk => derivePublicKey(sk));
const aggregatedPubkey = await aggregatePublicKeys(pubkeys);

const isValid = await verify(aggregated, aggregatedPubkey, message);
// Should be true

References