Add ed448, wycheproof vectors

This commit is contained in:
Paul Miller 2022-12-09 20:02:58 +00:00
parent 211c887a57
commit 1ed861dbad
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
29 changed files with 17450 additions and 143 deletions

@ -0,0 +1,123 @@
import * as bench from 'micro-bmark';
const { run, mark } = bench; // or bench.mark
// Curves
import * as nist from '../lib/nist.js';
import * as ed from '../lib/ed.js';
// Others
import { hmac } from '@noble/hashes/hmac';
import { sha256 } from '@noble/hashes/sha256';
import { sha512 } from '@noble/hashes/sha512';
import * as noble_secp256k1 from '@noble/secp256k1';
import { concatBytes, hexToBytes } from '@noble/hashes/utils';
noble_secp256k1.utils.sha256Sync = (...msgs) =>
sha256
.create()
.update(concatBytes(...msgs))
.digest();
noble_secp256k1.utils.hmacSha256Sync = (key, ...msgs) =>
hmac
.create(sha256, key)
.update(concatBytes(...msgs))
.digest();
import * as noble_ed25519 from '@noble/ed25519';
nist.secp256k1.utils.precompute(8); // Not enabled by default?
ed.ed25519.utils.precompute(8);
ed.ed448.utils.precompute(8);
noble_ed25519.utils.sha512Sync = (...m) => sha512(concatBytes(...m));
noble_secp256k1.utils.precompute(8);
noble_ed25519.utils.precompute(8);
const wrapBuf = (arrayBuffer) => new Uint8Array(arrayBuffer);
const ONLY_NOBLE = process.argv[2] === 'noble';
// TODO: add more?
export const CURVES = {
secp256k1: {
data: () => {
const priv = 'f6fc7fd5acaf8603709160d203253d5cd17daa307483877ad811ec8411df56d2';
const pub = noble_secp256k1.getPublicKey(priv, false);
const msg = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
const sig = noble_secp256k1.signSync(msg, priv);
return { priv, pub, msg, sig };
},
getPublicKey: {
samples: 10000,
old: () =>
noble_secp256k1.getPublicKey(noble_secp256k1.utils.randomPrivateKey()),
noble: () => nist.secp256k1.getPublicKey(nist.secp256k1.utils.randomPrivateKey()),
},
sign: {
samples: 5000,
old: ({ msg, priv }) => noble_secp256k1.signSync(msg, priv),
noble: ({ msg, priv }) => nist.secp256k1.sign(msg, priv),
},
getSharedSecret: {
samples: 1000,
old: ({ pub, priv }) => noble_secp256k1.getSharedSecret(priv, pub),
noble: ({ pub, priv }) => nist.secp256k1.getSharedSecret(priv, pub),
},
},
ed25519: {
data: () => {
function to32Bytes(numOrStr) {
const hex = typeof numOrStr === 'string' ? numOrStr : numOrStr.toString(16);
return hexToBytes(hex.padStart(64, '0'));
}
const priv = to32Bytes(0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60n);
const pub = noble_ed25519.sync.getPublicKey(priv);
const msg = to32Bytes('deadbeefdeadbeefdeadbeefdeadbeefdeadbeef');
const sig = noble_ed25519.sync.sign(msg, priv);
return { pub, priv, msg, sig };
},
getPublicKey: {
samples: 10000,
old: () =>
noble_ed25519.sync.getPublicKey(noble_ed25519.utils.randomPrivateKey()),
noble: () => ed.ed25519.getPublicKey(ed.ed25519.utils.randomPrivateKey()),
'ed448': () => ed.ed448.getPublicKey(ed.ed448.utils.randomPrivateKey()),
},
sign: {
samples: 5000,
old: ({ msg, priv }) => noble_ed25519.sync.sign(msg, priv),
noble: ({ msg, priv }) => ed.ed25519.sign(msg, priv),
'ed448': () => ed.ed448.sign(ed.ed448.utils.randomPrivateKey(), ed.ed448.utils.randomPrivateKey()),
},
verify: {
samples: 1000,
old: ({ msg, pub, sig }) => noble_ed25519.sync.verify(sig, msg, pub),
noble: ({ msg, pub, sig }) => ed.ed25519.verify(sig, msg, pub),
},
},
};
const main = () =>
run(async () => {
for (const [name, curve] of Object.entries(CURVES)) {
console.log(`==== ${name} ====`);
const data = curve.data();
for (const [fnName, libs] of Object.entries(curve)) {
if (fnName === 'data') continue;
const samples = libs.samples;
console.log(` - ${fnName} (samples: ${samples})`);
for (const [lib, fn] of Object.entries(libs)) {
if (lib === 'samples') continue;
if (ONLY_NOBLE && lib !== 'noble') continue;
await mark(` ${lib}`, samples, () => fn(data));
}
}
}
// Log current RAM
bench.logMem();
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
main();
}

@ -0,0 +1,21 @@
{
"name": "benchmark",
"private": true,
"version": "0.1.0",
"description": "benchmarks",
"main": "index.js",
"type": "module",
"scripts": {
"bench": "node index.js"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"micro-bmark": "0.2.0"
},
"dependencies": {
"@noble/ed25519": "^1.7.1",
"@noble/secp256k1": "^1.7.0"
}
}

@ -13,14 +13,14 @@
"module": "index.js",
"types": "index.d.ts",
"dependencies": {
"@noble/curves": "~0.1.0",
"@noble/curves": "file:../",
"@noble/hashes": "1.1.4"
},
"devDependencies": {
"@scure/base": "~1.1.0",
"@scure/bip32": "^1.1.1",
"@scure/bip39": "^1.1.0",
"@types/node": "^18.11.3",
"@types/node": "18.11.3",
"fast-check": "3.0.0",
"micro-should": "0.2.0",
"prettier": "2.6.2",

196
curve-definitions/src/ed.ts Normal file

@ -0,0 +1,196 @@
import { sha512 } from '@noble/hashes/sha512';
import { shake256 } from '@noble/hashes/sha3';
import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils';
import { twistedEdwards } from '@noble/curves/twistede';
import { mod, pow2, isNegativeLE } from '@noble/curves/modular';
const ed25519P = BigInt(
'57896044618658097711785492504343953926634992332820282019728792003956564819949'
);
// √(-1) aka √(a) aka 2^((p-1)/4)
const ED25519_SQRT_M1 = BigInt(
'19681161376707505956807079304988542015446066515923890162744021073123829784752'
);
function ed25519_pow_2_252_3(x: bigint) {
const P = ed25519P;
const _1n = BigInt(1);
const _2n = BigInt(2);
const _5n = BigInt(5);
const _10n = BigInt(10);
const _20n = BigInt(20);
const _40n = BigInt(40);
const _80n = BigInt(80);
const x2 = (x * x) % P;
const b2 = (x2 * x) % P; // x^3, 11
const b4 = (pow2(b2, _2n, P) * b2) % P; // x^15, 1111
const b5 = (pow2(b4, _1n, P) * x) % P; // x^31
const b10 = (pow2(b5, _5n, P) * b5) % P;
const b20 = (pow2(b10, _10n, P) * b10) % P;
const b40 = (pow2(b20, _20n, P) * b20) % P;
const b80 = (pow2(b40, _40n, P) * b40) % P;
const b160 = (pow2(b80, _80n, P) * b80) % P;
const b240 = (pow2(b160, _80n, P) * b80) % P;
const b250 = (pow2(b240, _10n, P) * b10) % P;
const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P;
// ^ To pow to (p+3)/8, multiply it by x.
return { pow_p_5_8, b2 };
}
export const ed25519 = twistedEdwards({
// Param: a
a: BigInt(-1),
// Equal to -121665/121666 over finite field.
// Negative number is P - number, and division is invert(number, P)
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
// Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
P: ed25519P,
// Subgroup order: how many points ed25519 has
// 2n ** 252n + 27742317777372353535851937790883648493n;
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
// Cofactor
h: BigInt(8),
// Base point (x, y) aka generator point
Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
a24: BigInt('121665'),
scalarBits: 255,
hash: sha512,
randomBytes,
adjustScalarBytes: (bytes: Uint8Array): Uint8Array => {
// Section 5: For X25519, in order to decode 32 random bytes as an integer scalar,
// set the three least significant bits of the first byte
bytes[0] &= 248; // 0b1111_1000
// and the most significant bit of the last to zero,
bytes[31] &= 127; // 0b0111_1111
// set the second most significant bit of the last byte to 1
bytes[31] |= 64; // 0b0100_0000
return bytes;
},
// dom2
domain: (data: Uint8Array, ctx: Uint8Array, hflag: boolean) => {
if (ctx.length || hflag) throw new Error('Contexts/pre-hash are not supported');
// TODO: support for ph/ctx too?
return data;
},
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
// Constant-time, u/√v
uvRatio: (u: bigint, v: bigint): { isValid: boolean; value: bigint } => {
const P = ed25519P;
const v3 = mod(v * v * v, P); // v³
const v7 = mod(v3 * v3 * v, P); // v⁷
// (p+3)/8 and (p-5)/8
const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
let x = mod(u * v3 * pow, P); // (uv³)(uv⁷)^(p-5)/8
const vx2 = mod(v * x * x, P); // vx²
const root1 = x; // First root candidate
const root2 = mod(x * ED25519_SQRT_M1, P); // Second root candidate
const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root
const useRoot2 = vx2 === mod(-u, P); // If vx² = -u, set x <-- x * 2^((p-1)/4)
const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P); // There is no valid root, vx² = -u√(-1)
if (useRoot1) x = root1;
if (useRoot2 || noRoot) x = root2; // We return root2 anyway, for const-time
if (isNegativeLE(x, P)) x = mod(-x, P);
return { isValid: useRoot1 || useRoot2, value: x };
},
});
// https://www.rfc-editor.org/rfc/rfc8032.html says bitLength is 456
// https://www.rfc-editor.org/rfc/rfc7748 says bitLength is 448
// WTF?!
// So, if we looking at wycheproof:
// EdDSA: 456
// X448 (sharedkey stuff) is 448. Awesome!
const ed448P = BigInt(
'726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439'
);
// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
function ed448_pow_Pminus3div4(x: bigint): bigint {
const P = ed448P;
// x ** ((P - 3n)/4n) % P
// [223 of 1, 0, 222 of 1], almost same as secp!
const b2 = (x * x * x) % P;
const b3 = (b2 * b2 * x) % P;
const b6 = (pow2(b3, 3n, P) * b3) % P;
const b9 = (pow2(b6, 3n, P) * b3) % P;
const b11 = (pow2(b9, 2n, P) * b2) % P;
const b22 = (pow2(b11, 11n, P) * b11) % P;
const b44 = (pow2(b22, 22n, P) * b22) % P;
const b88 = (pow2(b44, 44n, P) * b44) % P;
const b176 = (pow2(b88, 88n, P) * b88) % P;
const b220 = (pow2(b176, 44n, P) * b44) % P;
const b222 = (pow2(b220, 2n, P) * b2) % P;
const b223 = (pow2(b222, 1n, P) * x) % P;
return (pow2(b223, 223n, P) * b222) % P;
}
export const ed448 = twistedEdwards({
// Param: a
a: BigInt(1),
// Equal to -39081 over finite field.
// Negative number is P - number
d: BigInt(
'726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'
),
// Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n
P: ed448P,
// Subgroup order: how many points ed448 has; 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
n: BigInt(
'181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'
),
nBitLength: 456,
// Cofactor
h: BigInt(4),
// Base point (x, y) aka generator point
Gx: BigInt(
'224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710'
),
Gy: BigInt(
'298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660'
),
// The constant a24 is (156326 - 2) / 4 = 39081 for curve448/X448.
a24: BigInt('39081'),
scalarBits: 448, // TODO: fix that
// SHAKE256(dom4(phflag,context)||x, 114)
hash: wrapConstructor(() => shake256.create({ dkLen: 114 })),
randomBytes,
adjustScalarBytes: (bytes: Uint8Array): Uint8Array => {
// Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most
// significant bit of the last byte to 1.
bytes[0] &= 252; // 0b11111100
// and the most significant bit of the last byte to 1.
bytes[55] |= 128; // 0b10000000
bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
return bytes;
},
// dom4
domain: (data: Uint8Array, ctx: Uint8Array, hflag: boolean) => {
if (ctx.length > 255) throw new Error(`Context is too big: ${ctx.length}`);
return concatBytes(utf8ToBytes('SigEd448'), new Uint8Array([hflag ? 1 : 0, ctx.length]), data);
},
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
// Constant-time, u/√v
uvRatio: (u: bigint, v: bigint): { isValid: boolean; value: bigint } => {
const P = ed448P;
// https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.3
// To compute the square root of (u/v), the first step is to compute the
// candidate root x = (u/v)^((p+1)/4). This can be done using the
// following trick, to use a single modular powering for both the
// inversion of v and the square root:
// (p+1)/4 3 (p-3)/4
// x = (u/v) = u v (u^5 v^3) (mod p)
const u2v = mod(u * u * v, P);
const u3v = mod(u2v * u, P); // u^2v
const u5v3 = mod(u3v * u2v * v, P); // u^5v^3
const root = ed448_pow_Pminus3div4(u5v3);
const x = mod(u3v * root, P);
// Verify that root is exists
const x2 = mod(x * x, P); // x^2
// If v * x^2 = u, the recovered x-coordinate is x. Otherwise, no
// square root exists, and the decoding fails.
return { isValid: mod(x2 * v, P) === u, value: x };
},
});

@ -3,9 +3,12 @@ import { hmac } from '@noble/hashes/hmac';
import { sha256 } from '@noble/hashes/sha256';
import { sha384, sha512 } from '@noble/hashes/sha512';
import { concatBytes, randomBytes } from '@noble/hashes/utils';
import { weierstrass, CHash } from '@noble/curves/shortw';
import { weierstrass, CurveType, CHash } from '@noble/curves/shortw';
import { mod, pow2 } from '@noble/curves/modular';
// TODO: ability to provide API for different default hash.
// Wychenproof can help us here & test multiple hashes.
function getHash(hash: CHash) {
return {
hash,
@ -13,82 +16,104 @@ function getHash(hash: CHash) {
randomBytes,
};
}
// Same API as @noble/hashes, with ability to create curve with custom hash
type CurveDef = Readonly<Omit<CurveType, 'hash' | 'hmac' | 'randomBytes'>>;
function createCurve(curveDef: CurveDef, defHash: CHash) {
const create = (hash: CHash) => weierstrass({ ...curveDef, ...getHash(hash) });
return Object.freeze({ ...create(defHash), create });
}
// https://www.secg.org/sec2-v2.pdf
// https://neuromancer.sk/std/secg/secp192r1
export const P192 = weierstrass({
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
// Field over which we'll do calculations. Verify with: 2n ** 192n - 2n ** 64n - 1n
P: BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff'),
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
// Base point (x, y) aka generator point
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
lowS: false,
// Default options
...getHash(sha256),
} as const);
export const P192 = createCurve(
{
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
// Field over which we'll do calculations. Verify with: 2n ** 192n - 2n ** 64n - 1n
P: BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff'),
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
// Base point (x, y) aka generator point
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
lowS: false,
} as const,
sha256
);
export const secp192r1 = P192;
// https://neuromancer.sk/std/nist/P-224
export const P224 = weierstrass({
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
// Field over which we'll do calculations. Verify with:
P: 2n ** 224n - 2n ** 96n + 1n,
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
// Base point (x, y) aka generator point
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
lowS: false,
// Default options
...getHash(sha256),
} as const);
export const P224 = createCurve(
{
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
// Field over which we'll do calculations. Verify with:
P: 2n ** 224n - 2n ** 96n + 1n,
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
// Base point (x, y) aka generator point
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
lowS: false,
} as const,
sha256 // TODO: replace with sha224 when new @noble/hashes released
);
export const secp224r1 = P224;
// https://neuromancer.sk/std/nist/P-256
export const P256 = weierstrass({
// Params: a, b
a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
// Field over which we'll do calculations. Verify with:
// 2n ** 224n * (2n ** 32n - 1n) + 2n ** 192n + 2n ** 96n - 1n,
P: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base point (x, y) aka generator point
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
lowS: false,
// Default options
...getHash(sha256),
} as const);
export const P256 = createCurve(
{
// Params: a, b
a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
// Field over which we'll do calculations. Verify with:
// 2n ** 224n * (2n ** 32n - 1n) + 2n ** 192n + 2n ** 96n - 1n,
P: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base point (x, y) aka generator point
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
lowS: false,
} as const,
sha256
);
export const secp256r1 = P256;
// https://neuromancer.sk/std/nist/P-384
// prettier-ignore
export const P384 = weierstrass({
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc'),
b: BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef'),
// Field over which we'll do calculations. Verify with:
// 2n ** 384n - 2n ** 128n - 2n ** 96n + 2n ** 32n - 1n
P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'),
// Curve order, total count of valid points in the field. Verify with:
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
// Base point (x, y) aka generator point
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),
Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
lowS: false,
// Default options
...getHash(sha384),
} as const);
export const P384 = createCurve(
{
// Params: a, b
a: BigInt(
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc'
),
b: BigInt(
'0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef'
),
// Field over which we'll do calculations. Verify with:
// 2n ** 384n - 2n ** 128n - 2n ** 96n + 2n ** 32n - 1n
P: BigInt(
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'
),
// Curve order, total count of valid points in the field. Verify with:
n: BigInt(
'0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'
),
// Base point (x, y) aka generator point
Gx: BigInt(
'0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'
),
Gy: BigInt(
'0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'
),
lowS: false,
} as const,
sha384
);
export const secp384r1 = P384;
// https://neuromancer.sk/std/nist/P-521
// prettier-ignore
export const P521 = weierstrass({
export const P521 = createCurve({
// Params: a, b
a: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc'),
b: BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'),
@ -101,9 +126,7 @@ export const P521 = weierstrass({
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
lowS: false,
// Default options
...getHash(sha512),
} as const);
} as const, sha512);
export const secp521r1 = P521;
/**
@ -120,71 +143,73 @@ const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd
const _1n = BigInt(1);
const _2n = BigInt(2);
const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b;
export const secp256k1 = weierstrass({
a: 0n,
b: 7n,
// Field over which we'll do calculations. Verify with:
// 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n
P: secp256k1P,
// Curve order, total count of valid points in the field. Verify with:
n: secp256k1N,
// Base point (x, y) aka generator point
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
...getHash(sha256),
// noble-secp256k1 compat
lowS: true,
// Used to calculate y - the square root of y².
// Exponentiates it to very big number (P+1)/4.
// We are unwrapping the loop because it's 2x faster.
// (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
// We are multiplying it bit-by-bit
sqrtMod: (x: bigint): bigint => {
const P = secp256k1P;
const _3n = BigInt(3);
const _6n = BigInt(6);
const _11n = BigInt(11);
const _22n = BigInt(22);
const _23n = BigInt(23);
const _44n = BigInt(44);
const _88n = BigInt(88);
const b2 = (x * x * x) % P; // x^3, 11
const b3 = (b2 * b2 * x) % P; // x^7
const b6 = (pow2(b3, _3n, P) * b3) % P;
const b9 = (pow2(b6, _3n, P) * b3) % P;
const b11 = (pow2(b9, _2n, P) * b2) % P;
const b22 = (pow2(b11, _11n, P) * b11) % P;
const b44 = (pow2(b22, _22n, P) * b22) % P;
const b88 = (pow2(b44, _44n, P) * b44) % P;
const b176 = (pow2(b88, _88n, P) * b88) % P;
const b220 = (pow2(b176, _44n, P) * b44) % P;
const b223 = (pow2(b220, _3n, P) * b3) % P;
const t1 = (pow2(b223, _23n, P) * b22) % P;
const t2 = (pow2(t1, _6n, P) * b2) % P;
return pow2(t2, _2n, P);
},
endo: {
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
splitScalar: (k: bigint) => {
const n = secp256k1N;
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
const b2 = a1;
const POW_2_128 = BigInt('0x100000000000000000000000000000000');
export const secp256k1 = createCurve(
{
a: 0n,
b: 7n,
// Field over which we'll do calculations. Verify with:
// 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n
P: secp256k1P,
// Curve order, total count of valid points in the field. Verify with:
n: secp256k1N,
// Base point (x, y) aka generator point
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
// noble-secp256k1 compat
lowS: true,
// Used to calculate y - the square root of y².
// Exponentiates it to very big number (P+1)/4.
// We are unwrapping the loop because it's 2x faster.
// (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
// We are multiplying it bit-by-bit
sqrtMod: (x: bigint): bigint => {
const P = secp256k1P;
const _3n = BigInt(3);
const _6n = BigInt(6);
const _11n = BigInt(11);
const _22n = BigInt(22);
const _23n = BigInt(23);
const _44n = BigInt(44);
const _88n = BigInt(88);
const b2 = (x * x * x) % P; // x^3, 11
const b3 = (b2 * b2 * x) % P; // x^7
const b6 = (pow2(b3, _3n, P) * b3) % P;
const b9 = (pow2(b6, _3n, P) * b3) % P;
const b11 = (pow2(b9, _2n, P) * b2) % P;
const b22 = (pow2(b11, _11n, P) * b11) % P;
const b44 = (pow2(b22, _22n, P) * b22) % P;
const b88 = (pow2(b44, _44n, P) * b44) % P;
const b176 = (pow2(b88, _88n, P) * b88) % P;
const b220 = (pow2(b176, _44n, P) * b44) % P;
const b223 = (pow2(b220, _3n, P) * b3) % P;
const t1 = (pow2(b223, _23n, P) * b22) % P;
const t2 = (pow2(t1, _6n, P) * b2) % P;
return pow2(t2, _2n, P);
},
endo: {
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
splitScalar: (k: bigint) => {
const n = secp256k1N;
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
const b2 = a1;
const POW_2_128 = BigInt('0x100000000000000000000000000000000');
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod(k - c1 * a1 - c2 * a2, n);
let k2 = mod(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg) k1 = n - k1;
if (k2neg) k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalar: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod(k - c1 * a1 - c2 * a2, n);
let k2 = mod(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg) k1 = n - k1;
if (k2neg) k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalar: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
},
},
},
});
sha256
);

@ -2,8 +2,8 @@ import { deepStrictEqual, throws } from 'assert';
import { should } from 'micro-should';
import * as nist from '../lib/nist.js';
import { hexToBytes } from '@noble/curves/utils';
import { default as ecdsa } from './fixtures/ecdsa_test.json' assert { type: 'json' };
import { default as ecdh } from './fixtures/ecdh_test.json' assert { type: 'json' };
import { default as ecdsa } from './wycheproof/ecdsa_test.json' assert { type: 'json' };
import { default as ecdh } from './wycheproof/ecdh_test.json' assert { type: 'json' };
// import { hexToBytes } from '@noble/curves';

@ -0,0 +1,577 @@
import { deepStrictEqual, throws } from 'assert';
import { should } from 'micro-should';
import * as fc from 'fast-check';
import { ed25519 } from '../lib/ed.js';
import { readFileSync } from 'fs';
import { default as zip215 } from './ed25519/zip215.json' assert { type: 'json' };
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
import { default as ed25519vectors } from './wycheproof/eddsa_test.json' assert { type: 'json' };
import { default as x25519vectors } from './wycheproof/x25519_test.json' assert { type: 'json' };
import { sha512 } from '@noble/hashes/sha512';
const ed = ed25519;
const hex = bytesToHex;
function to32Bytes(numOrStr) {
let hex = typeof numOrStr === 'string' ? numOrStr : numOrStr.toString(16);
return hexToBytes(hex.padStart(64, '0'));
}
function utf8ToBytes(str) {
if (typeof str !== 'string') {
throw new TypeError(`utf8ToBytes expected string, got ${typeof str}`);
}
return new TextEncoder().encode(str);
}
ed.utils.precompute(8);
should('ed25519/should not accept >32byte private keys', async () => {
const invalidPriv =
100000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800073278156000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n;
throws(() => ed.getPublicKey(invalidPriv));
});
should('ed25519/should verify recent signature', () => {
fc.assert(
fc.property(
fc.hexaString({ minLength: 2, maxLength: 32 }),
fc.bigInt(2n, ed.CURVE.n),
(message, privateKey) => {
const publicKey = ed.getPublicKey(to32Bytes(privateKey));
const signature = ed.sign(to32Bytes(message), to32Bytes(privateKey));
deepStrictEqual(publicKey.length, 32);
deepStrictEqual(signature.length, 64);
deepStrictEqual(ed.verify(signature, to32Bytes(message), publicKey), true);
}
),
{ numRuns: 5 }
);
});
should('ed25519/should not verify signature with wrong message', () => {
fc.assert(
fc.property(
fc.array(fc.integer({ min: 0x00, max: 0xff })),
fc.array(fc.integer({ min: 0x00, max: 0xff })),
fc.bigInt(1n, ed.CURVE.n),
(bytes, wrongBytes, privateKey) => {
const privKey = to32Bytes(privateKey);
const message = new Uint8Array(bytes);
const wrongMessage = new Uint8Array(wrongBytes);
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(message, privKey);
deepStrictEqual(
ed.verify(signature, wrongMessage, publicKey),
bytes.toString() === wrongBytes.toString()
);
}
),
{ numRuns: 5 }
);
});
const privKey = to32Bytes('a665a45920422f9d417e4867ef');
const msg = hexToBytes('874f9960c5d2b7a9b5fad383e1ba44719ebb743a');
const wrongMsg = hexToBytes('589d8c7f1da0a24bc07b7381ad48b1cfc211af1c');
should('ed25519/basic methods/should sign and verify', () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
});
should('ed25519/basic methods/should not verify signature with wrong public key', () => {
const publicKey = ed.getPublicKey(12);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
});
should('ed25519/basic methods/should not verify signature with wrong hash', () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
});
should('ed25519/sync methods/should sign and verify', () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
});
should('ed25519/sync methods/should not verify signature with wrong public key', async () => {
const publicKey = ed.getPublicKey(12);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
});
should('ed25519/sync methods/should not verify signature with wrong hash', async () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
});
// https://xmr.llcoins.net/addresstests.html
should(
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 1',
() => {
const publicKey =
ed.Point.BASE.multiply(0x90af56259a4b6bfbc4337980d5d75fbe3c074630368ff3804d33028e5dbfa77n);
deepStrictEqual(
publicKey.toHex(),
'0f3b913371411b27e646b537e888f685bf929ea7aab93c950ed84433f064480d'
);
}
);
should(
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 2',
() => {
const publicKey =
ed.Point.BASE.multiply(0x364e8711a60780382a5d57b061c126f039940f28a9e91fe039d4d3094d8b88n);
deepStrictEqual(
publicKey.toHex(),
'ad545340b58610f0cd62f17d55af1ab11ecde9c084d5476865ddb4dbda015349'
);
}
);
should(
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 3',
() => {
const publicKey =
ed.Point.BASE.multiply(0xb9bf90ff3abec042752cac3a07a62f0c16cfb9d32a3fc2305d676ec2d86e941n);
deepStrictEqual(
publicKey.toHex(),
'e097c4415fe85724d522b2e449e8fd78dd40d20097bdc9ae36fe8ec6fe12cb8c'
);
}
);
should(
'ed25519/BASE_POINT.multiply()/should create right publicKey without SHA-512 hashing TEST 4',
() => {
const publicKey =
ed.Point.BASE.multiply(0x69d896f02d79524c9878e080308180e2859d07f9f54454e0800e8db0847a46en);
deepStrictEqual(
publicKey.toHex(),
'f12cb7c43b59971395926f278ce7c2eaded9444fbce62ca717564cb508a0db1d'
);
}
);
should('ed25519/BASE_POINT.multiply()/should throw Point#multiply on TEST 5', () => {
for (const num of [0n, 0, -1n, -1, 1.1]) {
throws(() => ed.Point.BASE.multiply(num));
}
});
// should('ed25519/getSharedSecret()/should convert base point to montgomery using toX25519()', () => {
// deepStrictEqual(hex(ed.Point.BASE.toX25519()), ed.curve25519.BASE_POINT_U);
// });
// should('ed25519/getSharedSecret()/should be commutative', async () => {
// for (let i = 0; i < 512; i++) {
// const asec = ed.utils.randomPrivateKey();
// const apub = ed.getPublicKey(asec);
// const bsec = ed.utils.randomPrivateKey();
// const bpub = ed.getPublicKey(bsec);
// try {
// deepStrictEqual(ed.getSharedSecret(asec, bpub), ed.getSharedSecret(bsec, apub));
// } catch (error) {
// console.error('not commutative', { asec, apub, bsec, bpub });
// throw error;
// }
// }
// });
// https://ed25519.cr.yp.to/python/sign.py
// https://ed25519.cr.yp.to/python/sign.input
const data = readFileSync('./test/ed25519/vectors.txt', 'utf-8');
const vectors = data
.trim()
.split('\n')
.map((line) => line.split(':'));
should('ed25519 official vectors/should match 1024 official vectors', () => {
for (let i = 0; i < vectors.length; i++) {
const vector = vectors[i];
// Extract.
const priv = vector[0].slice(0, 64);
const expectedPub = vector[1];
const msg = vector[2];
const expectedSignature = vector[3].slice(0, 128);
// Calculate
const pub = ed.getPublicKey(to32Bytes(priv));
deepStrictEqual(hex(pub), expectedPub);
deepStrictEqual(pub, ed.Point.fromHex(pub).toRawBytes());
const signature = hex(ed.sign(msg, priv));
// console.log('vector', i);
// expect(pub).toBe(expectedPub);
deepStrictEqual(signature, expectedSignature);
}
});
// https://tools.ietf.org/html/rfc8032#section-7
should('rfc8032 vectors/should create right signature for 0x9d and empty string', () => {
const privateKey = '9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60';
const publicKey = ed.getPublicKey(privateKey);
const message = '';
const signature = ed.sign(message, privateKey);
deepStrictEqual(
hex(publicKey),
'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
);
deepStrictEqual(
hex(signature),
'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
);
});
should('rfc8032 vectors/should create right signature for 0x4c and 72', () => {
const privateKey = '4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb';
const publicKey = ed.getPublicKey(privateKey);
const message = '72';
const signature = ed.sign(message, privateKey);
deepStrictEqual(
hex(publicKey),
'3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c'
);
deepStrictEqual(
hex(signature),
'92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00'
);
});
should('rfc8032 vectors/should create right signature for 0x00 and 5a', () => {
const privateKey = '002fdd1f7641793ab064bb7aa848f762e7ec6e332ffc26eeacda141ae33b1783';
const publicKey = ed.getPublicKey(privateKey);
const message =
'5ac1dfc324f43e6cb79a87ab0470fa857b51fb944982e19074ca44b1e40082c1d07b92efa7ea55ad42b7c027e0b9e33756d95a2c1796a7c2066811dc41858377d4b835c1688d638884cd2ad8970b74c1a54aadd27064163928a77988b24403aa85af82ceab6b728e554761af7175aeb99215b7421e4474c04d213e01ff03e3529b11077cdf28964b8c49c5649e3a46fa0a09dcd59dcad58b9b922a83210acd5e65065531400234f5e40cddcf9804968e3e9ac6f5c44af65001e158067fc3a660502d13fa8874fa93332138d9606bc41b4cee7edc39d753dae12a873941bb357f7e92a4498847d6605456cb8c0b425a47d7d3ca37e54e903a41e6450a35ebe5237c6f0c1bbbc1fd71fb7cd893d189850295c199b7d88af26bc8548975fda1099ffefee42a52f3428ddff35e0173d3339562507ac5d2c45bbd2c19cfe89b';
const signature = ed.sign(message, privateKey);
deepStrictEqual(
hex(publicKey),
'77d1d8ebacd13f4e2f8a40e28c4a63bc9ce3bfb69716334bcb28a33eb134086c'
);
deepStrictEqual(
hex(signature),
'0df3aa0d0999ad3dc580378f52d152700d5b3b057f56a66f92112e441e1cb9123c66f18712c87efe22d2573777296241216904d7cdd7d5ea433928bd2872fa0c'
);
});
should('rfc8032 vectors/should create right signature for 0xf5 and long msg', () => {
const privateKey = 'f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5';
const publicKey = ed.getPublicKey(privateKey);
const message =
'08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0';
const signature = ed.sign(message, privateKey);
deepStrictEqual(
hex(publicKey),
'278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e'
);
deepStrictEqual(
hex(signature),
'0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03'
);
});
// const { RistrettoPoint } = ed;
// // const PRIVATE_KEY = 0xa665a45920422f9d417e4867efn;
// // const MESSAGE = ripemd160(new Uint8Array([97, 98, 99, 100, 101, 102, 103]));
// // prettier-ignore
// // const MESSAGE = new Uint8Array([
// // 135, 79, 153, 96, 197, 210, 183, 169, 181, 250, 211, 131, 225, 186, 68, 113, 158, 187, 116, 58,
// // ]);
// // const WRONG_MESSAGE = ripemd160(new Uint8Array([98, 99, 100, 101, 102, 103]));
// // prettier-ignore
// // const WRONG_MESSAGE = new Uint8Array([
// // 88, 157, 140, 127, 29, 160, 162, 75, 192, 123, 115, 129, 173, 72, 177, 207, 194, 17, 175, 28,
// // ]);
// // it("should verify just signed message", async () => {
// // await fc.assert(fc.asyncProperty(
// // fc.hexa(),
// // fc.bigInt(2n, ristretto25519.PRIME_ORDER),
// // async (message, privateKey) => {
// // const publicKey = await ristretto25519.getPublicKey(privateKey);
// // const signature = await ristretto25519.sign(message, privateKey);
// // expect(publicKey.length).toBe(32);
// // expect(signature.length).toBe(64);
// // expect(await ristretto25519.verify(signature, message, publicKey)).toBe(true);
// // }),
// // { numRuns: 1 }
// // );
// // });
// // it("should not verify sign with wrong message", async () => {
// // await fc.assert(fc.asyncProperty(
// // fc.array(fc.integer(0x00, 0xff)),
// // fc.array(fc.integer(0x00, 0xff)),
// // fc.bigInt(2n, ristretto25519.PRIME_ORDER),
// // async (bytes, wrongBytes, privateKey) => {
// // const message = new Uint8Array(bytes);
// // const wrongMessage = new Uint8Array(wrongBytes);
// // const publicKey = await ristretto25519.getPublicKey(privateKey);
// // const signature = await ristretto25519.sign(message, privateKey);
// // expect(await ristretto25519.verify(signature, wrongMessage, publicKey)).toBe(
// // bytes.toString() === wrongBytes.toString()
// // );
// // }),
// // { numRuns: 1 }
// // );
// // });
// // it("should sign and verify", async () => {
// // const publicKey = await ristretto25519.getPublicKey(PRIVATE_KEY);
// // const signature = await ristretto25519.sign(MESSAGE, PRIVATE_KEY);
// // expect(await ristretto25519.verify(signature, MESSAGE, publicKey)).toBe(true);
// // });
// // it("should not verify signature with wrong public key", async () => {
// // const publicKey = await ristretto25519.getPublicKey(12);
// // const signature = await ristretto25519.sign(MESSAGE, PRIVATE_KEY);
// // expect(await ristretto25519.verify(signature, MESSAGE, publicKey)).toBe(false);
// // });
// // it("should not verify signature with wrong hash", async () => {
// // const publicKey = await ristretto25519.getPublicKey(PRIVATE_KEY);
// // const signature = await ristretto25519.sign(MESSAGE, PRIVATE_KEY);
// // expect(await ristretto25519.verify(signature, WRONG_MESSAGE, publicKey)).toBe(false);
// // });
// should('ristretto255/should follow the byte encodings of small multiples', () => {
// const encodingsOfSmallMultiples = [
// // This is the identity point
// '0000000000000000000000000000000000000000000000000000000000000000',
// // This is the basepoint
// 'e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76',
// // These are small multiples of the basepoint
// '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919',
// '94741f5d5d52755ece4f23f044ee27d5d1ea1e2bd196b462166b16152a9d0259',
// 'da80862773358b466ffadfe0b3293ab3d9fd53c5ea6c955358f568322daf6a57',
// 'e882b131016b52c1d3337080187cf768423efccbb517bb495ab812c4160ff44e',
// 'f64746d3c92b13050ed8d80236a7f0007c3b3f962f5ba793d19a601ebb1df403',
// '44f53520926ec81fbd5a387845beb7df85a96a24ece18738bdcfa6a7822a176d',
// '903293d8f2287ebe10e2374dc1a53e0bc887e592699f02d077d5263cdd55601c',
// '02622ace8f7303a31cafc63f8fc48fdc16e1c8c8d234b2f0d6685282a9076031',
// '20706fd788b2720a1ed2a5dad4952b01f413bcf0e7564de8cdc816689e2db95f',
// 'bce83f8ba5dd2fa572864c24ba1810f9522bc6004afe95877ac73241cafdab42',
// 'e4549ee16b9aa03099ca208c67adafcafa4c3f3e4e5303de6026e3ca8ff84460',
// 'aa52e000df2e16f55fb1032fc33bc42742dad6bd5a8fc0be0167436c5948501f',
// '46376b80f409b29dc2b5f6f0c52591990896e5716f41477cd30085ab7f10301e',
// 'e0c418f7c8d9c4cdd7395b93ea124f3ad99021bb681dfc3302a9d99a2e53e64e',
// ];
// let B = RistrettoPoint.BASE;
// let P = RistrettoPoint.ZERO;
// for (const encoded of encodingsOfSmallMultiples) {
// deepStrictEqual(P.toHex(), encoded);
// deepStrictEqual(RistrettoPoint.fromHex(encoded).toHex(), encoded);
// P = P.add(B);
// }
// });
// should('ristretto255/should not convert bad bytes encoding', () => {
// const badEncodings = [
// // These are all bad because they're non-canonical field encodings.
// '00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
// 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// 'f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// 'edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// // These are all bad because they're negative field elements.
// '0100000000000000000000000000000000000000000000000000000000000000',
// '01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// 'ed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20',
// 'c34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562',
// 'c940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78',
// '47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24',
// 'f1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72',
// '87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309',
// // These are all bad because they give a nonsquare x^2.
// '26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371',
// '4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f',
// 'de6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b',
// 'bcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042',
// '2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08',
// 'f4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22',
// '8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731',
// '2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b',
// // These are all bad because they give a negative xy value.
// '3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e',
// 'a45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220',
// 'd483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e',
// '8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32',
// '32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b',
// '227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165',
// '5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e',
// '445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b',
// // This is s = -1, which causes y = 0.
// 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// ];
// for (const badBytes of badEncodings) {
// const b = hexToBytes(badBytes);
// throws(() => RistrettoPoint.fromHex(b));
// }
// });
// should('ristretto255/should create right points from uniform hash', async () => {
// const labels = [
// 'Ristretto is traditionally a short shot of espresso coffee',
// 'made with the normal amount of ground coffee but extracted with',
// 'about half the amount of water in the same amount of time',
// 'by using a finer grind.',
// 'This produces a concentrated shot of coffee per volume.',
// 'Just pulling a normal shot short will produce a weaker shot',
// 'and is not a Ristretto as some believe.',
// ];
// const encodedHashToPoints = [
// '3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46',
// 'f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b',
// '006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826',
// 'f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a',
// 'ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179',
// 'e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628',
// '80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065',
// ];
// for (let i = 0; i < labels.length; i++) {
// const hash = sha512(utf8ToBytes(labels[i]));
// const point = RistrettoPoint.hashToCurve(hash);
// deepStrictEqual(point.toHex(), encodedHashToPoints[i]);
// }
// });
// should('curve25519/scalarMult 1', () => {
// const X25519_VECTORS = [
// {
// k: 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4',
// u: 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c',
// ku: 'c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552',
// },
// {
// k: '4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d',
// u: 'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493',
// ku: '95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957',
// },
// ];
// for (const { k, u, ku } of X25519_VECTORS) {
// const _k = Uint8Array.from(hexToBytes(k));
// const _u = Uint8Array.from(hexToBytes(u));
// deepStrictEqual(bytesToHex(ed.curve25519.scalarMult(_k, _u)), ku);
// }
// });
// should('curve25519/scalarMultBase recursive', () => {
// // https://datatracker.ietf.org/doc/html/rfc7748#section-5.2
// const VECTORS = [
// { iters: 1, res: '422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079' },
// { iters: 1000, res: '684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51' },
// // {iters: 1000000, res: '7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424'},
// ];
// for (const { iters, res } of VECTORS) {
// let k = hexToBytes('0900000000000000000000000000000000000000000000000000000000000000');
// let u = k;
// for (let i = 0; i < iters; i++) {
// if (i > 0 && i % 100000 === 0) console.log('10k');
// [k, u] = [ed.curve25519.scalarMult(k, u), k];
// }
// deepStrictEqual(bytesToHex(k), res);
// }
// });
// should('curve25519/scalarMult 2', () => {
// const a_priv = hexToBytes('77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a');
// const a_pub = hexToBytes('8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a');
// const b_priv = hexToBytes('5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb');
// const b_pub = hexToBytes('de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f');
// const k = '4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742';
// deepStrictEqual(bytesToHex(ed.curve25519.scalarMultBase(a_priv)), bytesToHex(a_pub));
// deepStrictEqual(bytesToHex(ed.curve25519.scalarMultBase(b_priv)), bytesToHex(b_pub));
// deepStrictEqual(bytesToHex(ed.curve25519.scalarMult(a_priv, b_pub)), k);
// deepStrictEqual(bytesToHex(ed.curve25519.scalarMult(b_priv, a_pub)), k);
// });
should('input immutability: sign/verify are immutable', () => {
const privateKey = ed.utils.randomPrivateKey();
const publicKey = ed.getPublicKey(privateKey);
for (let i = 0; i < 100; i++) {
let payload = randomBytes(100);
let signature = ed.sign(payload, privateKey);
if (!ed.verify(signature, payload, publicKey)) {
throw new Error('Signature verification failed');
}
const signatureCopy = Buffer.alloc(signature.byteLength);
signatureCopy.set(signature, 0); // <-- breaks
payload = payload.slice();
signature = signature.slice();
if (!ed.verify(signatureCopy, payload, publicKey))
throw new Error('Copied signature verification failed');
}
});
// https://zips.z.cash/zip-0215
// Vectors from https://gist.github.com/hdevalence/93ed42d17ecab8e42138b213812c8cc7
should('ZIP-215 compliance tests/should pass all of them', () => {
const str = utf8ToBytes('Zcash');
for (let v of zip215) {
let noble = false;
try {
noble = ed.verify(v.sig_bytes, str, v.vk_bytes);
} catch (e) {
noble = false;
}
deepStrictEqual(noble, v.valid_zip215);
}
});
should('ZIP-215 compliance tests/disallows sig.s >= CURVE.n', () => {
const sig = new ed.Signature(ed.Point.BASE, 1n);
// @ts-ignore
sig.s = ed.CURVE.n + 1n;
throws(() => ed.verify(sig, 'deadbeef', ed.Point.BASE));
});
// {
// const group = x25519vectors.testGroups[0];
// for (let i = 0; i < group.tests.length; i++) {
// const v = group.tests[i];
// should(`Wycheproof/X25519(${i}, ${v.result}) ${v.comment}`, () => {
// if (v.result === 'valid' || v.result === 'acceptable') {
// try {
// ed.Point.fromHex(v.public);
// } catch (e) {
// if (e.message.includes('Point.fromHex: invalid y coordinate')) return;
// throw e;
// }
// const shared = hex(ed.getSharedSecret(v.private, v.public));
// deepStrictEqual(shared, v.shared, 'valid');
// } else if (v.result === 'invalid') {
// let failed = false;
// try {
// ed.getSharedSecret(v.private, v.public);
// } catch (error) {
// failed = true;
// }
// deepStrictEqual(failed, true, 'invalid');
// } else throw new Error('unknown test result');
// });
// }
// }
{
for (let g = 0; g < ed25519vectors.testGroups.length; g++) {
const group = ed25519vectors.testGroups[g];
const key = group.key;
should(`Wycheproof/ED25519(${g}, public)`, () => {
deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk);
});
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
should(`Wycheproof/ED25519(${g}/${i}, ${v.result}): ${v.comment}`, () => {
if (v.result === 'valid' || v.result === 'acceptable') {
deepStrictEqual(hex(ed.sign(v.msg, key.sk)), v.sig);
deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true);
} else if (v.result === 'invalid') {
let failed = false;
try {
failed = !ed.verify(v.sig, v.msg, key.pk);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, 'invalid');
} else throw new Error('unknown test result');
});
}
}
}
should('Property test issue #1', () => {
const message = new Uint8Array([12, 12, 12]);
const signature = ed.sign(message, to32Bytes(1n));
const publicKey = ed.getPublicKey(to32Bytes(1n)); // <- was 1n
deepStrictEqual(ed.verify(signature, message, publicKey), true);
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,577 @@
import { deepStrictEqual, throws } from 'assert';
import { should } from 'micro-should';
import * as fc from 'fast-check';
import { ed25519, ed448 } from '../lib/ed.js';
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
import { default as ed448vectors } from './wycheproof/ed448_test.json' assert { type: 'json' };
import { default as x448vectors } from './wycheproof/x448_test.json' assert { type: 'json' };
const ed = ed448;
const hex = bytesToHex;
ed.utils.precompute(4);
should(`Basic`, () => {
const G1 = ed.Point.BASE;
deepStrictEqual(
G1.x,
224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710n
);
deepStrictEqual(
G1.y,
298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660n
);
const G2 = ed.Point.BASE.multiply(2n);
deepStrictEqual(
G2.x,
484559149530404593699549205258669689569094240458212040187660132787056912146709081364401144455726350866276831544947397859048262938744149n
);
deepStrictEqual(
G2.y,
494088759867433727674302672526735089350544552303727723746126484473087719117037293890093462157703888342865036477787453078312060500281069n
);
const G3 = ed.Point.BASE.multiply(3n);
deepStrictEqual(
G3.x,
23839778817283171003887799738662344287085130522697782688245073320169861206004018274567429238677677920280078599146891901463786155880335n
);
deepStrictEqual(
G3.y,
636046652612779686502873775776967954190574036985351036782021535703553242737829645273154208057988851307101009474686328623630835377952508n
);
});
should('Basic/decompress', () => {
const G1 = ed.Point.BASE;
const G2 = ed.Point.BASE.multiply(2n);
const G3 = ed.Point.BASE.multiply(3n);
const points = [G1, G2, G3];
const getXY = (p) => ({ x: p.x, y: p.y });
for (const p of points) deepStrictEqual(getXY(ed.Point.fromHex(p.toHex())), getXY(p));
});
const VECTORS_RFC8032 = [
{
secretKey:
'6c82a562cb808d10d632be89c8513ebf' +
'6c929f34ddfa8c9f63c9960ef6e348a3' +
'528c8a3fcc2f044e39a3fc5b94492f8f' +
'032e7549a20098f95b',
publicKey:
'5fd7449b59b461fd2ce787ec616ad46a' +
'1da1342485a70e1f8a0ea75d80e96778' +
'edf124769b46c7061bd6783df1e50f6c' +
'd1fa1abeafe8256180',
message: '',
signature:
'533a37f6bbe457251f023c0d88f976ae' +
'2dfb504a843e34d2074fd823d41a591f' +
'2b233f034f628281f2fd7a22ddd47d78' +
'28c59bd0a21bfd3980ff0d2028d4b18a' +
'9df63e006c5d1c2d345b925d8dc00b41' +
'04852db99ac5c7cdda8530a113a0f4db' +
'b61149f05a7363268c71d95808ff2e65' +
'2600',
},
{
secretKey:
'c4eab05d357007c632f3dbb48489924d' +
'552b08fe0c353a0d4a1f00acda2c463a' +
'fbea67c5e8d2877c5e3bc397a659949e' +
'f8021e954e0a12274e',
publicKey:
'43ba28f430cdff456ae531545f7ecd0a' +
'c834a55d9358c0372bfa0c6c6798c086' +
'6aea01eb00742802b8438ea4cb82169c' +
'235160627b4c3a9480',
message: '03',
signature:
'26b8f91727bd62897af15e41eb43c377' +
'efb9c610d48f2335cb0bd0087810f435' +
'2541b143c4b981b7e18f62de8ccdf633' +
'fc1bf037ab7cd779805e0dbcc0aae1cb' +
'cee1afb2e027df36bc04dcecbf154336' +
'c19f0af7e0a6472905e799f1953d2a0f' +
'f3348ab21aa4adafd1d234441cf807c0' +
'3a00',
},
{
secretKey:
'cd23d24f714274e744343237b93290f5' +
'11f6425f98e64459ff203e8985083ffd' +
'f60500553abc0e05cd02184bdb89c4cc' +
'd67e187951267eb328',
publicKey:
'dcea9e78f35a1bf3499a831b10b86c90' +
'aac01cd84b67a0109b55a36e9328b1e3' +
'65fce161d71ce7131a543ea4cb5f7e9f' +
'1d8b00696447001400',
message: '0c3e544074ec63b0265e0c',
signature:
'1f0a8888ce25e8d458a21130879b840a' +
'9089d999aaba039eaf3e3afa090a09d3' +
'89dba82c4ff2ae8ac5cdfb7c55e94d5d' +
'961a29fe0109941e00b8dbdeea6d3b05' +
'1068df7254c0cdc129cbe62db2dc957d' +
'bb47b51fd3f213fb8698f064774250a5' +
'028961c9bf8ffd973fe5d5c206492b14' +
'0e00',
},
{
secretKey:
'258cdd4ada32ed9c9ff54e63756ae582' +
'fb8fab2ac721f2c8e676a72768513d93' +
'9f63dddb55609133f29adf86ec9929dc' +
'cb52c1c5fd2ff7e21b',
publicKey:
'3ba16da0c6f2cc1f30187740756f5e79' +
'8d6bc5fc015d7c63cc9510ee3fd44adc' +
'24d8e968b6e46e6f94d19b945361726b' +
'd75e149ef09817f580',
message: '64a65f3cdedcdd66811e2915',
signature:
'7eeeab7c4e50fb799b418ee5e3197ff6' +
'bf15d43a14c34389b59dd1a7b1b85b4a' +
'e90438aca634bea45e3a2695f1270f07' +
'fdcdf7c62b8efeaf00b45c2c96ba457e' +
'b1a8bf075a3db28e5c24f6b923ed4ad7' +
'47c3c9e03c7079efb87cb110d3a99861' +
'e72003cbae6d6b8b827e4e6c143064ff' +
'3c00',
},
{
secretKey:
'7ef4e84544236752fbb56b8f31a23a10' +
'e42814f5f55ca037cdcc11c64c9a3b29' +
'49c1bb60700314611732a6c2fea98eeb' +
'c0266a11a93970100e',
publicKey:
'b3da079b0aa493a5772029f0467baebe' +
'e5a8112d9d3a22532361da294f7bb381' +
'5c5dc59e176b4d9f381ca0938e13c6c0' +
'7b174be65dfa578e80',
message: '64a65f3cdedcdd66811e2915e7',
signature:
'6a12066f55331b6c22acd5d5bfc5d712' +
'28fbda80ae8dec26bdd306743c5027cb' +
'4890810c162c027468675ecf645a8317' +
'6c0d7323a2ccde2d80efe5a1268e8aca' +
'1d6fbc194d3f77c44986eb4ab4177919' +
'ad8bec33eb47bbb5fc6e28196fd1caf5' +
'6b4e7e0ba5519234d047155ac727a105' +
'3100',
},
{
secretKey:
'd65df341ad13e008567688baedda8e9d' +
'cdc17dc024974ea5b4227b6530e339bf' +
'f21f99e68ca6968f3cca6dfe0fb9f4fa' +
'b4fa135d5542ea3f01',
publicKey:
'df9705f58edbab802c7f8363cfe5560a' +
'b1c6132c20a9f1dd163483a26f8ac53a' +
'39d6808bf4a1dfbd261b099bb03b3fb5' +
'0906cb28bd8a081f00',
message:
'bd0f6a3747cd561bdddf4640a332461a' +
'4a30a12a434cd0bf40d766d9c6d458e5' +
'512204a30c17d1f50b5079631f64eb31' +
'12182da3005835461113718d1a5ef944',
signature:
'554bc2480860b49eab8532d2a533b7d5' +
'78ef473eeb58c98bb2d0e1ce488a98b1' +
'8dfde9b9b90775e67f47d4a1c3482058' +
'efc9f40d2ca033a0801b63d45b3b722e' +
'f552bad3b4ccb667da350192b61c508c' +
'f7b6b5adadc2c8d9a446ef003fb05cba' +
'5f30e88e36ec2703b349ca229c267083' +
'3900',
},
{
secretKey:
'2ec5fe3c17045abdb136a5e6a913e32a' +
'b75ae68b53d2fc149b77e504132d3756' +
'9b7e766ba74a19bd6162343a21c8590a' +
'a9cebca9014c636df5',
publicKey:
'79756f014dcfe2079f5dd9e718be4171' +
'e2ef2486a08f25186f6bff43a9936b9b' +
'fe12402b08ae65798a3d81e22e9ec80e' +
'7690862ef3d4ed3a00',
message:
'15777532b0bdd0d1389f636c5f6b9ba7' +
'34c90af572877e2d272dd078aa1e567c' +
'fa80e12928bb542330e8409f31745041' +
'07ecd5efac61ae7504dabe2a602ede89' +
'e5cca6257a7c77e27a702b3ae39fc769' +
'fc54f2395ae6a1178cab4738e543072f' +
'c1c177fe71e92e25bf03e4ecb72f47b6' +
'4d0465aaea4c7fad372536c8ba516a60' +
'39c3c2a39f0e4d832be432dfa9a706a6' +
'e5c7e19f397964ca4258002f7c0541b5' +
'90316dbc5622b6b2a6fe7a4abffd9610' +
'5eca76ea7b98816af0748c10df048ce0' +
'12d901015a51f189f3888145c03650aa' +
'23ce894c3bd889e030d565071c59f409' +
'a9981b51878fd6fc110624dcbcde0bf7' +
'a69ccce38fabdf86f3bef6044819de11',
signature:
'c650ddbb0601c19ca11439e1640dd931' +
'f43c518ea5bea70d3dcde5f4191fe53f' +
'00cf966546b72bcc7d58be2b9badef28' +
'743954e3a44a23f880e8d4f1cfce2d7a' +
'61452d26da05896f0a50da66a239a8a1' +
'88b6d825b3305ad77b73fbac0836ecc6' +
'0987fd08527c1a8e80d5823e65cafe2a' +
'3d00',
},
{
secretKey:
'872d093780f5d3730df7c212664b37b8' +
'a0f24f56810daa8382cd4fa3f77634ec' +
'44dc54f1c2ed9bea86fafb7632d8be19' +
'9ea165f5ad55dd9ce8',
publicKey:
'a81b2e8a70a5ac94ffdbcc9badfc3feb' +
'0801f258578bb114ad44ece1ec0e799d' +
'a08effb81c5d685c0c56f64eecaef8cd' +
'f11cc38737838cf400',
message:
'6ddf802e1aae4986935f7f981ba3f035' +
'1d6273c0a0c22c9c0e8339168e675412' +
'a3debfaf435ed651558007db4384b650' +
'fcc07e3b586a27a4f7a00ac8a6fec2cd' +
'86ae4bf1570c41e6a40c931db27b2faa' +
'15a8cedd52cff7362c4e6e23daec0fbc' +
'3a79b6806e316efcc7b68119bf46bc76' +
'a26067a53f296dafdbdc11c77f7777e9' +
'72660cf4b6a9b369a6665f02e0cc9b6e' +
'dfad136b4fabe723d2813db3136cfde9' +
'b6d044322fee2947952e031b73ab5c60' +
'3349b307bdc27bc6cb8b8bbd7bd32321' +
'9b8033a581b59eadebb09b3c4f3d2277' +
'd4f0343624acc817804728b25ab79717' +
'2b4c5c21a22f9c7839d64300232eb66e' +
'53f31c723fa37fe387c7d3e50bdf9813' +
'a30e5bb12cf4cd930c40cfb4e1fc6225' +
'92a49588794494d56d24ea4b40c89fc0' +
'596cc9ebb961c8cb10adde976a5d602b' +
'1c3f85b9b9a001ed3c6a4d3b1437f520' +
'96cd1956d042a597d561a596ecd3d173' +
'5a8d570ea0ec27225a2c4aaff26306d1' +
'526c1af3ca6d9cf5a2c98f47e1c46db9' +
'a33234cfd4d81f2c98538a09ebe76998' +
'd0d8fd25997c7d255c6d66ece6fa56f1' +
'1144950f027795e653008f4bd7ca2dee' +
'85d8e90f3dc315130ce2a00375a318c7' +
'c3d97be2c8ce5b6db41a6254ff264fa6' +
'155baee3b0773c0f497c573f19bb4f42' +
'40281f0b1f4f7be857a4e59d416c06b4' +
'c50fa09e1810ddc6b1467baeac5a3668' +
'd11b6ecaa901440016f389f80acc4db9' +
'77025e7f5924388c7e340a732e554440' +
'e76570f8dd71b7d640b3450d1fd5f041' +
'0a18f9a3494f707c717b79b4bf75c984' +
'00b096b21653b5d217cf3565c9597456' +
'f70703497a078763829bc01bb1cbc8fa' +
'04eadc9a6e3f6699587a9e75c94e5bab' +
'0036e0b2e711392cff0047d0d6b05bd2' +
'a588bc109718954259f1d86678a579a3' +
'120f19cfb2963f177aeb70f2d4844826' +
'262e51b80271272068ef5b3856fa8535' +
'aa2a88b2d41f2a0e2fda7624c2850272' +
'ac4a2f561f8f2f7a318bfd5caf969614' +
'9e4ac824ad3460538fdc25421beec2cc' +
'6818162d06bbed0c40a387192349db67' +
'a118bada6cd5ab0140ee273204f628aa' +
'd1c135f770279a651e24d8c14d75a605' +
'9d76b96a6fd857def5e0b354b27ab937' +
'a5815d16b5fae407ff18222c6d1ed263' +
'be68c95f32d908bd895cd76207ae7264' +
'87567f9a67dad79abec316f683b17f2d' +
'02bf07e0ac8b5bc6162cf94697b3c27c' +
'd1fea49b27f23ba2901871962506520c' +
'392da8b6ad0d99f7013fbc06c2c17a56' +
'9500c8a7696481c1cd33e9b14e40b82e' +
'79a5f5db82571ba97bae3ad3e0479515' +
'bb0e2b0f3bfcd1fd33034efc6245eddd' +
'7ee2086ddae2600d8ca73e214e8c2b0b' +
'db2b047c6a464a562ed77b73d2d841c4' +
'b34973551257713b753632efba348169' +
'abc90a68f42611a40126d7cb21b58695' +
'568186f7e569d2ff0f9e745d0487dd2e' +
'b997cafc5abf9dd102e62ff66cba87',
signature:
'e301345a41a39a4d72fff8df69c98075' +
'a0cc082b802fc9b2b6bc503f926b65bd' +
'df7f4c8f1cb49f6396afc8a70abe6d8a' +
'ef0db478d4c6b2970076c6a0484fe76d' +
'76b3a97625d79f1ce240e7c576750d29' +
'5528286f719b413de9ada3e8eb78ed57' +
'3603ce30d8bb761785dc30dbc320869e' +
'1a00',
},
];
for (let i = 0; i < VECTORS_RFC8032.length; i++) {
const v = VECTORS_RFC8032[i];
should(`RFC8032/${i}`, () => {
deepStrictEqual(hex(ed.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(hex(ed.sign(v.message, v.secretKey)), v.signature);
deepStrictEqual(ed.verify(v.signature, v.message, v.publicKey), true);
});
}
should('ed448/should not accept >57byte private keys', async () => {
const invalidPriv =
100000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800073278156000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n;
throws(() => ed.getPublicKey(invalidPriv));
});
function to57Bytes(numOrStr) {
let hex = typeof numOrStr === 'string' ? numOrStr : numOrStr.toString(16);
return hexToBytes(hex.padStart(114, '0'));
}
should('ed448/should verify recent signature', () => {
fc.assert(
fc.property(
fc.hexaString({ minLength: 2, maxLength: 57 }),
fc.bigInt(2n, ed.CURVE.n),
(message, privateKey) => {
const publicKey = ed.getPublicKey(to57Bytes(privateKey));
const signature = ed.sign(to57Bytes(message), to57Bytes(privateKey));
deepStrictEqual(publicKey.length, 57);
deepStrictEqual(signature.length, 114);
deepStrictEqual(ed.verify(signature, to57Bytes(message), publicKey), true);
}
),
{ numRuns: 5 }
);
});
should('ed448/should not verify signature with wrong message', () => {
fc.assert(
fc.property(
fc.array(fc.integer({ min: 0x00, max: 0xff })),
fc.array(fc.integer({ min: 0x00, max: 0xff })),
fc.bigInt(1n, ed.CURVE.n),
(bytes, wrongBytes, privateKey) => {
const message = new Uint8Array(bytes);
const wrongMessage = new Uint8Array(wrongBytes);
const priv = to57Bytes(privateKey);
const publicKey = ed.getPublicKey(priv);
const signature = ed.sign(message, priv);
deepStrictEqual(
ed.verify(signature, wrongMessage, publicKey),
bytes.toString() === wrongBytes.toString()
);
}
),
{ numRuns: 5 }
);
});
const privKey = to57Bytes('a665a45920422f9d417e4867ef');
const msg = hexToBytes('874f9960c5d2b7a9b5fad383e1ba44719ebb743a');
const wrongMsg = hexToBytes('589d8c7f1da0a24bc07b7381ad48b1cfc211af1c');
should('ed25519/basic methods/should sign and verify', () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
});
should('ed25519/basic methods/should not verify signature with wrong public key', () => {
const publicKey = ed.getPublicKey(12);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
});
should('ed25519/basic methods/should not verify signature with wrong hash', () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
});
should('ed25519/sync methods/should sign and verify', () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), true);
});
should('ed25519/sync methods/should not verify signature with wrong public key', async () => {
const publicKey = ed.getPublicKey(12);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, msg, publicKey), false);
});
should('ed25519/sync methods/should not verify signature with wrong hash', async () => {
const publicKey = ed.getPublicKey(privKey);
const signature = ed.sign(msg, privKey);
deepStrictEqual(ed.verify(signature, wrongMsg, publicKey), false);
});
should('ed25519/BASE_POINT.multiply()/should throw Point#multiply on TEST 5', () => {
for (const num of [0n, 0, -1n, -1, 1.1]) {
throws(() => ed.Point.BASE.multiply(num));
}
});
// should('ed25519/getSharedSecret()/should convert base point to montgomery using toX25519()', () => {
// deepStrictEqual(hex(ed.Point.BASE.toX25519()), ed.curve25519.BASE_POINT_U);
// });
// should('ed25519/getSharedSecret()/should be commutative', async () => {
// for (let i = 0; i < 512; i++) {
// const asec = ed.utils.randomPrivateKey();
// const apub = ed.getPublicKey(asec);
// const bsec = ed.utils.randomPrivateKey();
// const bpub = ed.getPublicKey(bsec);
// try {
// deepStrictEqual(ed.getSharedSecret(asec, bpub), ed.getSharedSecret(bsec, apub));
// } catch (error) {
// console.error('not commutative', { asec, apub, bsec, bpub });
// throw error;
// }
// }
// });
should('input immutability: sign/verify are immutable', () => {
const privateKey = ed.utils.randomPrivateKey();
const publicKey = ed.getPublicKey(privateKey);
for (let i = 0; i < 100; i++) {
let payload = randomBytes(100);
let signature = ed.sign(payload, privateKey);
if (!ed.verify(signature, payload, publicKey)) {
throw new Error('Signature verification failed');
}
const signatureCopy = Buffer.alloc(signature.byteLength);
signatureCopy.set(signature, 0); // <-- breaks
payload = payload.slice();
signature = signature.slice();
if (!ed.verify(signatureCopy, payload, publicKey))
throw new Error('Copied signature verification failed');
}
});
{
for (let g = 0; g < ed448vectors.testGroups.length; g++) {
const group = ed448vectors.testGroups[g];
const key = group.key;
should(`Wycheproof/ED448(${g}, public)`, () => {
deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk);
});
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
should(`Wycheproof/ED448(${g}/${i}, ${v.result}): ${v.comment}`, () => {
if (v.result === 'valid' || v.result === 'acceptable') {
deepStrictEqual(hex(ed.sign(v.msg, key.sk)), v.sig);
deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true);
} else if (v.result === 'invalid') {
let failed = false;
try {
failed = !ed.verify(v.sig, v.msg, key.pk);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, 'invalid');
} else throw new Error('unknown test result');
});
}
}
}
// {
// const group = x25519vectors.testGroups[0];
// for (let i = 0; i < group.tests.length; i++) {
// const v = group.tests[i];
// should(`Wycheproof/X25519(${i}, ${v.result}) ${v.comment}`, () => {
// if (v.result === 'valid' || v.result === 'acceptable') {
// try {
// ed.Point.fromHex(v.public);
// } catch (e) {
// if (e.message.includes('Point.fromHex: invalid y coordinate')) return;
// throw e;
// }
// const shared = hex(ed.getSharedSecret(v.private, v.public));
// deepStrictEqual(shared, v.shared, 'valid');
// } else if (v.result === 'invalid') {
// let failed = false;
// try {
// ed.getSharedSecret(v.private, v.public);
// } catch (error) {
// failed = true;
// }
// deepStrictEqual(failed, true, 'invalid');
// } else throw new Error('unknown test result');
// });
// }
// }
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}
/*
OUR:
verify(r) Point {
x: 117083889870452976893611547833716470707682026107584166971579726410379933200511856552571178072395970298806909801597194212619985635844270n,
y: 664613439225768038924451828443390535972832706605490606711138767575182918078146210986473699054775106829537240700777959779811881639147732n
}
verify(s) 171560600556246420336815304075147406138580530023825761769062776185328256162525428025207885397693292244020015666168990464688721996580108n
verify(G*s) Point {
x: 162580569181617012512915096099987276929520102470148179595683186785564923123644100210058934137413137508679834237807539232961980479559703n,
y: 300823828808029813226461528962321558722882991716498392051038897352648558972404548670077149616666377671445681138581862112882370877960540n
}
verify(k, hashed) 8903905151968610333524336167784696500100432517973872822290595420701503447289798240464976231189650851226450153394571270017367997886911n
verify(kA, pubKey*k) Point {
x: 689275764828592611152871878771714953006357504547408405065617338137477032523786110957620128317758694018203461690302684307888964572340785n,
y: 481328274497162994197716136544465653692120986048960981855841218770941500118441012672159998270864104759919787387966448820647078734831560n
}
verify(RkA, r+kA) Point {
x: 122982406147090575324915101352793466553671728663998628086189507014151752138194638629641411526703069442455515495095211707112301230852909n,
y: 628599576854758762451451863221817761200843280520482487953855243757271313346398229758661810534375546179313418158952236033181207878869809n
}
verify(RkA*h) Point {
x: 285367816437357046852385747901568148949273863571594761351869427482364138883891040584481510007402650226067916995110428282873262921611092n,
y: 156274886003874424437114343095234538185297810914769372891105611450134155931335556420419362638465757217877136785807507867845960943191541n
}
verify(SB*h) Point {
x: 49879895074926972607089290381794972663529905435154505099510082025305354413619454150885832024420892269163908738032246918490575686924369n,
y: 493395180352948178031760912270438078255871801590750728653962749871941650726588112030608282487999493622892374555049324278196950479173047n
}
verify(RkA-SB) Point {
x: 387994761565948378495106619286831545021939931213704916072043327425382665414799988004170105004375426191018762465670849206465968350321870n,
y: 6861694927033303775201514393095605504169468049999574963263295660536234490030921387020643041252124207285319521500442198840633575797105n
}
verify((RkA-SB)*h) Point {
x: 459153706735977722773001536505633023208447605158247558496590837749184216434578577646373840599757767671074933212247199030379143045005320n,
y: 610562540704855906228140299454456520343298226945170317172546981746408207471796755968182254530606222931325758957275600304516146767443812n
}
verify(R) x=117083889870452976893611547833716470707682026107584166971579726410379933200511856552571178072395970298806909801597194212619985635844270
y=664613439225768038924451828443390535972832706605490606711138767575182918078146210986473699054775106829537240700777959779811881639147732
verify(S) 171560600556246420336815304075147406138580530023825761769062776185328256162525428025207885397693292244020015666168990464688721996580108
Verify parsed
!!!!!!!! CTX True b'' b'53696745643434380000'
verify(h) 8903905151968610333524336167784696500100432517973872822290595420701503447289798240464976231189650851226450153394571270017367997886911
MUL 8903905151968610333524336167784696500100432517973872822290595420701503447289798240464976231189650851226450153394571270017367997886911
MUL 171560600556246420336815304075147406138580530023825761769062776185328256162525428025207885397693292244020015666168990464688721996580108
verify((R+(a*h)) ) x=122982406147090575324915101352793466553671728663998628086189507014151752138194638629641411526703069442455515495095211707112301230852909
y=628599576854758762451451863221817761200843280520482487953855243757271313346398229758661810534375546179313418158952236033181207878869809
ok ^
verify(B*S) x=162580569181617012512915096099987276929520102470148179595683186785564923123644100210058934137413137508679834237807539232961980479559703
y=300823828808029813226461528962321558722882991716498392051038897352648558972404548670077149616666377671445681138581862112882370877960540
OK!
verify((R+(a*h)) * c) x=285367816437357046852385747901568148949273863571594761351869427482364138883891040584481510007402650226067916995110428282873262921611092
y=156274886003874424437114343095234538185297810914769372891105611450134155931335556420419362638465757217877136785807507867845960943191541
verify(B*S*c) x=49879895074926972607089290381794972663529905435154505099510082025305354413619454150885832024420892269163908738032246918490575686924369
y=493395180352948178031760912270438078255871801590750728653962749871941650726588112030608282487999493622892374555049324278196950479173047
*/

@ -2,6 +2,8 @@ import { should } from 'micro-should';
import './basic.test.js';
import './rfc6979.test.js';
import './ed448.test.js';
import './ed25519.test.js';
import './secp256k1.test.js';
import './starknet/starknet.test.js';

@ -17,7 +17,6 @@ should('RFC6979', () => {
for (const c of v.cases) {
const h = curve.CURVE.hash(c.message);
const sigObj = curve.sign(h, v.private);
// const sigObj = curve.Signature.fromDER(sig);
deepStrictEqual(sigObj.r, hexToBigint(c.r), 'R');
deepStrictEqual(sigObj.s, hexToBigint(c.s), 'S');
deepStrictEqual(curve.verify(sigObj.toDERRawBytes(), h, pubKey), true, 'verify(1)');

@ -0,0 +1,908 @@
{
"algorithm" : "EDDSA",
"generatorVersion" : "0.8r12",
"numberOfTests" : 86,
"header" : [
"Test vectors of type EddsaVerify are intended for testing",
"the verification of Eddsa signatures."
],
"notes" : {
"SignatureMalleability" : "EdDSA signatures are non-malleable, if implemented accordingly. Failing to check the range of S allows to modify signatures. See RFC 8032, Section 5.2.7 and Section 8.4."
},
"schema" : "eddsa_verify_schema.json",
"testGroups" : [
{
"jwk" : {
"crv" : "Ed448",
"d" : "iDAeB2UY01N_kwLuD1Ij5LY-HwFgB9PC69_sX3CZfoEZxrrQrnuAP0h5HKjsVJqiobhi96UVkLnV",
"kid" : "none",
"kty" : "OKP",
"x" : "QZYQpTSvEn9YOwSBjNt_D_MAsCXy4BaCvK4z_Wkc7gOVEd8M3caQ7peEJuizjlDOWvfc-6UPcEwA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "419610a534af127f583b04818cdb7f0ff300b025f2e01682bcae33fd691cee039511df0cddc690ee978426e8b38e50ce5af7dcfba50f704c00",
"sk" : "88301e076518d3537f9302ee0f5223e4b63e1f016007d3c2ebdfec5f70997e8119c6bad0ae7b803f48791ca8ec549aa2a1b862f7a51590b9d5",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00419610a534af127f583b04818cdb7f0ff300b025f2e01682bcae33fd691cee039511df0cddc690ee978426e8b38e50ce5af7dcfba50f704c00",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAQZYQpTSvEn9YOwSBjNt/D/MAsCXy4BaCvK4z/Wkc7gOVEd8M3caQ7peEJuizjlDOWvfc+6UPcEwA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 1,
"comment" : "",
"msg" : "",
"sig" : "cf7953007666e12f73af9ec92e3e018da5ee5a8d5b17f5100a354c58f1d5f4bb37ab835c52f72374c72d612689149cf6d36a70db6dc5a6c400b597348e0e31e51e65bb144e63c892a367b4c055c036aa6cd7e728cdd2a098963bda863903e6dd025b5a5d891209f4e28537694804e50b0800",
"result" : "valid",
"flags" : []
},
{
"tcId" : 2,
"comment" : "",
"msg" : "78",
"sig" : "c56e94d5c9ca860c244f33db556bf6b3cec38b024b77604a35d6a07211b1316b9a027133c374b86f72665cc45ce01583a2e0f2775c6172da801acef168717cab1196cddfb149359dfef589756257cc2d6b02fc516d8d41b4adaa3f11428f41410ef0dc3c1b008d3d052173d4389508ed0100",
"result" : "valid",
"flags" : []
},
{
"tcId" : 3,
"comment" : "",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600",
"result" : "valid",
"flags" : []
},
{
"tcId" : 4,
"comment" : "",
"msg" : "48656c6c6f",
"sig" : "442e33780f199dd7bc71d1335f74df7f3a0ec789e21a175c1bffddb6e50091998d969ac8194b3acefb7702f6c222f84f7eeca3b80406f1fe80687915e7925bf52deb47b6b779e26d30eec7c5fef03580f280a089eefd0bacc9fbbb6a4d73a591d1671d192e6bbcfdb79ad3db5673a1263000",
"result" : "valid",
"flags" : []
},
{
"tcId" : 5,
"comment" : "",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff28060a05236fc9c1682b0e55b60a082c9a57bffe61ef4dda5ce65df539805122b3a09a05976d41ad68ab52df85428152c57da93531e5d16920e00",
"result" : "valid",
"flags" : []
},
{
"tcId" : 6,
"comment" : "",
"msg" : "000000000000000000000000",
"sig" : "a8ca64d1ab00eae77fd2854d8422db3ae12fca91c14f274f30a44df98590786ec4cbb96a9564fc1b9b16c22d2bd00aa65f0876323729f5ac809fb0b89a4d3f27afbabb596851d835173d60ea34e0875359f3d6adb13cef1395b7eaa5f9147583ff38b4deb183062874915bf194ae61072300",
"result" : "valid",
"flags" : []
},
{
"tcId" : 7,
"comment" : "",
"msg" : "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
"sig" : "b205d3e24ccef64c1e86f15f48ddfa682453503489475188b04a8f55860b3c8a9c01e6de820bb7d9b15daff8de25a4a870e987157a115ec1802da0d0606da12842ea7eab658b5eea6dd1f3a641a5174425578003cd318b8d6b8dcb4de954b5078d1912c578ad8281515d6df3672b94173f00",
"result" : "valid",
"flags" : []
},
{
"tcId" : 8,
"comment" : "",
"msg" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60",
"sig" : "3492ef66e5fdf1503e9e206c5c2f0d4b7891aad793575527d2251e0df1b97c2feac188bc382ce3c92c4bc36ba2695f32bedadd480eaa932300d0db1f9a9c60844d2ea5aea64933c7be46c4f9d21cb48b39eae23d08496de7ce9501197185cc5d4ff8aa4b018ce7ad321f6a7d778c4a070400",
"result" : "valid",
"flags" : []
},
{
"tcId" : 9,
"comment" : "",
"msg" : "ffffffffffffffffffffffffffffffff",
"sig" : "545e1905af1b5886552eaf78e17304c6f83fcfb3444df2d1ea056486db615e3bb29131bb0c1fd295364dc515dae581967148eb23c6c9012e806d3623baff00548c648e3cb3756aaaaf659f2fb7dd2e71c7611448593ca63f2a98913ab7f182e6820eaf1334e2745e0e7bc0dccab98de71600",
"result" : "valid",
"flags" : []
},
{
"tcId" : 10,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 11,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 12,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 13,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 14,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 15,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 16,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 17,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 18,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 19,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 20,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 21,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 22,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3ff24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 23,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3ff34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 24,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 25,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 26,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 27,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffff24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 28,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffff34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 29,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 30,
"comment" : "empty signature",
"msg" : "54657374",
"sig" : "",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 31,
"comment" : "s missing",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 32,
"comment" : "signature too short",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 33,
"comment" : "signature too long",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826002020",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 34,
"comment" : "include pk in signature",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600419610a534af127f583b04818cdb7f0ff300b025f2e01682bcae33fd691cee039511df0cddc690ee978426e8b38e50ce5af7dcfba50f704c00",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 35,
"comment" : "prepending 0 byte to signature",
"msg" : "54657374",
"sig" : "005d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 36,
"comment" : "prepending 0 byte to s",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f2800031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 37,
"comment" : "appending 0 byte to signature",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98260000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 38,
"comment" : "removing 0 byte from signature",
"msg" : "5465737430",
"sig" : "dbd6384516ab6b0eb2d609414564ec217383b66040dfb0676128251ae24c1d7c179c21a9ee307dc13f8fe6550bc40187f093da85617bcf5d009d3ee8b798ad978b6e683bc4e911940ea82ea0b7e95dc24fe0b29e44663211892c2aaa3451379d22c289b94378f11fb700f1689d4a00d73e",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 39,
"comment" : "removing 0 byte from signature",
"msg" : "546573743535",
"sig" : "ce2b2fff0bf445a36813cf2a76e0cc5619a4f16ee53f0fe3cd46fc0414db7248b32fbda54bbb37e708d6238076ea12bf850b964b044520bb80fbaf0e1d1ed3bcab261462df5e7f2de73ac9cbae26dfa29015039acf90575961fc9b91b9ca276dae7d5fa805bd202c5579a0f4c66e801400",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 40,
"comment" : "dropping byte from signature",
"msg" : "546573743633",
"sig" : "c283ed36d78c275a5d02f7939aed2c4ef68320ae1bf6fc25e834b758046a6d52a480216a942dfe771f3bd307f4ce7d3f446e0824961bd5de80cda42b5cc38e6ec3d53f386978b9877d3c98a28ac8fc66630ffd178933a18de1aee23cab5011c9ff4c9277311b4c6c33acb8e82b8c693c00",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 41,
"comment" : "removing leading 0 byte from signature",
"msg" : "54657374333631",
"sig" : "62e629bd2b8f595df401c362c766216d45de89fceecd99c69d323b5c53ad5ac3ea7224963feba2f2895551d94f548248ef8597d2a959f880d59934a5e8f07847834d66ba1a6b09de5dba692172b13f768f0c29e8196144c130d2353445d63cbd0b690794fdad30a48e8bb7cc2504f80700",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 42,
"comment" : "modified bit 0 in R",
"msg" : "313233343030",
"sig" : "5cb94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280afc33a525116cc12e0d1c3a1fde6de518a6544f360d0fe18d5be7770b057a2bf792db4b7648fa84a6eaecae909e33fa59c5dfe4804ba2623",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 43,
"comment" : "modified bit 1 in R",
"msg" : "313233343030",
"sig" : "5fb94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280f91386c3e9dd9e7c9af7ca6bbef8b7a44ae3d68eeade449d7dfbb31de8419eb943e2ecbcdd06df5227e82b9ded519a56e70f0a1c0fc17b06",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 44,
"comment" : "modified bit 2 in R",
"msg" : "313233343030",
"sig" : "59b94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280f1aab07b4ad069dfafc01b4532e1e44cbf7177e1bdda197fc87434046db5b935afd9114ac5e1138eaead23c3b59dba9026d2da4a86fe800b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 45,
"comment" : "modified bit 7 in R",
"msg" : "313233343030",
"sig" : "ddb94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2807668402b7b093fc754019324077c1f842a7d2e35adf7b87094115cec459ad5419e162988ef42b1988d9b944d9d5a7ce09c6f342afa500839",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 46,
"comment" : "modified bit 8 in R",
"msg" : "313233343030",
"sig" : "5db84c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280279b70338586b9e13e669191cc0dfc2a937d50a6118758de04a4ca41f4877abdb971afa87fe4b83bc243b8dfd2cb368aa389a4cb11e83e31",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 47,
"comment" : "modified bit 16 in R",
"msg" : "313233343030",
"sig" : "5db94d53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280c7b847556b3a6f9447483899ab730a23004c695054dd57b1c3214fa87f632f39c8ff1471f0532b8eee4154930e1ca30d574b8f9e85b0432b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 48,
"comment" : "modified bit 31 in R",
"msg" : "313233343030",
"sig" : "5db94cd3101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2800b017917472b130a1cc1c8e995a252617d5ddaf1f3d48930b4876fa0d2cfedec90a8c85c8274892a1ca3b6cfce63ebfebc307210b844ae0c",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 49,
"comment" : "modified bit 32 in R",
"msg" : "313233343030",
"sig" : "5db94c53111f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2805f38f6371860fcc4f2ec515afd35cb05d8941e2448cc469a15b8537e758b16d46b123581613462c2bb20d8a07299ab795d0998e1e4277931",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 50,
"comment" : "modified bit 63 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f529f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff28017111ba6fefd45e2490f1d53a184007fa073470706d7f4a9606fcad2954e74c32116ba7701d225b76e55164e64df3245c1031f0df734bd31",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 51,
"comment" : "modified bit 64 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6d1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2808d7d0aa1fd81d0e31789921771c654338f96f0b557b615e3da55670271608a0e022e4e8cf393e309f8f6412281b6147e7fce42b089eb1e0c",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 52,
"comment" : "modified bit 97 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ca4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280b08d3be6ebf4e60bf6d74e105ea2fa9b965c62816bbd22ea3bb0c1acfd12300523ca76f94b6f789488a957fbeb212d713baccf95fd594f3d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 53,
"comment" : "modified bit 127 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7606fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280a23f54857e9b0f72b2ef90d2768834590464d75933ed08c454faa762b3702a2b631c33c339d05b2e24c20a8214f99af31f93f80f416a1129",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 54,
"comment" : "modified bit 240 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0881a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280734bdc399273d3403d934ceaae16e87a68c6bff6b77d8037ff41c97922498a58e704c29ab519d41bab70735f71fc26f589361e2b21754300",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 55,
"comment" : "modified bit 247 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0800a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280ba961cc8d0765c99d57470ee1c0c77f0a562a198fd0175eddb0c033e0fb8525328c5e2c516e2b00f73609c7f769195eb1a02ff54090d781f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 56,
"comment" : "modified bit 248 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a97b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280e72685907da9e5a64e4142ed02fc0c6bf95763201db5942aac055fa87e6fdd32e483fd21ed4110d5d7ef619b740fef2ad8a71fe821e42a2a",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 57,
"comment" : "modified bit 253 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880887b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280500646d67c74f13471f0ad034da530f7238fe7897e532af8ec2977643a410b1d054934df567e170276389e66b3f3ccb3c15aed239d04f72b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 58,
"comment" : "modified bit 254 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880e87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2807bb153b8e350aa736a91c921217578539600c1299ab76522ef8f6902d79c93f274073ee6beafe6200ecaf59f7cd11bb1c833f24bf30ed52d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 59,
"comment" : "modified bit 255 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880287b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2804a67b22be599d6433b87ea961c82c457ab50f64ac6b7efb0b2f90988927f83742303c278f8248e02d5679b41ed505aba0fb51110d0def810",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 60,
"comment" : "modified bit 440 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff3807f452efb0cd97dab5506028b7b876830dee02a9c0cbd140dcde509638d4d546c30856b2151bdf79930df5bbb11f2beb66bcdc25ad75f2116",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 61,
"comment" : "modified bit 441 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff0808d78231bb3c9a87c5b8d168fe05f8197503a3d73a6d700f436b5a76ab866388baa6930191a077aca7970058932c88b7f9e6ecb13c89dcd1d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 62,
"comment" : "modified bit 447 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cf72809e5a8406063fb3545f0fb627f841b2e3a85ad5d378018e8b58fe58e14ee5520d57abc9140e9c5a75a8b09ac3334dd0cad69b48771284321d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 63,
"comment" : "modified bit 448 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2811adf92201088e051ee48b57aecf46edfc68e5baeed5ae4910ba5681d370f75ab593811e18293ef0808581c254196bcbf2b4c454136a6711b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 64,
"comment" : "modified bit 449 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2825e06c3999e8308be439c40940b0075d3e4f65147c1608cbe6e9c432e33bed6686f9393ae2568f0ad60febcb4b6179c0d90d034e7c3c46810",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 65,
"comment" : "modified bit 454 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2c02456bbd141df048dbf1843be6d5fef402483314c2af547b361a09f3319489eaede43404df9faf634c1298d678b5261c808b0be3726013e39",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 66,
"comment" : "modified bit 455 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2007106d2a896a7fec6dee53eea272d9b6e738c340295416b50f39a9463a5635450b9f93c4c06737affd42ae06cee5879c96c0bd58a91345503",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 67,
"comment" : "R==0",
"msg" : "313233343030",
"sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027ab98ab862e4e7ec3361a45ac1993e9b47d9ac40db91faed752399cee0413122b47346594fd7d2c8949b43e4cabaf17d8339ea0e307023f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 68,
"comment" : "invalid R",
"msg" : "313233343030",
"sig" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd11bae33a0999fd3fd2bed6fa5577685e8fd595e79c006e58fd35f69f91b1d853553fb4006019a07725aa37773883dbe12253812887ac828",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 69,
"comment" : "all bits flipped in R",
"msg" : "313233343030",
"sig" : "a246b3acefe0ade093e0bc49f15b281f9042b63d175050b033d7619ba1f77f578471aa7a720b30dd6e58cfc0025bb947d5ee84b22bf7300d7f334e48141af0fade1469f5dedb851c9e725d27bd65012bada05e70cde641aad9ce0bea4983164f73816b6f13095e6b93eb03e850cad0cf0d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 70,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280241bd6142ddb02c0f9fa133955d3e610b4b27cb814227de8b241ef4e86402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9866",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 71,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28017602ec0bf9d7be34e8ad9c6c795533244e952675efdcbac9c65b9cb85402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98a6",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 72,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280fde9de16e5226d2af9a864e2ac1a2d756456ffc4f1b3693570ad4dc584402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 73,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280c9fd3fc42f2d50b84de67a197724e0faa43058801821a546173d76b882402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 74,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9866",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 75,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98a6",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 76,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 77,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28030d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d285402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "bIKlYsuAjRDWMr6JyFE-v2ySnzTd-oyfY8mWDvbjSKNSjIo_zC8ETjmj_FuUSS-PAy51SaIAmPlb",
"kid" : "none",
"kty" : "OKP",
"x" : "X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq_oJWGA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180",
"sk" : "6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a005fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq/oJWGA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 78,
"comment" : "RFC 8032",
"msg" : "",
"sig" : "533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "xOqwXTVwB8Yy89u0hImSTVUrCP4MNToNSh8ArNosRjr76mfF6NKHfF47w5emWZSe-AIelU4KEidO",
"kid" : "none",
"kty" : "OKP",
"x" : "Q7oo9DDN_0Vq5TFUX37NCsg0pV2TWMA3K_oMbGeYwIZq6gHrAHQoArhDjqTLghacI1FgYntMOpSA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480",
"sk" : "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a0043ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAQ7oo9DDN/0Vq5TFUX37NCsg0pV2TWMA3K/oMbGeYwIZq6gHrAHQoArhDjqTLghacI1FgYntMOpSA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 79,
"comment" : "RFC 8032: 1 octet",
"msg" : "03",
"sig" : "26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f4352541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cbcee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0ff3348ab21aa4adafd1d234441cf807c03a00",
"result" : "valid",
"flags" : []
},
{
"tcId" : 80,
"comment" : "RFC 8032: 1 octet with context",
"msg" : "03",
"sig" : "d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00",
"result" : "invalid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "zSPST3FCdOdENDI3uTKQ9RH2Ql-Y5kRZ_yA-iYUIP_32BQBVOrwOBc0CGEvbicTM1n4YeVEmfrMo",
"kid" : "none",
"kty" : "OKP",
"x" : "3OqeePNaG_NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl_OFh1xznExpUPqTLX36fHYsAaWRHABQA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400",
"sk" : "cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffdf60500553abc0e05cd02184bdb89c4ccd67e187951267eb328",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoA3OqeePNaG/NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl/OFh1xznExpUPqTLX36fHYsAaWRHABQA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 81,
"comment" : "RFC 8032: 11 bytes",
"msg" : "0c3e544074ec63b0265e0c",
"sig" : "1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d389dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b051068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5028961c9bf8ffd973fe5d5c206492b140e00",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "JYzdStoy7Zyf9U5jdWrlgvuPqyrHIfLI5nanJ2hRPZOfY93bVWCRM_Ka34bsmSncy1LBxf0v9-Ib",
"kid" : "none",
"kty" : "OKP",
"x" : "O6FtoMbyzB8wGHdAdW9eeY1rxfwBXXxjzJUQ7j_UStwk2OlotuRub5TRm5RTYXJr114UnvCYF_WA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580",
"sk" : "258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d939f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a003ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAO6FtoMbyzB8wGHdAdW9eeY1rxfwBXXxjzJUQ7j/UStwk2OlotuRub5TRm5RTYXJr114UnvCYF/WA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 82,
"comment" : "RFC 8032: 12 bytes",
"msg" : "64a65f3cdedcdd66811e2915",
"sig" : "7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4ae90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457eb1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861e72003cbae6d6b8b827e4e6c143064ff3c00",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "fvToRUQjZ1L7tWuPMaI6EOQoFPX1XKA3zcwRxkyaOylJwbtgcAMUYRcypsL-qY7rwCZqEak5cBAO",
"kid" : "none",
"kty" : "OKP",
"x" : "s9oHmwqkk6V3ICnwRnuuvuWoES2dOiJTI2HaKU97s4FcXcWeF2tNnzgcoJOOE8bAexdL5l36V46A"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb3815c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80",
"sk" : "7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b2949c1bb60700314611732a6c2fea98eebc0266a11a93970100e",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb3815c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAs9oHmwqkk6V3ICnwRnuuvuWoES2dOiJTI2HaKU97s4FcXcWeF2tNnzgcoJOOE8bAexdL5l36V46A\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 83,
"comment" : "RFC 8032: 13 bytes",
"msg" : "64a65f3cdedcdd66811e2915e7",
"sig" : "6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf56b4e7e0ba5519234d047155ac727a1053100",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "1l3zQa0T4AhWdoi67dqOnc3BfcAkl06ltCJ7ZTDjOb_yH5nmjKaWjzzKbf4PufT6tPoTXVVC6j8B",
"kid" : "none",
"kty" : "OKP",
"x" : "35cF9Y7bq4Asf4Njz-VWCrHGEywgqfHdFjSDom-KxTo51oCL9KHfvSYbCZuwOz-1CQbLKL2KCB8A"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00",
"sk" : "d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoA35cF9Y7bq4Asf4Njz+VWCrHGEywgqfHdFjSDom+KxTo51oCL9KHfvSYbCZuwOz+1CQbLKL2KCB8A\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 84,
"comment" : "RFC 8032: 64 bytes",
"msg" : "bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944",
"sig" : "554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b18dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722ef552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba5f30e88e36ec2703b349ca229c2670833900",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "LsX-PBcEWr2xNqXmqRPjKrda5otT0vwUm3flBBMtN1abfnZrp0oZvWFiNDohyFkKqc68qQFMY231",
"kid" : "none",
"kty" : "OKP",
"x" : "eXVvAU3P4gefXdnnGL5BceLvJIagjyUYb2v_Q6mTa5v-EkArCK5leYo9geIunsgOdpCGLvPU7ToA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00",
"sk" : "2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d37569b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a0079756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAeXVvAU3P4gefXdnnGL5BceLvJIagjyUYb2v/Q6mTa5v+EkArCK5leYo9geIunsgOdpCGLvPU7ToA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 85,
"comment" : "RFC 8032: 256 bytes",
"msg" : "15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567cfa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072fc1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a6039c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b590316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce012d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11",
"sig" : "c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc60987fd08527c1a8e80d5823e65cafe2a3d00",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "hy0JN4D103MN98ISZks3uKDyT1aBDaqDgs1Po_d2NOxE3FTxwu2b6ob6-3Yy2L4ZnqFl9a1V3Zzo",
"kid" : "none",
"kty" : "OKP",
"x" : "qBsuinClrJT_28ybrfw_6wgB8lhXi7EUrUTs4ewOeZ2gjv-4HF1oXAxW9k7srvjN8RzDhzeDjPQA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400",
"sk" : "872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAqBsuinClrJT/28ybrfw/6wgB8lhXi7EUrUTs4ewOeZ2gjv+4HF1oXAxW9k7srvjN8RzDhzeDjPQA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 86,
"comment" : "RFC 8032: 1023 bytes",
"msg" : "6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e972660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd323219b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab797172b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f52096cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db977025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f0410a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf9696149e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a6059d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87",
"sig" : "e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bddf7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed573603ce30d8bb761785dc30dbc320869e1a00",
"result" : "valid",
"flags" : []
}
]
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -42,10 +42,10 @@
"import": "./lib/esm/shortw.js",
"default": "./lib/shortw.js"
},
"./twisted": {
"types": "./lib/twisted.d.ts",
"import": "./lib/esm/twisted.js",
"default": "./lib/twisted.js"
"./twistede": {
"types": "./lib/twistede.d.ts",
"import": "./lib/esm/twistede.js",
"default": "./lib/twistede.js"
},
"./utils": {
"types": "./lib/utils.d.ts",

@ -211,7 +211,10 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
// invert on all of them. invert is very slow operation,
// so this improves performance massively.
static toAffineBatch(points: ExtendedPoint[]): Point[] {
const toInv = mod.invertBatch(points.map((p) => p.z), CURVE.P);
const toInv = mod.invertBatch(
points.map((p) => p.z),
CURVE.P
);
return points.map((p, i) => p.toAffine(toInv[i]));
}