2022-12-28 09:32:27 +03:00
|
|
|
import { deepStrictEqual } from 'assert';
|
2023-01-13 18:00:13 +03:00
|
|
|
import { describe, should } from 'micro-should';
|
2022-12-28 09:32:27 +03:00
|
|
|
import { bytesToHex } from '@noble/hashes/utils';
|
|
|
|
// Generic tests for all curves in package
|
|
|
|
import { sha256 } from '@noble/hashes/sha256';
|
|
|
|
import { sha512 } from '@noble/hashes/sha512';
|
2022-12-31 09:47:26 +03:00
|
|
|
import { shake128, shake256 } from '@noble/hashes/sha3';
|
2023-01-21 21:02:45 +03:00
|
|
|
import * as secp256r1 from '../lib/esm/p256.js';
|
|
|
|
import * as secp384r1 from '../lib/esm/p384.js';
|
|
|
|
import * as secp521r1 from '../lib/esm/p521.js';
|
|
|
|
import * as ed25519 from '../lib/esm/ed25519.js';
|
|
|
|
import * as ed448 from '../lib/esm/ed448.js';
|
|
|
|
import * as secp256k1 from '../lib/esm/secp256k1.js';
|
2022-12-28 09:32:27 +03:00
|
|
|
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
2022-12-31 09:47:26 +03:00
|
|
|
import {
|
|
|
|
stringToBytes,
|
|
|
|
expand_message_xmd,
|
|
|
|
expand_message_xof,
|
|
|
|
} from '../lib/esm/abstract/hash-to-curve.js';
|
|
|
|
// XMD
|
2022-12-28 09:32:27 +03:00
|
|
|
import { default as xmd_sha256_38 } from './hash-to-curve/expand_message_xmd_SHA256_38.json' assert { type: 'json' };
|
|
|
|
import { default as xmd_sha256_256 } from './hash-to-curve/expand_message_xmd_SHA256_256.json' assert { type: 'json' };
|
|
|
|
import { default as xmd_sha512_38 } from './hash-to-curve/expand_message_xmd_SHA512_38.json' assert { type: 'json' };
|
2022-12-31 09:47:26 +03:00
|
|
|
// XOF
|
|
|
|
import { default as xof_shake128_36 } from './hash-to-curve/expand_message_xof_SHAKE128_36.json' assert { type: 'json' };
|
|
|
|
import { default as xof_shake128_256 } from './hash-to-curve/expand_message_xof_SHAKE128_256.json' assert { type: 'json' };
|
|
|
|
import { default as xof_shake256_36 } from './hash-to-curve/expand_message_xof_SHAKE256_36.json' assert { type: 'json' };
|
2022-12-28 09:32:27 +03:00
|
|
|
// P256
|
|
|
|
import { default as p256_ro } from './hash-to-curve/P256_XMD:SHA-256_SSWU_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as p256_nu } from './hash-to-curve/P256_XMD:SHA-256_SSWU_NU_.json' assert { type: 'json' };
|
|
|
|
// P384
|
|
|
|
import { default as p384_ro } from './hash-to-curve/P384_XMD:SHA-384_SSWU_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as p384_nu } from './hash-to-curve/P384_XMD:SHA-384_SSWU_NU_.json' assert { type: 'json' };
|
|
|
|
// P521
|
|
|
|
import { default as p521_ro } from './hash-to-curve/P521_XMD:SHA-512_SSWU_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as p521_nu } from './hash-to-curve/P521_XMD:SHA-512_SSWU_NU_.json' assert { type: 'json' };
|
|
|
|
// secp256k1
|
|
|
|
import { default as secp256k1_ro } from './hash-to-curve/secp256k1_XMD:SHA-256_SSWU_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as secp256k1_nu } from './hash-to-curve/secp256k1_XMD:SHA-256_SSWU_NU_.json' assert { type: 'json' };
|
|
|
|
// bls-G1
|
|
|
|
import { default as g1_ro } from './hash-to-curve/BLS12381G1_XMD:SHA-256_SSWU_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as g1_nu } from './hash-to-curve/BLS12381G1_XMD:SHA-256_SSWU_NU_.json' assert { type: 'json' };
|
|
|
|
// bls-G2
|
|
|
|
import { default as g2_ro } from './hash-to-curve/BLS12381G2_XMD:SHA-256_SSWU_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as g2_nu } from './hash-to-curve/BLS12381G2_XMD:SHA-256_SSWU_NU_.json' assert { type: 'json' };
|
|
|
|
// ed25519
|
|
|
|
import { default as ed25519_ro } from './hash-to-curve/edwards25519_XMD:SHA-512_ELL2_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as ed25519_nu } from './hash-to-curve/edwards25519_XMD:SHA-512_ELL2_NU_.json' assert { type: 'json' };
|
|
|
|
// ed448
|
|
|
|
import { default as ed448_ro } from './hash-to-curve/edwards448_XOF:SHAKE256_ELL2_RO_.json' assert { type: 'json' };
|
|
|
|
import { default as ed448_nu } from './hash-to-curve/edwards448_XOF:SHAKE256_ELL2_NU_.json' assert { type: 'json' };
|
|
|
|
|
|
|
|
function testExpandXMD(hash, vectors) {
|
2023-01-13 18:00:13 +03:00
|
|
|
describe(`${vectors.hash}/${vectors.DST.length}`, () => {
|
|
|
|
for (let i = 0; i < vectors.tests.length; i++) {
|
|
|
|
const t = vectors.tests[i];
|
|
|
|
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
|
|
|
const p = expand_message_xmd(
|
|
|
|
stringToBytes(t.msg),
|
|
|
|
stringToBytes(vectors.DST),
|
|
|
|
t.len_in_bytes,
|
|
|
|
hash
|
|
|
|
);
|
|
|
|
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2022-12-28 09:32:27 +03:00
|
|
|
}
|
|
|
|
|
2023-01-13 18:00:13 +03:00
|
|
|
describe('expand_message_xmd', () => {
|
|
|
|
testExpandXMD(sha256, xmd_sha256_38);
|
|
|
|
testExpandXMD(sha256, xmd_sha256_256);
|
|
|
|
testExpandXMD(sha512, xmd_sha512_38);
|
|
|
|
});
|
2022-12-28 09:32:27 +03:00
|
|
|
|
2022-12-31 09:47:26 +03:00
|
|
|
function testExpandXOF(hash, vectors) {
|
2023-01-13 18:00:13 +03:00
|
|
|
describe(`${vectors.hash}/${vectors.DST.length}`, () => {
|
|
|
|
for (let i = 0; i < vectors.tests.length; i++) {
|
|
|
|
const t = vectors.tests[i];
|
|
|
|
should(`${i}`, () => {
|
|
|
|
const p = expand_message_xof(
|
|
|
|
stringToBytes(t.msg),
|
|
|
|
stringToBytes(vectors.DST),
|
|
|
|
+t.len_in_bytes,
|
|
|
|
vectors.k,
|
|
|
|
hash
|
|
|
|
);
|
|
|
|
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2022-12-31 09:47:26 +03:00
|
|
|
}
|
|
|
|
|
2023-01-13 18:00:13 +03:00
|
|
|
describe('expand_message_xof', () => {
|
|
|
|
testExpandXOF(shake128, xof_shake128_36);
|
|
|
|
testExpandXOF(shake128, xof_shake128_256);
|
|
|
|
testExpandXOF(shake256, xof_shake256_36);
|
|
|
|
});
|
2022-12-31 09:47:26 +03:00
|
|
|
|
2022-12-28 09:32:27 +03:00
|
|
|
function stringToFp(s) {
|
|
|
|
// bls-G2 support
|
|
|
|
if (s.includes(',')) {
|
|
|
|
const [c0, c1] = s.split(',').map(BigInt);
|
|
|
|
return { c0, c1 };
|
|
|
|
}
|
|
|
|
return BigInt(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testCurve(curve, ro, nu) {
|
2023-01-13 18:00:13 +03:00
|
|
|
describe(`${ro.curve}/${ro.ciphersuite}`, () => {
|
|
|
|
for (let i = 0; i < ro.vectors.length; i++) {
|
|
|
|
const t = ro.vectors[i];
|
|
|
|
should(`(${i})`, () => {
|
2023-01-21 21:02:45 +03:00
|
|
|
const p = curve.hashToCurve(stringToBytes(t.msg), {
|
2023-01-13 18:00:13 +03:00
|
|
|
DST: ro.dst,
|
|
|
|
});
|
|
|
|
deepStrictEqual(p.x, stringToFp(t.P.x), 'Px');
|
|
|
|
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
2022-12-28 09:32:27 +03:00
|
|
|
});
|
2023-01-13 18:00:13 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
describe(`${nu.curve}/${nu.ciphersuite}`, () => {
|
|
|
|
for (let i = 0; i < nu.vectors.length; i++) {
|
|
|
|
const t = nu.vectors[i];
|
|
|
|
should(`(${i})`, () => {
|
2023-01-21 21:02:45 +03:00
|
|
|
const p = curve.encodeToCurve(stringToBytes(t.msg), {
|
2023-01-13 18:00:13 +03:00
|
|
|
DST: nu.dst,
|
|
|
|
});
|
|
|
|
deepStrictEqual(p.x, stringToFp(t.P.x), 'Px');
|
|
|
|
deepStrictEqual(p.y, stringToFp(t.P.y), 'Py');
|
2022-12-28 09:32:27 +03:00
|
|
|
});
|
2023-01-13 18:00:13 +03:00
|
|
|
}
|
|
|
|
});
|
2022-12-28 09:32:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
testCurve(secp256r1, p256_ro, p256_nu);
|
|
|
|
testCurve(secp384r1, p384_ro, p384_nu);
|
|
|
|
testCurve(secp521r1, p521_ro, p521_nu);
|
|
|
|
// TODO: remove same tests from bls12
|
2023-01-21 21:02:45 +03:00
|
|
|
testCurve(bls12_381.hashToCurve.G1, g1_ro, g1_nu);
|
|
|
|
testCurve(bls12_381.hashToCurve.G2, g2_ro, g2_nu);
|
2022-12-28 09:32:27 +03:00
|
|
|
testCurve(secp256k1, secp256k1_ro, secp256k1_nu);
|
2022-12-31 09:47:26 +03:00
|
|
|
testCurve(ed25519, ed25519_ro, ed25519_nu);
|
|
|
|
testCurve(ed448, ed448_ro, ed448_nu);
|
2022-12-28 09:32:27 +03:00
|
|
|
|
|
|
|
// ESM is broken.
|
|
|
|
import url from 'url';
|
|
|
|
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
|
|
|
should.run();
|
|
|
|
}
|