Our checkCompressedPoint stays: it matches the Go reference on every edge case, is 1.3 KB gzip and adds no runtime dependency. Its assurance now comes from a contrast test run on every test pass: - 41 frozen edge-case encodings with the Go reference verdict (drand crypto KeyGroup over kyber-bls12381 and kilic/bls12-381, as profile.Validate uses it), reproducible with scripts/bls12381-go-verdicts.go; - the audited @noble/curves 2.4.0 on the same edge cases and on a fixed-seed corpus of valid points, negations, bit flips, random x and G1 points on the curve outside the subgroup. Breaking the G1 or the G2 subgroup check makes the test fail. @noble/curves 2.4.0 is a development dependency only; a test fails if anything that is not a test imports it, and the build contains none of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>main
parent
5f8c8c8031
commit
c13377af2b
@ -0,0 +1,63 @@
|
||||
//go:build ignore
|
||||
|
||||
// Prints the Go reference verdict for every encoding in
|
||||
// src/lib/dkc/testing/bls12381-vectors.json, as a JSON object from label to
|
||||
// "point", "identity" or "invalid". The decoding is the one profile.Validate
|
||||
// uses: the KeyGroup of the drand crypto scheme (G1 for the unchained scheme,
|
||||
// G2 for bls-unchained-g1-rfc9380, Quicknet), whose UnmarshalBinary is
|
||||
// kyber-bls12381 over kilic/bls12-381 FromCompressed, and Equal(Null()) for the
|
||||
// identity. Run it from a scratch module that requires the reference
|
||||
// implementation (replace g.activething.com/go/DateKeys => ../datekeys-go and
|
||||
// GOFLAGS=-mod=mod), passing the path of the vectors file:
|
||||
//
|
||||
// go run bls12381-go-verdicts.go path/to/bls12381-vectors.json
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/drand/drand/v2/crypto"
|
||||
)
|
||||
|
||||
func main() {
|
||||
raw, err := os.ReadFile(os.Args[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var file struct {
|
||||
Vectors []struct{ Label, Group, Hex string }
|
||||
}
|
||||
if err := json.Unmarshal(raw, &file); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
g1, _ := crypto.GetSchemeByID(crypto.UnchainedSchemeID)
|
||||
g2, _ := crypto.GetSchemeByID(crypto.SigsOnG1ID)
|
||||
out := map[string]string{}
|
||||
for _, v := range file.Vectors {
|
||||
s := g1
|
||||
if v.Group == "G2" {
|
||||
s = g2
|
||||
}
|
||||
b, err := hex.DecodeString(v.Hex)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
k := s.KeyGroup.Point()
|
||||
switch {
|
||||
case k.UnmarshalBinary(b) != nil:
|
||||
out[v.Label] = "invalid"
|
||||
case k.Equal(k.Null()):
|
||||
out[v.Label] = "identity"
|
||||
default:
|
||||
out[v.Label] = "point"
|
||||
}
|
||||
}
|
||||
j, err := json.MarshalIndent(out, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(j))
|
||||
}
|
||||
@ -0,0 +1,177 @@
|
||||
// Contrast test of bls12381.ts against an audited implementation.
|
||||
//
|
||||
// checkCompressedPoint is our own code. It is kept because it matches the Go
|
||||
// reference on every edge case, is 1.3 KB gzip and adds no runtime
|
||||
// dependency. Its assurance comes from this file: on every run it is compared
|
||||
// with the Go reference on frozen edge cases and with @noble/curves 2.4.0
|
||||
// (Cure53 2024; Trail of Bits 2026 review, whose BLS findings were fixed in
|
||||
// 2.3.0) on a deterministic corpus. noble is a development dependency only:
|
||||
// the last test fails if anything outside a test imports it, so it never
|
||||
// reaches the site.
|
||||
|
||||
import { bls12_381 } from '@noble/curves/bls12-381.js';
|
||||
import { readdirSync, readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { checkCompressedPoint, type Group } from './bls12381.ts';
|
||||
|
||||
type Verdict = 'point' | 'identity' | 'invalid';
|
||||
|
||||
const SIZE: Record<Group, number> = { G1: 48, G2: 96 };
|
||||
const P = bls12_381.fields.Fp.ORDER;
|
||||
const R = bls12_381.fields.Fr.ORDER;
|
||||
|
||||
// The audited oracle. noble also decodes uncompressed encodings, which the
|
||||
// protocol never uses for a public key, so the length is checked first, as
|
||||
// the Go reference does; with that check noble >= 2.3.0 matches Go on every
|
||||
// frozen edge case.
|
||||
function noble(group: Group, bytes: Uint8Array): Verdict {
|
||||
if (bytes.length !== SIZE[group]) return 'invalid';
|
||||
try {
|
||||
const point = bls12_381[group].Point.fromBytes(bytes);
|
||||
point.assertValidity();
|
||||
return point.is0() ? 'identity' : 'point';
|
||||
} catch {
|
||||
return 'invalid';
|
||||
}
|
||||
}
|
||||
|
||||
const hex = (s: string): Uint8Array => Uint8Array.from(s.match(/../g) ?? [], (b) => parseInt(b, 16));
|
||||
const toHex = (b: Uint8Array): string => Array.from(b, (v) => v.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
// splitmix64: a fixed-seed generator, so every run checks the same corpus.
|
||||
function rng(seed: bigint): (n: number) => Uint8Array {
|
||||
let state = seed;
|
||||
const M = (1n << 64n) - 1n;
|
||||
const next = (): bigint => {
|
||||
state = (state + 0x9e3779b97f4a7c15n) & M;
|
||||
let z = state;
|
||||
z = ((z ^ (z >> 30n)) * 0xbf58476d1ce4e5b9n) & M;
|
||||
z = ((z ^ (z >> 27n)) * 0x94d049bb133111ebn) & M;
|
||||
return z ^ (z >> 31n);
|
||||
};
|
||||
return (n) => {
|
||||
const out = new Uint8Array(n);
|
||||
for (let i = 0; i < n; i += 8) {
|
||||
let w = next();
|
||||
for (let j = 0; j < 8 && i + j < n; j++, w >>= 8n) out[i + j] = Number(w & 0xffn);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
}
|
||||
|
||||
const big = (b: Uint8Array): bigint => b.reduce((acc, v) => (acc << 8n) | BigInt(v), 0n);
|
||||
|
||||
function be48(x: bigint): Uint8Array {
|
||||
const out = new Uint8Array(48);
|
||||
for (let i = 47; i >= 0; i--, x >>= 8n) out[i] = Number(x & 0xffn);
|
||||
return out;
|
||||
}
|
||||
|
||||
function modPow(base: bigint, exp: bigint): bigint {
|
||||
let result = 1n;
|
||||
let b = base % P;
|
||||
for (let e = exp; e > 0n; e >>= 1n) {
|
||||
if (e & 1n) result = (result * b) % P;
|
||||
b = (b * b) % P;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// A G1 encoding of a point on y^2 = x^3 + 4 chosen from a random x: the
|
||||
// cofactor is about 2^126, so it is outside the prime-order subgroup.
|
||||
function onCurveOutsideSubgroupG1(random: (n: number) => Uint8Array): Uint8Array {
|
||||
for (;;) {
|
||||
const x = big(random(48)) % P;
|
||||
const rhs = (x * x * x + 4n) % P;
|
||||
if (modPow(rhs, (P - 1n) / 2n) !== 1n) continue;
|
||||
const y = modPow(rhs, (P + 1n) / 4n);
|
||||
const out = be48(x);
|
||||
out[0]! |= 0x80 | (y > (P - 1n) / 2n ? 0x20 : 0);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
interface Case {
|
||||
label: string;
|
||||
group: Group;
|
||||
bytes: Uint8Array;
|
||||
}
|
||||
|
||||
function corpus(): Case[] {
|
||||
const random = rng(20260926n);
|
||||
const cases: Case[] = [];
|
||||
const scalar = (): bigint => (big(random(40)) % (R - 1n)) + 1n;
|
||||
for (const [group, valid, other] of [
|
||||
['G1', 60, 120],
|
||||
['G2', 20, 40],
|
||||
] as const) {
|
||||
const G = bls12_381[group].Point;
|
||||
for (let i = 0; i < valid; i++) {
|
||||
const bytes = G.BASE.multiply(scalar()).toBytes(true);
|
||||
cases.push({ label: `${group} valid ${i}`, group, bytes });
|
||||
const negated = new Uint8Array(bytes);
|
||||
negated[0]! ^= 0x20;
|
||||
cases.push({ label: `${group} valid ${i} negated`, group, bytes: negated });
|
||||
const flipped = new Uint8Array(bytes);
|
||||
const bit = Number(big(random(2)) % BigInt(SIZE[group] * 8 - 3)) + 3;
|
||||
flipped[bit >> 3]! ^= 0x80 >> (bit & 7);
|
||||
cases.push({ label: `${group} valid ${i} bit ${bit} flipped`, group, bytes: flipped });
|
||||
}
|
||||
for (let i = 0; i < other; i++) {
|
||||
const bytes = random(SIZE[group]);
|
||||
bytes[0] = 0x80 | (bytes[0]! & 0x3f);
|
||||
cases.push({ label: `${group} random x ${i}`, group, bytes });
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < 60; i++) {
|
||||
cases.push({ label: `G1 on the curve, outside the subgroup ${i}`, group: 'G1', bytes: onCurveOutsideSubgroupG1(random) });
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
describe('bls12381.ts against the Go reference and @noble/curves 2.4.0', () => {
|
||||
const file = JSON.parse(readFileSync(new URL('./testing/bls12381-vectors.json', import.meta.url), 'utf8')) as {
|
||||
vectors: { label: string; group: Group; hex: string; go: Verdict }[];
|
||||
};
|
||||
|
||||
it('matches the Go reference on every frozen edge case', () => {
|
||||
expect(file.vectors.length).toBe(41);
|
||||
for (const v of file.vectors) expect(checkCompressedPoint(v.group, hex(v.hex)), v.label).toBe(v.go);
|
||||
});
|
||||
|
||||
it('noble agrees with the Go reference on every frozen edge case', () => {
|
||||
for (const v of file.vectors) expect(noble(v.group, hex(v.hex)), v.label).toBe(v.go);
|
||||
});
|
||||
|
||||
it('matches noble on a deterministic corpus', { timeout: 120_000 }, () => {
|
||||
const cases = corpus();
|
||||
const seen = { point: 0, identity: 0, invalid: 0 };
|
||||
for (const c of cases) {
|
||||
const want = noble(c.group, c.bytes);
|
||||
expect(checkCompressedPoint(c.group, c.bytes), `${c.label}: ${toHex(c.bytes)}`).toBe(want);
|
||||
seen[want]++;
|
||||
}
|
||||
// Both classes that matter are exercised: valid points (and their
|
||||
// negations) and encodings that decode to no subgroup point.
|
||||
expect(seen.point).toBeGreaterThanOrEqual(160);
|
||||
expect(seen.invalid).toBeGreaterThanOrEqual(200);
|
||||
});
|
||||
|
||||
it('only tests import @noble/curves', () => {
|
||||
const root = fileURLToPath(new URL('../../', import.meta.url));
|
||||
const offenders: string[] = [];
|
||||
const walk = (dir: string): void => {
|
||||
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
||||
const path = join(dir, entry.name);
|
||||
if (entry.isDirectory()) walk(path);
|
||||
else if (/\.(ts|js|svelte)$/.test(entry.name) && !/\.test\.ts$/.test(entry.name)) {
|
||||
if (readFileSync(path, 'utf8').includes('@noble/')) offenders.push(path);
|
||||
}
|
||||
}
|
||||
};
|
||||
walk(root);
|
||||
expect(offenders).toEqual([]);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,251 @@
|
||||
{
|
||||
"description": "Edge-case compressed BLS12-381 encodings (valid points, sort-bit flips, identity encodings with stray flags or payload, missing compression flag, wrong lengths, uncompressed forms, x + p, points on the curve outside the subgroup) with the verdict of the Go reference: the KeyGroup of the drand/drand/v2 crypto schemes (G1 for the unchained scheme, G2 for bls-unchained-g1-rfc9380), backed by github.com/drand/kyber-bls12381 v0.3.4 over github.com/kilic/bls12-381 v0.1.0, as profile.Validate uses it. Encodings generated with @noble/curves 2.4.0 arithmetic; verdicts from scripts/bls12381-go-verdicts.go.",
|
||||
"vectors": [
|
||||
{
|
||||
"label": "g1_generator",
|
||||
"group": "G1",
|
||||
"hex": "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g1_7G",
|
||||
"group": "G1",
|
||||
"hex": "b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g2_generator",
|
||||
"group": "G2",
|
||||
"hex": "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g2_quicknet_pk",
|
||||
"group": "G2",
|
||||
"hex": "83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g2_7G",
|
||||
"group": "G2",
|
||||
"hex": "8d0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c8049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g1_gen_sort_flipped",
|
||||
"group": "G1",
|
||||
"hex": "b7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g2_gen_sort_flipped",
|
||||
"group": "G2",
|
||||
"hex": "b3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
|
||||
"go": "point"
|
||||
},
|
||||
{
|
||||
"label": "g1_identity_c0",
|
||||
"group": "G1",
|
||||
"hex": "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "identity"
|
||||
},
|
||||
{
|
||||
"label": "g1_identity_sort_e0",
|
||||
"group": "G1",
|
||||
"hex": "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_identity_payload_1",
|
||||
"group": "G1",
|
||||
"hex": "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_identity_payload_p_low",
|
||||
"group": "G1",
|
||||
"hex": "da0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_identity_payload_p_first",
|
||||
"group": "G1",
|
||||
"hex": "da0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_infinity_without_compression_40",
|
||||
"group": "G1",
|
||||
"hex": "400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_all_zero",
|
||||
"group": "G1",
|
||||
"hex": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_compressed_x0",
|
||||
"group": "G1",
|
||||
"hex": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_identity_c0",
|
||||
"group": "G2",
|
||||
"hex": "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "identity"
|
||||
},
|
||||
{
|
||||
"label": "g2_identity_sort_e0",
|
||||
"group": "G2",
|
||||
"hex": "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_identity_payload_1",
|
||||
"group": "G2",
|
||||
"hex": "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_identity_payload_p_low",
|
||||
"group": "G2",
|
||||
"hex": "c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_identity_payload_p_first",
|
||||
"group": "G2",
|
||||
"hex": "da0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_infinity_without_compression_40",
|
||||
"group": "G2",
|
||||
"hex": "400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_all_zero",
|
||||
"group": "G2",
|
||||
"hex": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_compressed_x0",
|
||||
"group": "G2",
|
||||
"hex": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_gen_no_compression_flag",
|
||||
"group": "G1",
|
||||
"hex": "17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_gen_no_compression_flag",
|
||||
"group": "G2",
|
||||
"hex": "13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_len47",
|
||||
"group": "G1",
|
||||
"hex": "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_len95",
|
||||
"group": "G2",
|
||||
"hex": "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bd",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_uncompressed_96",
|
||||
"group": "G1",
|
||||
"hex": "17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_uncompressed_192",
|
||||
"group": "G2",
|
||||
"hex": "13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_noncanonical_x_plus_p",
|
||||
"group": "G1",
|
||||
"hex": "bf73ddd4c9cd4de0d32470a193f4f1e3fb9926b584ad13e4aac0ffabba099c4f013b75ba40707c427d998c5529beb9f9",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_noncanonical_c1_plus_p",
|
||||
"group": "G2",
|
||||
"hex": "9afc95623e5b8ebb7e4582fca3d718e9820e7ee8b4a85d4644490e50e7c366c1181c96c49af5a770a89c7dc641a83f810411a5de6730ffece671a9f21d65028cc0f1102378de124562cb1ff49db6f004fcd14d683024b0548eff3d1468df2688",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_noncanonical_c0_plus_p",
|
||||
"group": "G2",
|
||||
"hex": "80fb837804dba8213329db46608b6c121d973363c1234a86dd183baff112709cf97096c5e9a1a770ee9d7dc641a894d61e12b7c8a0b0e687318d51a860b0af6425685ba86c632504c9fbf2959467e6291b7d4d66e178b05448fe3d1468ded133",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_x_equals_p",
|
||||
"group": "G1",
|
||||
"hex": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_c1_equals_p",
|
||||
"group": "G2",
|
||||
"hex": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_c0_equals_p",
|
||||
"group": "G2",
|
||||
"hex": "8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_not_on_curve",
|
||||
"group": "G1",
|
||||
"hex": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_on_curve_not_in_subgroup",
|
||||
"group": "G1",
|
||||
"hex": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_not_on_curve",
|
||||
"group": "G2",
|
||||
"hex": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_on_curve_not_in_subgroup",
|
||||
"group": "G2",
|
||||
"hex": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g1_x_all_ones",
|
||||
"group": "G1",
|
||||
"hex": "9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"go": "invalid"
|
||||
},
|
||||
{
|
||||
"label": "g2_x_all_ones",
|
||||
"group": "G2",
|
||||
"hex": "9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"go": "invalid"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in new issue