From 2cba19bbaf5b59be02b4bef92bc74441305c7db3 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 9 Dec 2022 19:16:15 +0000 Subject: [PATCH 001/145] Shuffle things around, new variables, comments --- index.ts | 134 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 63 deletions(-) diff --git a/index.ts b/index.ts index a33c1f1..764cf6b 100644 --- a/index.ts +++ b/index.ts @@ -28,10 +28,41 @@ const CURVE = Object.freeze({ // Base point (x, y) aka generator point Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), + // For endomorphism, see below beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), }); +const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b; +const endo = { + beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), + // Split 256-bit K into 2 128-bit (k1, k2) for which k1 + k2 * lambda = K. + // Used for endomorphism https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066 + splitScalar(k: bigint) { + const { n } = CURVE; + 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('splitScalarEndo: Endomorphism failed, k=' + k); + } + return { k1neg, k1, k2neg, k2 }; + }, +}; +const fieldLen = 32; +const groupLen = 32; + // Cleaner js output if that's on a separate line. export { CURVE }; @@ -132,7 +163,7 @@ class JacobianPoint { // Fast algo for doubling 2 Jacobian Points when curve's a=0. // Note: cannot be reused for other curves when a != 0. - // From: http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + // From: https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l // Cost: 2M + 5S + 6add + 3*2 + 1*3 + 1*8. double(): JacobianPoint { const { x: X1, y: Y1, z: Z1 } = this; @@ -149,10 +180,9 @@ class JacobianPoint { return new JacobianPoint(X3, Y3, Z3); } - // Fast algo for adding 2 Jacobian Points when curve's a=0. - // Note: cannot be reused for other curves when a != 0. - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-1998-cmo-2 - // Cost: 12M + 4S + 6add + 1*2. + // Fast algo for adding 2 Jacobian Points. + // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2 + // Cost: 12M + 4S + 6add + 1*2 // Note: 2007 Bernstein-Lange (11M + 5S + 9add + 4*2) is actually 10% slower. add(other: JacobianPoint): JacobianPoint { if (!(other instanceof JacobianPoint)) throw new TypeError('JacobianPoint expected'); @@ -213,7 +243,7 @@ class JacobianPoint { } return p; } - let { k1neg, k1, k2neg, k2 } = splitScalarEndo(n); + let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n); let k1p = P0; let k2p = P0; let d: JacobianPoint = this; @@ -226,7 +256,7 @@ class JacobianPoint { } if (k1neg) k1p = k1p.negate(); if (k2neg) k2p = k2p.negate(); - k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z); + k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z); return k1p.add(k2p); } @@ -323,6 +353,10 @@ class JacobianPoint { } } // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() + // Even if the variable is still unused, there are some checks which will + // throw an exception, so compiler needs to prove they won't happen, which is hard. + // At this point there is a way to F be infinity-point even if p is not, + // which makes it less const-time: around 1 bigint multiply. return { p, f }; } @@ -341,12 +375,12 @@ class JacobianPoint { // Fake point, we use it to achieve constant-time multiplication. let fake: JacobianPoint; if (USE_ENDOMORPHISM) { - const { k1neg, k1, k2neg, k2 } = splitScalarEndo(n); + const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n); let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint); let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint); k1p = constTimeNegate(k1neg, k1p); k2p = constTimeNegate(k2neg, k2p); - k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z); + k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z); point = k1p.add(k2p); fake = f1p.add(f2p); } else { @@ -364,7 +398,9 @@ class JacobianPoint { toAffine(invZ?: bigint): Point { const { x, y, z } = this; const is0 = this.equals(JacobianPoint.ZERO); - if (invZ == null) invZ = is0 ? _8n : invert(z); // 8 was chosen arbitrarily + // If invZ was 0, we return zero point. However we still want to execute + // all operations, so we replace invZ with a random number, 8. + if (invZ == null) invZ = is0 ? _8n : invert(z); const iz1 = invZ; const iz2 = mod(iz1 * iz1); const iz3 = mod(iz2 * iz1); @@ -443,8 +479,8 @@ export class Point { // Schnorr doesn't support uncompressed points, so this is only for ECDSA private static fromUncompressedHex(bytes: Uint8Array) { - const x = bytesToNumber(bytes.subarray(1, 33)); - const y = bytesToNumber(bytes.subarray(33, 65)); + const x = bytesToNumber(bytes.subarray(1, fieldLen + 1)); + const y = bytesToNumber(bytes.subarray(fieldLen + 1, fieldLen * 2 + 1)); const point = new Point(x, y); point.assertValidity(); return point; @@ -698,8 +734,7 @@ export class Signature { } } -// Concatenates several Uint8Arrays into one. -// TODO: check if we're copying data instead of moving it and if that's ok +// Copies several Uint8Arrays into one. function concatBytes(...arrays: Uint8Array[]): Uint8Array { if (!arrays.every((b) => b instanceof Uint8Array)) throw new Error('Uint8Array list expected'); if (arrays.length === 1) return arrays[0]; @@ -730,10 +765,9 @@ function bytesToHex(uint8a: Uint8Array): string { const POW_2_256 = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000'); function numTo32bStr(num: bigint): string { if (typeof num !== 'bigint') throw new Error('Expected bigint'); - if (!(_0n <= num && num < POW_2_256)) throw new Error('Expected number < 2^256'); + if (!(_0n <= num && num < POW_2_256)) throw new Error('Expected number 0 <= n < 2^256'); return num.toString(16).padStart(64, '0'); } - function numTo32b(num: bigint): Uint8Array { const b = hexToBytes(numTo32bStr(num)); if (b.length !== 32) throw new Error('Error: expected 32 bytes'); @@ -886,33 +920,6 @@ function invertBatch(nums: bigint[], p: bigint = CURVE.P): bigint[] { return scratch; } -const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b; -const ENDO = { - a1: BigInt('0x3086d221a7d46bcde86c90e49284eb15'), - b1: -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3'), - a2: BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'), - b2: BigInt('0x3086d221a7d46bcde86c90e49284eb15'), // === a1 - POW_2_128: BigInt('0x100000000000000000000000000000000'), -}; -// Split 256-bit K into 2 128-bit (k1, k2) for which k1 + k2 * lambda = K. -// Used for endomorphism https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066 -function splitScalarEndo(k: bigint) { - const { n } = CURVE; - const { a1, b1, a2, b2, POW_2_128 } = ENDO; - 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('splitScalarEndo: Endomorphism failed, k=' + k); - } - return { k1neg, k1, k2neg, k2 }; -} - // Ensures ECDSA message hashes are 32 bytes and < curve order function truncateHash(hash: Uint8Array): bigint { const { n } = CURVE; @@ -1032,10 +1039,10 @@ function normalizePrivateKey(key: PrivKey): bigint { } else if (typeof key === 'number' && Number.isSafeInteger(key) && key > 0) { num = BigInt(key); } else if (typeof key === 'string') { - if (key.length !== 64) throw new Error('Expected 32 bytes of private key'); + if (key.length !== 2 * groupLen) throw new Error('Expected 32 bytes of private key'); num = hexToNumber(key); } else if (key instanceof Uint8Array) { - if (key.length !== 32) throw new Error('Expected 32 bytes of private key'); + if (key.length !== groupLen) throw new Error('Expected 32 bytes of private key'); num = bytesToNumber(key); } else { throw new TypeError('Expected valid private key'); @@ -1521,8 +1528,10 @@ export const utils = { */ hashToPrivateKey: (hash: Hex): Uint8Array => { hash = ensureBytes(hash); - if (hash.length < 40 || hash.length > 1024) - throw new Error('Expected 40-1024 bytes of private key as per FIPS 186'); + const minLen = fieldLen + 8; + if (hash.length < minLen || hash.length > 1024) { + throw new Error(`Expected ${minLen}-1024 bytes of private key as per FIPS 186`); + } const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n; return numTo32b(num); }, @@ -1540,8 +1549,21 @@ export const utils = { // Takes curve order + 64 bits from CSPRNG // so that modulo bias is neglible, matches FIPS 186 B.1.1. - randomPrivateKey: (): Uint8Array => { - return utils.hashToPrivateKey(utils.randomBytes(40)); + randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(fieldLen + 8)), + + /** + * 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it. + * 2. Precomputes point multiplication table. Is done by default on first `getPublicKey()` call. + * If you want your first getPublicKey to take 0.16ms instead of 20ms, make sure to call + * utils.precompute() somewhere without arguments first. + * @param windowSize 2, 4, 8, 16 + * @returns cached point + */ + precompute(windowSize = 8, point = Point.BASE): Point { + const cached = point === Point.BASE ? point : new Point(point.x, point.y); + cached._setWindowSize(windowSize); + cached.multiply(_3n); + return cached; }, sha256: async (...messages: Uint8Array[]): Promise => { @@ -1605,20 +1627,6 @@ export const utils = { return _sha256Sync(tagP, ...messages); }, - /** - * 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it. - * 2. Precomputes point multiplication table. Is done by default on first `getPublicKey()` call. - * If you want your first getPublicKey to take 0.16ms instead of 20ms, make sure to call - * utils.precompute() somewhere without arguments first. - * @param windowSize 2, 4, 8, 16 - * @returns cached point - */ - precompute(windowSize = 8, point = Point.BASE): Point { - const cached = point === Point.BASE ? point : new Point(point.x, point.y); - cached._setWindowSize(windowSize); - cached.multiply(_3n); - return cached; - }, // For tests _JacobianPoint: JacobianPoint, }; From 73cf04ef4f1d61b795a37cdb297b439d8b4ccbb6 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 6 Jan 2023 11:09:02 +0000 Subject: [PATCH 002/145] Bench: compressed keys --- test/benchmark.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/benchmark.js b/test/benchmark.js index 9d4427a..02e8e15 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -34,13 +34,13 @@ run(async (windowSize) => { // secp.getPublicKey('7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcb'); // }); await mark('getPublicKey(utils.randomPrivateKey())', 5000, () => { - secp.getPublicKey(secp.utils.randomPrivateKey()); + secp.getPublicKey(secp.utils.randomPrivateKey(), true); }); const priv = 'f6fc7fd5acaf8603709160d203253d5cd17daa307483877ad811ec8411df56d2'; - const pub = secp.getPublicKey(priv, false); + const pub = secp.getPublicKey(priv, true); const priv2 = '2e63f49054e1e44ccc2e6ef6ce387936efb16158f89cc302a2426e0b7fd66f66'; - const pub2 = secp.getPublicKey(priv2, false); + const pub2 = secp.getPublicKey(priv2, true); const msg = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef'; const signature = await secp.sign(msg, priv); From 3b72151034cf5daff25b8714ee249e4f7415ddd0 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 6 Jan 2023 11:14:12 +0000 Subject: [PATCH 003/145] Improve math --- index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 764cf6b..75f8156 100644 --- a/index.ts +++ b/index.ts @@ -866,7 +866,10 @@ function sqrtMod(x: bigint): bigint { const b223 = (pow2(b220, _3n) * b3) % P; const t1 = (pow2(b223, _23n) * b22) % P; const t2 = (pow2(t1, _6n) * b2) % P; - return pow2(t2, _2n); + const rt = pow2(t2, _2n); + const xc = (rt * rt) % P; + if (xc !== x) throw new Error('Cannot find square root'); + return rt; } // Inverses number over modulo From bcfb39359c1afcd6426f97e212a80825ccdf567f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 8 Jan 2023 15:17:15 +0000 Subject: [PATCH 004/145] Remove isCompressed der sigs, unused --- index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/index.ts b/index.ts index 75f8156..514854b 100644 --- a/index.ts +++ b/index.ts @@ -704,12 +704,11 @@ export class Signature { } // DER-encoded - toDERRawBytes(isCompressed = false) { - return hexToBytes(this.toDERHex(isCompressed)); + toDERRawBytes() { + return hexToBytes(this.toDERHex()); } - toDERHex(isCompressed = false) { + toDERHex() { const sHex = sliceDER(numberToHexUnpadded(this.s)); - if (isCompressed) return sHex; const rHex = sliceDER(numberToHexUnpadded(this.r)); const rLen = numberToHexUnpadded(rHex.length / 2); const sLen = numberToHexUnpadded(sHex.length / 2); From b161b1c8b855751306ffc8ace0c25545ae1a9434 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 8 Jan 2023 17:59:42 +0000 Subject: [PATCH 005/145] Backport curves changes: drbg, truncateHash, etc --- index.ts | 163 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 61 deletions(-) diff --git a/index.ts b/index.ts index 514854b..d25ddab 100644 --- a/index.ts +++ b/index.ts @@ -29,11 +29,12 @@ const CURVE = Object.freeze({ Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - // For endomorphism, see below + // Legacy, endo params are defined below beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), }); const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b; +// Endomorphism params const endo = { beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), // Split 256-bit K into 2 128-bit (k1, k2) for which k1 + k2 * lambda = K. @@ -60,8 +61,13 @@ const endo = { return { k1neg, k1, k2neg, k2 }; }, }; -const fieldLen = 32; -const groupLen = 32; + +// Placeholder for non-sha256 hashes +const fieldLen = 32; // Field element: their range is 0 to CURVE.P +const groupLen = 32; // Group element: their range is 1 to CURVE.n +const hashLen = 32; // Hash used with secp256k1, sha2-256 +const compressedLen = fieldLen + 1; // DER-encoded field element +const uncompressedLen = 2 * fieldLen + 1; // DER-encoded pair of field elements // Cleaner js output if that's on a separate line. export { CURVE }; @@ -81,7 +87,7 @@ function weierstrass(x: bigint): bigint { type Hex = Uint8Array | string; // Very few implementations accept numbers, we do it to ease learning curve type PrivKey = Hex | bigint | number; -// 33/65-byte ECDSA key, or 32-byte Schnorr key - not interchangeable +// compressed/uncompressed ECDSA key, or Schnorr key - not interchangeable type PubKey = Hex | Point; // ECDSA signature type Sig = Hex | Signature; @@ -105,6 +111,10 @@ class ShaError extends Error { } } +function assertJacPoint(other: unknown) { + if (!(other instanceof JacobianPoint)) throw new TypeError('JacobianPoint expected'); +} + /** * Jacobian Point works in 3d / jacobi coordinates: (x, y, z) ∋ (x=x/z², y=y/z³) * Default Point works in 2d / affine coordinates: (x, y) @@ -142,7 +152,7 @@ class JacobianPoint { * Compare one point to another. */ equals(other: JacobianPoint): boolean { - if (!(other instanceof JacobianPoint)) throw new TypeError('JacobianPoint expected'); + assertJacPoint(other); const { x: X1, y: Y1, z: Z1 } = this; const { x: X2, y: Y2, z: Z2 } = other; const Z1Z1 = mod(Z1 * Z1); @@ -185,7 +195,7 @@ class JacobianPoint { // Cost: 12M + 4S + 6add + 1*2 // Note: 2007 Bernstein-Lange (11M + 5S + 9add + 4*2) is actually 10% slower. add(other: JacobianPoint): JacobianPoint { - if (!(other instanceof JacobianPoint)) throw new TypeError('JacobianPoint expected'); + assertJacPoint(other); const { x: X1, y: Y1, z: Z1 } = this; const { x: X2, y: Y2, z: Z2 } = other; if (X2 === _0n || Y2 === _0n) return this; @@ -453,8 +463,8 @@ export class Point { } /** - * Supports compressed Schnorr (32-byte) and ECDSA (33-byte) points - * @param bytes 32/33 bytes + * Supports compressed Schnorr and ECDSA points + * @param bytes * @returns Point instance */ private static fromCompressedHex(bytes: Uint8Array) { @@ -488,19 +498,22 @@ export class Point { /** * Converts hash string or Uint8Array to Point. - * @param hex 32-byte (schnorr) or 33/65-byte (ECDSA) hex + * @param hex schnorr or ECDSA hex */ static fromHex(hex: Hex): Point { const bytes = ensureBytes(hex); const len = bytes.length; const header = bytes[0]; // this.assertValidity() is done inside of those two functions - if (len === 32 || (len === 33 && (header === 0x02 || header === 0x03))) { + // Schnorr + if (len === fieldLen) return this.fromCompressedHex(bytes); + // ECDSA + if (len === compressedLen && (header === 0x02 || header === 0x03)) { return this.fromCompressedHex(bytes); } - if (len === 65 && header === 0x04) return this.fromUncompressedHex(bytes); + if (len === uncompressedLen && header === 0x04) return this.fromUncompressedHex(bytes); throw new Error( - `Point.fromHex: received invalid point. Expected 32-33 compressed bytes or 65 uncompressed bytes, not ${len}` + `Point.fromHex: received invalid point. Expected 32-${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}` ); } @@ -700,7 +713,7 @@ export class Signature { } normalizeS(): Signature { - return this.hasHighS() ? new Signature(this.r, CURVE.n - this.s) : this; + return this.hasHighS() ? new Signature(this.r, mod(-this.s, CURVE.n)) : this; } // DER-encoded @@ -710,9 +723,11 @@ export class Signature { toDERHex() { const sHex = sliceDER(numberToHexUnpadded(this.s)); const rHex = sliceDER(numberToHexUnpadded(this.r)); - const rLen = numberToHexUnpadded(rHex.length / 2); - const sLen = numberToHexUnpadded(sHex.length / 2); - const length = numberToHexUnpadded(rHex.length / 2 + sHex.length / 2 + 4); + const sHexL = sHex.length / 2; + const rHexL = rHex.length / 2; + const sLen = numberToHexUnpadded(sHexL); + const rLen = numberToHexUnpadded(rHexL); + const length = numberToHexUnpadded(rHexL + sHexL + 4); return `30${length}02${rLen}${rHex}02${sLen}${sHex}`; } @@ -922,15 +937,19 @@ function invertBatch(nums: bigint[], p: bigint = CURVE.P): bigint[] { return scratch; } +// Can be replaced by bytesToNumber(). Placeholder for non-sha256 hashes +function bits2int_2(bytes: Uint8Array) { + const delta = bytes.length * 8 - groupLen * 8; // 256-256=0 for sha256/secp256k1 + const num = bytesToNumber(bytes); + return delta > 0 ? num >> BigInt(delta) : num; +} + // Ensures ECDSA message hashes are 32 bytes and < curve order -function truncateHash(hash: Uint8Array): bigint { +function truncateHash(hash: Uint8Array, truncateOnly = false): bigint { + const h = bits2int_2(hash); + if (truncateOnly) return h; const { n } = CURVE; - const byteLength = hash.length; - const delta = byteLength * 8 - 256; // size of curve.n - let h = bytesToNumber(hash); - if (delta > 0) h = h >> BigInt(delta); - if (h >= n) h -= n; - return h; + return h >= n ? h - n : h; } // RFC6979 related code @@ -948,10 +967,13 @@ class HmacDrbg { k: Uint8Array; v: Uint8Array; counter: number; - constructor() { - // Step B, Step C - this.v = new Uint8Array(32).fill(1); - this.k = new Uint8Array(32).fill(0); + constructor(public hashLen: number, public qByteLen: number) { + if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number'); + if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number'); + + // Step B, Step C: set hashLen to 8*ceil(hlen/8) + this.v = new Uint8Array(hashLen).fill(1); + this.k = new Uint8Array(hashLen).fill(0); this.counter = 0; } private hmac(...values: Uint8Array[]) { @@ -987,24 +1009,40 @@ class HmacDrbg { async generate(): Promise { this.incr(); - this.v = await this.hmac(this.v); - return this.v; + let len = 0; + const out: Uint8Array[] = []; + while (len < this.qByteLen) { + this.v = await this.hmac(this.v); + const sl = this.v.slice(); + out.push(sl); + len += this.v.length; + } + return concatBytes(...out); } generateSync(): Uint8Array { this.checkSync(); this.incr(); - this.v = this.hmacSync(this.v); - return this.v; + let len = 0; + const out: Uint8Array[] = []; + while (len < this.qByteLen) { + this.v = this.hmacSync(this.v); + const sl = this.v.slice(); + out.push(sl); + len += this.v.length; + } + return concatBytes(...out); } // There is no need in clean() method // It's useless, there are no guarantees with JS GC // whether bigints are removed even if you clean Uint8Arrays. } +// Valid scalars are [1, n-1] function isWithinCurveOrder(num: bigint): boolean { return _0n < num && num < CURVE.n; } +// Valid field elements are [1, p-1] function isValidFieldElement(num: bigint): boolean { return _0n < num && num < CURVE.P; } @@ -1017,20 +1055,27 @@ function isValidFieldElement(num: bigint): boolean { * @param d private key * @returns Signature with its point on curve Q OR undefined if params were invalid */ -function kmdToSig(kBytes: Uint8Array, m: bigint, d: bigint): RecoveredSig | undefined { - const k = bytesToNumber(kBytes); +function kmdToSig(kBytes: Uint8Array, m: bigint, d: bigint, lowS = true): RecoveredSig | undefined { + const { n } = CURVE; + const k = truncateHash(kBytes, true); if (!isWithinCurveOrder(k)) return; // Important: all mod() calls in the function must be done over `n` - const { n } = CURVE; + const kinv = invert(k, n); const q = Point.BASE.multiply(k); // r = x mod n const r = mod(q.x, n); if (r === _0n) return; - // s = (1/k * (m + dr) mod n - const s = mod(invert(k, n) * mod(m + d * r, n), n); + // s = (m + dr)/k mod n where x/k == x*inv(k) + const s = mod(kinv * mod(m + d * r, n), n); if (s === _0n) return; - const sig = new Signature(r, s); - const recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n); + + // Recovery bit adjustment + let sig = new Signature(r, s); + let recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n); + if (lowS && sig.hasHighS()) { + sig = sig.normalizeS(); + recovery ^= 1; + } return { sig, recovery }; } @@ -1085,7 +1130,7 @@ function normalizeSignature(signature: Sig): Signature { /** * Computes public key for secp256k1 private key. * @param privateKey 32-byte private key - * @param isCompressed whether to return compact (33-byte), or full (65-byte) key + * @param isCompressed whether to return compact, or full key * @returns Public key, full by default; short when isCompressed=true */ export function getPublicKey(privateKey: PrivKey, isCompressed = false): Uint8Array { @@ -1097,7 +1142,7 @@ export function getPublicKey(privateKey: PrivKey, isCompressed = false): Uint8Ar * @param msgHash message hash * @param signature DER or compact sig * @param recovery 0 or 1 - * @param isCompressed whether to return compact (33-byte), or full (65-byte) key + * @param isCompressed whether to return compact, or full key * @returns Public key, full by default; short when isCompressed=true */ export function recoverPublicKey( @@ -1116,8 +1161,8 @@ function isProbPub(item: PrivKey | PubKey): boolean { const arr = item instanceof Uint8Array; const str = typeof item === 'string'; const len = (arr || str) && (item as Hex).length; - if (arr) return len === 33 || len === 65; - if (str) return len === 66 || len === 130; + if (arr) return len === compressedLen || len === uncompressedLen; + if (str) return len === compressedLen * 2 || len === uncompressedLen * 2; if (item instanceof Point) return true; return false; } @@ -1128,7 +1173,7 @@ function isProbPub(item: PrivKey | PubKey): boolean { * 2. Checks for the public key of being on-curve * @param privateA private key * @param publicB different public key - * @param isCompressed whether to return compact (33-byte), or full (65-byte) key + * @param isCompressed whether to return compact, or full key * @returns shared public key */ export function getSharedSecret( @@ -1152,7 +1197,7 @@ type SignOutput = Uint8Array | [Uint8Array, number]; // RFC6979 methods function bits2int(bytes: Uint8Array) { - const slice = bytes.length > 32 ? bytes.slice(0, 32) : bytes; + const slice = bytes.length > fieldLen ? bytes.slice(0, fieldLen) : bytes; return bytesToNumber(slice); } function bits2octets(bytes: Uint8Array): Uint8Array { @@ -1175,9 +1220,9 @@ function initSigArgs(msgHash: Hex, privateKey: PrivKey, extraEntropy?: Entropy) const seedArgs = [int2octets(d), bits2octets(h1)]; // RFC6979 3.6: additional k' could be provided if (extraEntropy != null) { - if (extraEntropy === true) extraEntropy = utils.randomBytes(32); + if (extraEntropy === true) extraEntropy = utils.randomBytes(fieldLen); const e = ensureBytes(extraEntropy); - if (e.length !== 32) throw new Error('sign: Expected 32 bytes of extra data'); + if (e.length !== fieldLen) throw new Error(`sign: Expected ${fieldLen} bytes of extra data`); seedArgs.push(e); } // seed is constructed from private key and message @@ -1191,12 +1236,8 @@ function initSigArgs(msgHash: Hex, privateKey: PrivKey, extraEntropy?: Entropy) // Takes signature with its recovery bit, normalizes it // Produces DER/compact signature and proper recovery bit function finalizeSig(recSig: RecoveredSig, opts: OptsNoRecov | OptsRecov): SignOutput { - let { sig, recovery } = recSig; - const { canonical, der, recovered } = Object.assign({ canonical: true, der: true }, opts); - if (canonical && sig.hasHighS()) { - sig = sig.normalizeS(); - recovery ^= 1; - } + const { sig, recovery } = recSig; + const { der, recovered } = Object.assign({ canonical: true, der: true }, opts); const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes(); return recovered ? [hashed, recovery] : hashed; } @@ -1228,10 +1269,10 @@ async function sign(msgHash: Hex, privKey: PrivKey, opts: Opts = {}): Promise { hash = ensureBytes(hash); - const minLen = fieldLen + 8; + const minLen = groupLen + 8; if (hash.length < minLen || hash.length > 1024) { - throw new Error(`Expected ${minLen}-1024 bytes of private key as per FIPS 186`); + throw new Error(`Expected valid bytes of private key as per FIPS 186`); } const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n; return numTo32b(num); @@ -1550,8 +1591,8 @@ export const utils = { }, // Takes curve order + 64 bits from CSPRNG - // so that modulo bias is neglible, matches FIPS 186 B.1.1. - randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(fieldLen + 8)), + // so that modulo bias is neglible, matches FIPS 186 B.4.1. + randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)), /** * 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it. From 9f3b1e56bed1cdac0cbadea9bd6a713e32b763e7 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 8 Jan 2023 18:41:57 +0000 Subject: [PATCH 006/145] Add support for recovery_bit=2,3. Closes gh-72 --- index.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/index.ts b/index.ts index d25ddab..e6f3167 100644 --- a/index.ts +++ b/index.ts @@ -533,19 +533,17 @@ export class Point { * ``` */ static fromSignature(msgHash: Hex, signature: Sig, recovery: number): Point { - msgHash = ensureBytes(msgHash); - const h = truncateHash(msgHash); const { r, s } = normalizeSignature(signature); - if (recovery !== 0 && recovery !== 1) { - throw new Error('Cannot recover signature: invalid recovery bit'); - } - const prefix = recovery & 1 ? '03' : '02'; - const R = Point.fromHex(prefix + numTo32bStr(r)); + if (![0, 1, 2, 3].includes(recovery)) throw new Error('Cannot recover: invalid recovery bit'); + const h = truncateHash(ensureBytes(msgHash)); const { n } = CURVE; - const rinv = invert(r, n); + const radj = (recovery === 2 || recovery === 3) ? r + n : r; + const rinv = invert(radj, n); // Q = u1⋅G + u2⋅R const u1 = mod(-h * rinv, n); const u2 = mod(s * rinv, n); + const prefix = recovery & 1 ? '03' : '02'; + const R = Point.fromHex(prefix + numTo32bStr(radj)); const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); if (!Q) throw new Error('Cannot recover signature: point at infinify'); Q.assertValidity(); @@ -1069,8 +1067,8 @@ function kmdToSig(kBytes: Uint8Array, m: bigint, d: bigint, lowS = true): Recove const s = mod(kinv * mod(m + d * r, n), n); if (s === _0n) return; - // Recovery bit adjustment let sig = new Signature(r, s); + // Recovery bit is usually 0 or 1; rarely it's 2 or 3, when q.x > n let recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n); if (lowS && sig.hasHighS()) { sig = sig.normalizeS(); @@ -1258,7 +1256,7 @@ function finalizeSig(recSig: RecoveredSig, opts: OptsNoRecov | OptsRecov): SignO * sign(m, d, k) where * (x, y) = G × k * r = x mod n - * s = (1/k * (m + dr) mod n + * s = (m + dr)/k mod n * ``` * @param opts `recovered, canonical, der, extraEntropy` */ @@ -1267,11 +1265,11 @@ async function sign(msgHash: Hex, privKey: PrivKey, opts?: OptsNoRecov): Promise async function sign(msgHash: Hex, privKey: PrivKey, opts: Opts = {}): Promise { // Steps A, D of RFC6979 3.2. const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); - let sig: RecoveredSig | undefined; // Steps B, C, D, E, F, G const drbg = new HmacDrbg(hashLen, groupLen); await drbg.reseed(seed); // Step H3, repeat until k is in range [1, n-1] + let sig: RecoveredSig | undefined; while (!(sig = kmdToSig(await drbg.generate(), m, d, opts.canonical))) await drbg.reseed(); return finalizeSig(sig, opts); } @@ -1286,11 +1284,11 @@ function signSync(msgHash: Hex, privKey: PrivKey, opts?: OptsNoRecov): U8A; function signSync(msgHash: Hex, privKey: PrivKey, opts: Opts = {}): SignOutput { // Steps A, D of RFC6979 3.2. const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); - let sig: RecoveredSig | undefined; // Steps B, C, D, E, F, G const drbg = new HmacDrbg(hashLen, groupLen); drbg.reseedSync(seed); // Step H3, repeat until k is in range [1, n-1] + let sig: RecoveredSig | undefined; while (!(sig = kmdToSig(drbg.generateSync(), m, d, opts.canonical))) drbg.reseedSync(); return finalizeSig(sig, opts); } From a276a1c3639d1854420a1c78010280c902857ec1 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 8 Jan 2023 19:04:09 +0000 Subject: [PATCH 007/145] Lint --- index.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/index.ts b/index.ts index e6f3167..0b37042 100644 --- a/index.ts +++ b/index.ts @@ -537,7 +537,7 @@ export class Point { if (![0, 1, 2, 3].includes(recovery)) throw new Error('Cannot recover: invalid recovery bit'); const h = truncateHash(ensureBytes(msgHash)); const { n } = CURVE; - const radj = (recovery === 2 || recovery === 3) ? r + n : r; + const radj = recovery === 2 || recovery === 3 ? r + n : r; const rinv = invert(radj, n); // Q = u1⋅G + u2⋅R const u1 = mod(-h * rinv, n); @@ -852,11 +852,13 @@ function pow2(x: bigint, power: bigint): bigint { return res; } -// 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 +/** + * Allows to compute square root √y 2x faster. + * To calculate √y, we need to exponentiate it to a very big number: + * `y² = x³ + ax + b; y = y² ^ (p+1)/4` + * We are unwrapping the loop and multiplying it bit-by-bit. + * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] + */ function sqrtMod(x: bigint): bigint { const { P } = CURVE; const _6n = BigInt(6); From fd51da079a21195963d0feb1fe7c035d7703b6a8 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 8 Jan 2023 19:50:45 +0000 Subject: [PATCH 008/145] Release 1.7.1. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 422d3c8..5fb67d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@noble/secp256k1", - "version": "1.7.0", + "version": "1.7.1", "description": "Fastest JS implementation of secp256k1. Independently audited, high-security, 0-dependency ECDSA & Schnorr signatures", "files": [ "lib" From e125abdd2f42b2ad4cf5f4a1b7927d7737b7becf Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 9 Jan 2023 16:50:32 +0000 Subject: [PATCH 009/145] Add tests for (p-p)==0. gh-91. --- test/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/index.ts b/test/index.ts index a20f40c..a118c1f 100644 --- a/test/index.ts +++ b/test/index.ts @@ -123,9 +123,8 @@ describe('secp256k1', () => { if (expected) { expect(p.add(q).toHex(true)).toBe(expected); } else { - if (!p.equals(q.negate())) { - expect(() => p.add(q).toHex(true)).toThrowError(); - } + if (p.equals(q.negate())) expect(p.add(q).toHex(true)).toBe(secp.Point.ZERO.toHex(true)); + else expect(() => p.add(q).toHex(true)).toThrowError(); } } }); From a1a990d6bbe3c51f3dc3fdfaac4629ee6789d86a Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 13 Jan 2023 22:09:50 +0000 Subject: [PATCH 010/145] Prepare tests for micro --- test/index.ts | 419 ++++++++++++++++++++++++++------------------------ 1 file changed, 217 insertions(+), 202 deletions(-) diff --git a/test/index.ts b/test/index.ts index a118c1f..0433537 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,7 +1,7 @@ import * as fc from 'fast-check'; import * as secp from '..'; import { readFileSync } from 'fs'; -import { createHash } from 'crypto'; +// import { createHash } from 'crypto'; import * as sysPath from 'path'; import * as ecdsa from './vectors/ecdsa.json'; import * as ecdh from './vectors/ecdh.json'; @@ -15,10 +15,10 @@ const FC_BIGINT = fc.bigInt(1n + 1n, secp.CURVE.n - 1n); // prettier-ignore const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxy', secp.CURVE.n + 2n]; -secp.utils.sha256Sync = (...msgs) => - createHash('sha256') - .update(secp.utils.concatBytes(...msgs)) - .digest(); +// secp.utils.sha256Sync = (...msgs) => +// createHash('sha256') +// .update(secp.utils.concatBytes(...msgs)) +// .digest(); const toBEHex = (n: number | bigint) => n.toString(16).padStart(64, '0'); const hex = secp.utils.bytesToHex; @@ -57,26 +57,26 @@ describe('secp256k1', () => { expect(() => secp.getPublicKey(item as any)).toThrowError(); } }); - it('precompute', () => { - secp.utils.precompute(4); - const data = privatesTxt - .split('\n') - .filter((line) => line) - .map((line) => line.split(':')); - for (let [priv, x, y] of data) { - const point = secp.Point.fromPrivateKey(BigInt(priv)); - expect(toBEHex(point.x)).toBe(x); - expect(toBEHex(point.y)).toBe(y); - - const point2 = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))); - expect(toBEHex(point2.x)).toBe(x); - expect(toBEHex(point2.y)).toBe(y); - - const point3 = secp.Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv))))); - expect(toBEHex(point3.x)).toBe(x); - expect(toBEHex(point3.y)).toBe(y); - } - }); + // it('precompute', () => { + // // secp.utils.precompute(4); + // const data = privatesTxt + // .split('\n') + // .filter((line) => line) + // .map((line) => line.split(':')); + // for (let [priv, x, y] of data) { + // const point = secp.Point.fromPrivateKey(BigInt(priv)); + // expect(toBEHex(point.x)).toBe(x); + // expect(toBEHex(point.y)).toBe(y); + + // const point2 = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))); + // expect(toBEHex(point2.x)).toBe(x); + // expect(toBEHex(point2.y)).toBe(y); + + // const point3 = secp.Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv))))); + // expect(toBEHex(point3.x)).toBe(x); + // expect(toBEHex(point3.y)).toBe(y); + // } + // }); describe('Point', () => { it('.isValidPoint()', () => { for (const vector of points.valid.isPoint) { @@ -123,8 +123,11 @@ describe('secp256k1', () => { if (expected) { expect(p.add(q).toHex(true)).toBe(expected); } else { - if (p.equals(q.negate())) expect(p.add(q).toHex(true)).toBe(secp.Point.ZERO.toHex(true)); - else expect(() => p.add(q).toHex(true)).toThrowError(); + if (p.equals(q.negate())) { + expect(p.add(q).toHex(true)).toBe(secp.Point.ZERO.toHex(true)); + } else { + expect(() => p.add(q).toHex(true)).toThrowError(); + } } } }); @@ -152,6 +155,7 @@ describe('secp256k1', () => { } } for (const num of [0n, 0, -1n, -1, 1.1]) { + // @ts-ignore expect(() => secp.Point.BASE.multiply(num)).toThrowError(); } }); @@ -179,21 +183,21 @@ describe('secp256k1', () => { ); }); - it('.fromDERHex() roundtrip', () => { - fc.assert( - fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { - const sig = new secp.Signature(r, s); - expect(secp.Signature.fromDER(sig.toDERHex())).toEqual(sig); - }) - ); - }); + // it('.fromDERHex() roundtrip', () => { + // fc.assert( + // fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { + // const sig = new secp.Signature(r, s); + // expect(secp.Signature.fromDER(sig.toDERHex())).toEqual(sig); + // }) + // ); + // }); }); describe('.sign()', () => { it('should create deterministic signatures with RFC 6979', async () => { for (const vector of ecdsa.valid) { let usig = await secp.sign(vector.m, vector.d, { der: false }); - let sig = hex(usig); + let sig = usig.toCompactHex(); const vsig = vector.signature; expect(sig.slice(0, 64)).toBe(vsig.slice(0, 64)); expect(sig.slice(64, 128)).toBe(vsig.slice(64, 128)); @@ -215,57 +219,57 @@ describe('secp256k1', () => { expect(async () => await secp.sign('')).rejects.toThrowError(); }); - it('should create correct DER encoding against libsecp256k1', async () => { - const CASES = [ - [ - 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', - '304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b', - ], - [ - '5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82', - '3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c', - ], - [ - '0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808', - '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', - ], - ]; - const privKey = hexToBytes( - '0101010101010101010101010101010101010101010101010101010101010101' - ); - for (let [msg, exp] of CASES) { - const res = await secp.sign(msg, privKey, { extraEntropy: undefined }); - expect(hex(res)).toBe(exp); - const rs = secp.Signature.fromDER(res).toCompactHex(); - expect(secp.Signature.fromCompact(rs).toDERHex()).toBe(exp); - } - }); - it('sign ecdsa extraData', async () => { - const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; - const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; - const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; - const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; - const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - - for (const e of ecdsa.extraEntropy) { - const sign = async (extraEntropy?: string) => { - const s = await secp.sign(e.m, e.d, { der: false, extraEntropy }); - return hex(s); - }; - expect(await sign()).toBe(e.signature); - expect(await sign(ent1)).toBe(e.extraEntropy0); - expect(await sign(ent2)).toBe(e.extraEntropy1); - expect(await sign(ent3)).toBe(e.extraEntropyRand); - expect(await sign(ent4)).toBe(e.extraEntropyN); - expect(await sign(ent5)).toBe(e.extraEntropyMax); - } - }); + // it('should create correct DER encoding against libsecp256k1', async () => { + // const CASES = [ + // [ + // 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', + // '304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b', + // ], + // [ + // '5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82', + // '3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c', + // ], + // [ + // '0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808', + // '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', + // ], + // ]; + // const privKey = hexToBytes( + // '0101010101010101010101010101010101010101010101010101010101010101' + // ); + // for (let [msg, exp] of CASES) { + // const res = await secp.sign(msg, privKey, { extraEntropy: undefined }); + // expect(hex(res)).toBe(exp); + // const rs = secp.Signature.fromDER(res).toCompactHex(); + // expect(secp.Signature.fromCompact(rs).toDERHex()).toBe(exp); + // } + // }); + // it('sign ecdsa extraData', async () => { + // const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; + // const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; + // const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; + // const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; + // const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; + + // for (const e of ecdsa.extraEntropy) { + // const sign = async (extraEntropy?: string) => { + // const s = await secp.sign(e.m, e.d, { der: false, extraEntropy }); + // return s.toCompactHex(); + // }; + // expect(await sign()).toBe(e.signature); + // expect(await sign(ent1)).toBe(e.extraEntropy0); + // expect(await sign(ent2)).toBe(e.extraEntropy1); + // expect(await sign(ent3)).toBe(e.extraEntropyRand); + // expect(await sign(ent4)).toBe(e.extraEntropyN); + // expect(await sign(ent5)).toBe(e.extraEntropyMax); + // } + // }); }); describe('.verify()', () => { it('should verify signature', async () => { const MSG = '01'.repeat(32); - const PRIV_KEY = 0x2n; + const PRIV_KEY = secp.utils.numToField(0x2n); const signature = await secp.sign(MSG, PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY); expect(publicKey.length).toBe(65); @@ -273,8 +277,8 @@ describe('secp256k1', () => { }); it('should not verify signature with wrong public key', async () => { const MSG = '01'.repeat(32); - const PRIV_KEY = 0x2n; - const WRONG_PRIV_KEY = 0x22n; + const PRIV_KEY = secp.utils.numToField(0x2n); + const WRONG_PRIV_KEY = secp.utils.numToField(0x22n); const signature = await secp.sign(MSG, PRIV_KEY); const publicKey = secp.Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); expect(publicKey.length).toBe(130); @@ -282,7 +286,7 @@ describe('secp256k1', () => { }); it('should not verify signature with wrong hash', async () => { const MSG = '01'.repeat(32); - const PRIV_KEY = 0x2n; + const PRIV_KEY = secp.utils.numToField(0x2n); const WRONG_MSG = '11'.repeat(32); const signature = await secp.sign(MSG, PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY); @@ -295,8 +299,9 @@ describe('secp256k1', () => { FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), async (privKey, msg) => { - const pub = secp.getPublicKey(privKey); - const sig = await secp.sign(msg, privKey); + const pk = secp.utils.numToField(privKey); + const pub = secp.getPublicKey(pk); + const sig = await secp.sign(msg, pk); expect(secp.verify(sig, msg, pub)).toBeTruthy(); } ) @@ -319,7 +324,7 @@ describe('secp256k1', () => { // @ts-ignore signature.s = s; - const verified = secp.verify(signature, msg, pub); + const verified = secp.verify(signature, msg, pub.toRawBytes()); // Verifies, but it shouldn't, because signature S > curve order expect(verified).toBeFalsy(); }); @@ -329,7 +334,7 @@ describe('secp256k1', () => { const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; const r = 104546003225722045112039007203142344920046999340768276760147352389092131869133n; const s = 96900796730960181123786672629079577025401317267213807243199432755332205217369n; - const pub = new secp.Point(x, y); + const pub = new secp.Point(x, y).toRawBytes(); const sig = new secp.Signature(r, s); expect(secp.verify(sig, msg, pub)).toBeFalsy(); }); @@ -339,9 +344,9 @@ describe('secp256k1', () => { const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n; const r = 432420386565659656852420866390673177323n; const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n; - const pub = new secp.Point(x, y); + const pub = new secp.Point(x, y).toRawBytes(); const sig = new secp.Signature(r, s); - expect(secp.verify(sig, msg, pub, { strict: false })).toBeTruthy(); + expect(secp.verify(sig, msg, pub, { lowS: false })).toBeTruthy(); }); it('should not verify invalid deterministic signatures with RFC 6979', () => { for (const vector of ecdsa.invalid.verify) { @@ -351,75 +356,75 @@ describe('secp256k1', () => { }); }); - describe('schnorr', () => { - // index,secret key,public key,aux_rand,message,signature,verification result,comment - const vectors = schCsv - .split('\n') - .map((line: string) => line.split(',')) - .slice(1, -1); - for (let vec of vectors) { - const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec; - it(`should sign with Schnorr scheme vector ${index}`, async () => { - if (sec) { - expect(hex(secp.schnorr.getPublicKey(sec))).toBe(pub.toLowerCase()); - const sig = await secp.schnorr.sign(msg, sec, rnd); - const sigS = secp.schnorr.signSync(msg, sec, rnd); - expect(hex(sig)).toBe(expSig.toLowerCase()); - expect(hex(sigS)).toBe(expSig.toLowerCase()); - expect(await secp.schnorr.verify(sigS, msg, pub)).toBe(true); - expect(secp.schnorr.verifySync(sig, msg, pub)).toBe(true); - } else { - const passed = await secp.schnorr.verify(expSig, msg, pub); - const passedS = secp.schnorr.verifySync(expSig, msg, pub); - if (passes === 'TRUE') { - expect(passed).toBeTruthy(); - expect(passedS).toBeTruthy(); - } else { - expect(passed).toBeFalsy(); - expect(passedS).toBeFalsy(); - } - } - }); - } - }); - - describe('.recoverPublicKey()', () => { - it('should recover public key from recovery bit', async () => { - const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; - const privateKey = 123456789n; - const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); - const [signature, recovery] = await secp.sign(message, privateKey, { recovered: true }); - const recoveredPubkey = secp.recoverPublicKey(message, signature, recovery); - expect(recoveredPubkey).not.toBe(null); - expect(hex(recoveredPubkey!)).toBe(publicKey); - expect(secp.verify(signature, message, publicKey)).toBe(true); - }); - it('should not recover zero points', () => { - const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; - const sig = - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; - const recovery = 0; - expect(() => secp.recoverPublicKey(msgHash, sig, recovery)).toThrowError(); - }); - it('should handle all-zeros msghash', async () => { - const privKey = secp.utils.randomPrivateKey(); - const pub = secp.getPublicKey(privKey); - const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; - const [sig, rec] = await secp.sign(zeros, privKey, { recovered: true }); - const recoveredKey = secp.recoverPublicKey(zeros, sig, rec); - expect(recoveredKey).toEqual(pub); - }); - it('should handle RFC 6979 vectors', async () => { - for (const vector of ecdsa.valid) { - if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue; - let [usig, rec] = await secp.sign(vector.m, vector.d, { der: false, recovered: true }); - let sig = hex(usig); - const vpub = secp.getPublicKey(vector.d); - const recovered = secp.recoverPublicKey(vector.m, sig, rec)!; - expect(hex(recovered)).toBe(hex(vpub)); - } - }); - }); + // describe('schnorr', () => { + // // index,secret key,public key,aux_rand,message,signature,verification result,comment + // const vectors = schCsv + // .split('\n') + // .map((line: string) => line.split(',')) + // .slice(1, -1); + // for (let vec of vectors) { + // const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec; + // it(`should sign with Schnorr scheme vector ${index}`, async () => { + // if (sec) { + // expect(hex(secp.schnorr.getPublicKey(sec))).toBe(pub.toLowerCase()); + // const sig = await secp.schnorr.sign(msg, sec, rnd); + // const sigS = secp.schnorr.signSync(msg, sec, rnd); + // expect(hex(sig)).toBe(expSig.toLowerCase()); + // expect(hex(sigS)).toBe(expSig.toLowerCase()); + // expect(await secp.schnorr.verify(sigS, msg, pub)).toBe(true); + // expect(secp.schnorr.verifySync(sig, msg, pub)).toBe(true); + // } else { + // const passed = await secp.schnorr.verify(expSig, msg, pub); + // const passedS = secp.schnorr.verifySync(expSig, msg, pub); + // if (passes === 'TRUE') { + // expect(passed).toBeTruthy(); + // expect(passedS).toBeTruthy(); + // } else { + // expect(passed).toBeFalsy(); + // expect(passedS).toBeFalsy(); + // } + // } + // }); + // } + // }); + + // describe('.recoverPublicKey()', () => { + // it('should recover public key from recovery bit', async () => { + // const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; + // const privateKey = 123456789n; + // const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); + // const [signature, recovery] = await secp.sign(message, privateKey, { recovered: true }); + // const recoveredPubkey = secp.recoverPublicKey(message, signature, recovery); + // expect(recoveredPubkey).not.toBe(null); + // expect(hex(recoveredPubkey!)).toBe(publicKey); + // expect(secp.verify(signature, message, publicKey)).toBe(true); + // }); + // it('should not recover zero points', () => { + // const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; + // const sig = + // '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; + // const recovery = 0; + // expect(() => secp.recoverPublicKey(msgHash, sig, recovery)).toThrowError(); + // }); + // it('should handle all-zeros msghash', async () => { + // const privKey = secp.utils.randomPrivateKey(); + // const pub = secp.getPublicKey(privKey); + // const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; + // const [sig, rec] = await secp.sign(zeros, privKey, { recovered: true }); + // const recoveredKey = secp.recoverPublicKey(zeros, sig, rec); + // expect(recoveredKey).toEqual(pub); + // }); + // it('should handle RFC 6979 vectors', async () => { + // for (const vector of ecdsa.valid) { + // if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue; + // let [usig, rec] = await secp.sign(vector.m, vector.d, { der: false, recovered: true }); + // let sig = hex(usig); + // const vpub = secp.getPublicKey(vector.d); + // const recovered = secp.recoverPublicKey(vector.m, sig, rec)!; + // expect(hex(recovered)).toBe(hex(vpub)); + // } + // }); + // }); describe('.getSharedSecret()', () => { // TODO: Real implementation. @@ -455,31 +460,39 @@ describe('secp256k1', () => { describe('utils', () => { it('isValidPrivateKey()', () => { + // @ts-ignore for (const vector of privates.valid.isPrivate) { const { d, expected } = vector; expect(secp.utils.isValidPrivateKey(d)).toBe(expected); } }); - const normal = secp.utils._normalizePrivateKey; + // const normal = secp.utils._normalizePrivateKey; + const normal = (a: any) => { + if (typeof a === 'string') a = secp.utils.hexToBytes(a); + if (a instanceof Uint8Array) return secp.utils.bytesToNumber(a); + if (typeof a === 'number' || typeof a === 'bigint') return BigInt(a); + throw new Error(); + }; type Hex = string | Uint8Array; type PrivKey = Hex | bigint | number; const tweakUtils = { privateAdd: (privateKey: PrivKey, tweak: Hex): Uint8Array => { const p = normal(privateKey); const t = normal(tweak); - return secp.utils._bigintTo32Bytes(secp.utils.mod(p + t, secp.CURVE.n)); + return secp.utils.numToField(secp.utils.mod(p + t, secp.CURVE.n)); }, privateNegate: (privateKey: PrivKey): Uint8Array => { const p = normal(privateKey); - return secp.utils._bigintTo32Bytes(secp.CURVE.n - p); + return secp.utils.numToField(secp.CURVE.n - p); }, pointAddScalar: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { const P = secp.Point.fromHex(p); const t = normal(tweak); - const Q = secp.Point.BASE.multiplyAndAddUnsafe(P, t, 1n); - if (!Q) throw new Error('Tweaked point at infinity'); + const Q = P.add(secp.Point.BASE.multiply(t)); + // const Q = secp.Point.BASE.multiplyAndAddUnsafe(P, t, 1n); + if (!Q || Q.equals(secp.Point.ZERO)) throw new Error('Tweaked point at infinity'); return Q.toRawBytes(isCompressed); }, @@ -492,12 +505,14 @@ describe('secp256k1', () => { }; it('privateAdd()', () => { + // @ts-ignore for (const vector of privates.valid.add) { const { a, b, expected } = vector; expect(secp.utils.bytesToHex(tweakUtils.privateAdd(a, b))).toBe(expected); } }); it('privateNegate()', () => { + // @ts-ignore for (const vector of privates.valid.negate) { const { a, expected } = vector; expect(secp.utils.bytesToHex(tweakUtils.privateNegate(a))).toBe(expected); @@ -513,7 +528,7 @@ describe('secp256k1', () => { it('pointAddScalar() invalid', () => { for (const vector of points.invalid.pointAddScalar) { const { P, d, exception } = vector; - expect(() => tweakUtils.pointAddScalar(P, d)).toThrowError(RegExp(`${exception}`)); + expect(() => tweakUtils.pointAddScalar(P, d)).toThrowError(); } }); it('pointMultiply()', () => { @@ -525,45 +540,45 @@ describe('secp256k1', () => { it('pointMultiply() invalid', () => { for (const vector of points.invalid.pointMultiply) { const { P, d, exception } = vector; - expect(() => tweakUtils.pointMultiply(P, d)).toThrowError(RegExp(`${exception}`)); + expect(() => tweakUtils.pointMultiply(P, d)).toThrowError(); } }); }); - describe('wychenproof vectors', () => { - it('should pass all tests', async () => { - for (let group of wp.testGroups) { - const pubKey = secp.Point.fromHex(group.key.uncompressed); - for (let test of group.tests) { - const m = await secp.utils.sha256(hexToBytes(test.msg)); - if (test.result === 'valid' || test.result === 'acceptable') { - const verified = secp.verify(test.sig, m, pubKey); - if (secp.Signature.fromDER(test.sig).hasHighS()) { - expect(verified).toBeFalsy(); - } else { - expect(verified).toBeTruthy(); - } - } else if (test.result === 'invalid') { - let failed = false; - try { - const verified = secp.verify(test.sig, m, pubKey); - if (!verified) failed = true; - } catch (error) { - failed = true; - } - expect(failed).toBeTruthy(); - } else { - expect(false).toBeTruthy(); - } - } - } - }); - }); + // describe('wychenproof vectors', () => { + // it('should pass all tests', async () => { + // for (let group of wp.testGroups) { + // const pubKey = secp.Point.fromHex(group.key.uncompressed); + // for (let test of group.tests) { + // const m = await secp.utils.sha256(hexToBytes(test.msg)); + // if (test.result === 'valid' || test.result === 'acceptable') { + // const verified = secp.verify(test.sig, m, pubKey); + // if (secp.Signature.fromDER(test.sig).hasHighS()) { + // expect(verified).toBeFalsy(); + // } else { + // expect(verified).toBeTruthy(); + // } + // } else if (test.result === 'invalid') { + // let failed = false; + // try { + // const verified = secp.verify(test.sig, m, pubKey); + // if (!verified) failed = true; + // } catch (error) { + // failed = true; + // } + // expect(failed).toBeTruthy(); + // } else { + // expect(false).toBeTruthy(); + // } + // } + // } + // }); + // }); }); -describe('JacobianPoint', () => { - const JZERO = secp.utils._JacobianPoint.ZERO; - const AZERO = secp.utils._JacobianPoint.fromAffine(secp.Point.ZERO); - expect(AZERO.equals(JZERO)).toBeTruthy(); - expect(AZERO.toAffine().equals(JZERO.toAffine())).toBeTruthy(); -}); +// describe('JacobianPoint', () => { +// const JZERO = secp.utils._JacobianPoint.ZERO; +// const AZERO = secp.utils._JacobianPoint.fromAffine(secp.Point.ZERO); +// expect(AZERO.equals(JZERO)).toBeTruthy(); +// expect(AZERO.toAffine().equals(JZERO.toAffine())).toBeTruthy(); +// }); From 875d38c5ab9fa0ffa7836e0df7bedb9210e300d1 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 13 Jan 2023 22:10:12 +0000 Subject: [PATCH 011/145] micro-noble-secp. Iteration 1: 8115 --- index.ts | 1855 +++++++++--------------------------------------------- 1 file changed, 284 insertions(+), 1571 deletions(-) diff --git a/index.ts b/index.ts index 0b37042..ef09430 100644 --- a/index.ts +++ b/index.ts @@ -1,996 +1,313 @@ -/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ -// https://www.secg.org/sec2-v2.pdf - -// Uses built-in crypto module from node.js to generate randomness / hmac-sha256. -// In browser the line is automatically removed during build time: uses crypto.subtle instead. -import * as nodeCrypto from 'crypto'; - -// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n -const _0n = BigInt(0); -const _1n = BigInt(1); -const _2n = BigInt(2); -const _3n = BigInt(3); -const _8n = BigInt(8); - -// Curve fomula is y² = x³ + ax + b -const CURVE = Object.freeze({ - // Params: a, b - a: _0n, - b: BigInt(7), - // Field over which we'll do calculations. Verify with: - // console.log(CURVE.P === (2n**256n - 2n**32n - 2n**9n - 2n**8n-2n**7n-2n**6n-2n**4n - 1n)) - P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'), - // Curve order, total count of valid points in the field. Verify with: - // console.log(CURVE.n === (2n**256n - 432420386565659656852420866394968145599n)) - n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'), - // Cofactor. It's 1, so other subgroups don't exist, and default subgroup is prime-order - h: _1n, - // Base point (x, y) aka generator point - Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), - Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - - // Legacy, endo params are defined below - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), -}); - -const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b; -// Endomorphism params -const endo = { - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), - // Split 256-bit K into 2 128-bit (k1, k2) for which k1 + k2 * lambda = K. - // Used for endomorphism https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066 - splitScalar(k: bigint) { - const { n } = CURVE; - 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('splitScalarEndo: Endomorphism failed, k=' + k); - } - return { k1neg, k1, k2neg, k2 }; - }, +export const CURVE = { + P: 2n ** 256n - 2n ** 32n - 977n, + n: 2n ** 256n - 432420386565659656852420866394968145599n, + a: 0n, + b: 7n, + Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n, + Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n, }; - -// Placeholder for non-sha256 hashes -const fieldLen = 32; // Field element: their range is 0 to CURVE.P -const groupLen = 32; // Group element: their range is 1 to CURVE.n -const hashLen = 32; // Hash used with secp256k1, sha2-256 -const compressedLen = fieldLen + 1; // DER-encoded field element -const uncompressedLen = 2 * fieldLen + 1; // DER-encoded pair of field elements - -// Cleaner js output if that's on a separate line. -export { CURVE }; - -/** - * y² = x³ + ax + b: Short weierstrass curve formula - * @returns y² - */ -function weierstrass(x: bigint): bigint { - const { a, b } = CURVE; - const x2 = mod(x * x); - const x3 = mod(x2 * x); - return mod(x3 + a * x + b); -} - -// We accept hex strings besides Uint8Array for simplicity +const fLen = 32; // field/group byte length +const stdOpts: { lowS?: boolean; der?: boolean; extraEntropy?: any } = { lowS: true }; type Hex = Uint8Array | string; -// Very few implementations accept numbers, we do it to ease learning curve -type PrivKey = Hex | bigint | number; -// compressed/uncompressed ECDSA key, or Schnorr key - not interchangeable -type PubKey = Hex | Point; -// ECDSA signature -type Sig = Hex | Signature; - -/** - * Always true for secp256k1. - * We're including it here if you'll want to reuse code to support - * different curve (e.g. secp256r1) - just set it to false then. - * Endomorphism only works for Koblitz curves with a == 0. - * It improves efficiency: - * Uses 2x less RAM, speeds up precomputation by 2x and ECDH / sign key recovery by 20%. - * Should always be used for Jacobian's double-and-add multiplication. - * For affines cached multiplication, it trades off 1/2 init time & 1/3 ram for 20% perf hit. - * https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066 - */ -const USE_ENDOMORPHISM = CURVE.a === _0n; - -class ShaError extends Error { - constructor(message: string) { - super(message); - } -} - -function assertJacPoint(other: unknown) { - if (!(other instanceof JacobianPoint)) throw new TypeError('JacobianPoint expected'); -} - -/** - * Jacobian Point works in 3d / jacobi coordinates: (x, y, z) ∋ (x=x/z², y=y/z³) - * Default Point works in 2d / affine coordinates: (x, y) - * We're doing calculations in jacobi, because its operations don't require costly inversion. - */ -class JacobianPoint { - constructor(readonly x: bigint, readonly y: bigint, readonly z: bigint) {} - - static readonly BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n); - static readonly ZERO = new JacobianPoint(_0n, _1n, _0n); - static fromAffine(p: Point): JacobianPoint { - if (!(p instanceof Point)) { - throw new TypeError('JacobianPoint#fromAffine: expected Point'); - } - // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) - if (p.equals(Point.ZERO)) return JacobianPoint.ZERO; - return new JacobianPoint(p.x, p.y, _1n); - } - - /** - * Takes a bunch of Jacobian Points but executes only one - * invert on all of them. invert is very slow operation, - * so this improves performance massively. - */ - static toAffineBatch(points: JacobianPoint[]): Point[] { - const toInv = invertBatch(points.map((p) => p.z)); - return points.map((p, i) => p.toAffine(toInv[i])); - } - - static normalizeZ(points: JacobianPoint[]): JacobianPoint[] { - return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine); - } - - /** - * Compare one point to another. - */ - equals(other: JacobianPoint): boolean { - assertJacPoint(other); - const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = other; - const Z1Z1 = mod(Z1 * Z1); - const Z2Z2 = mod(Z2 * Z2); - const U1 = mod(X1 * Z2Z2); - const U2 = mod(X2 * Z1Z1); - const S1 = mod(mod(Y1 * Z2) * Z2Z2); - const S2 = mod(mod(Y2 * Z1) * Z1Z1); - return U1 === U2 && S1 === S2; - } - - /** - * Flips point to one corresponding to (x, -y) in Affine coordinates. - */ - negate(): JacobianPoint { - return new JacobianPoint(this.x, mod(-this.y), this.z); - } - - // Fast algo for doubling 2 Jacobian Points when curve's a=0. - // Note: cannot be reused for other curves when a != 0. - // From: https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - // Cost: 2M + 5S + 6add + 3*2 + 1*3 + 1*8. - double(): JacobianPoint { - const { x: X1, y: Y1, z: Z1 } = this; - const A = mod(X1 * X1); - const B = mod(Y1 * Y1); - const C = mod(B * B); - const x1b = X1 + B; - const D = mod(_2n * (mod(x1b * x1b) - A - C)); - const E = mod(_3n * A); - const F = mod(E * E); - const X3 = mod(F - _2n * D); - const Y3 = mod(E * (D - X3) - _8n * C); - const Z3 = mod(_2n * Y1 * Z1); - return new JacobianPoint(X3, Y3, Z3); - } - - // Fast algo for adding 2 Jacobian Points. - // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2 - // Cost: 12M + 4S + 6add + 1*2 - // Note: 2007 Bernstein-Lange (11M + 5S + 9add + 4*2) is actually 10% slower. - add(other: JacobianPoint): JacobianPoint { - assertJacPoint(other); - const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = other; - if (X2 === _0n || Y2 === _0n) return this; - if (X1 === _0n || Y1 === _0n) return other; - // We're using same code in equals() - const Z1Z1 = mod(Z1 * Z1); - const Z2Z2 = mod(Z2 * Z2); - const U1 = mod(X1 * Z2Z2); - const U2 = mod(X2 * Z1Z1); - const S1 = mod(mod(Y1 * Z2) * Z2Z2); - const S2 = mod(mod(Y2 * Z1) * Z1Z1); - const H = mod(U2 - U1); - const r = mod(S2 - S1); - // H = 0 meaning it's the same point. - if (H === _0n) { - if (r === _0n) { - return this.double(); - } else { - return JacobianPoint.ZERO; - } - } - const HH = mod(H * H); - const HHH = mod(H * HH); - const V = mod(U1 * HH); - const X3 = mod(r * r - HHH - _2n * V); - const Y3 = mod(r * (V - X3) - S1 * HHH); - const Z3 = mod(Z1 * Z2 * H); - return new JacobianPoint(X3, Y3, Z3); - } - - subtract(other: JacobianPoint) { - return this.add(other.negate()); - } - - /** - * Non-constant-time multiplication. Uses double-and-add algorithm. - * It's faster, but should only be used when you don't care about - * an exposed private key e.g. sig verification, which works over *public* keys. - */ - multiplyUnsafe(scalar: bigint): JacobianPoint { - const P0 = JacobianPoint.ZERO; - if (typeof scalar === 'bigint' && scalar === _0n) return P0; - // Will throw on 0 - let n = normalizeScalar(scalar); - if (n === _1n) return this; - - // The condition is not executed unless you change global var - if (!USE_ENDOMORPHISM) { - let p = P0; - let d: JacobianPoint = this; - while (n > _0n) { - if (n & _1n) p = p.add(d); - d = d.double(); - n >>= _1n; - } - return p; - } - let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n); - let k1p = P0; - let k2p = P0; - let d: JacobianPoint = this; - while (k1 > _0n || k2 > _0n) { - if (k1 & _1n) k1p = k1p.add(d); - if (k2 & _1n) k2p = k2p.add(d); - d = d.double(); - k1 >>= _1n; - k2 >>= _1n; - } - if (k1neg) k1p = k1p.negate(); - if (k2neg) k2p = k2p.negate(); - k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z); - return k1p.add(k2p); - } - - /** - * Creates a wNAF precomputation window. Used for caching. - * Default window size is set by `utils.precompute()` and is equal to 8. - * Which means we are caching 65536 points: 256 points for every bit from 0 to 256. - * @returns 65K precomputed points, depending on W - */ - private precomputeWindow(W: number): JacobianPoint[] { - // splitScalarEndo could return 129-bit numbers, so we need at least 128 / W + 1 - const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1; - const points: JacobianPoint[] = []; - let p: JacobianPoint = this; - let base = p; - for (let window = 0; window < windows; window++) { - base = p; - points.push(base); - for (let i = 1; i < 2 ** (W - 1); i++) { - base = base.add(p); - points.push(base); - } - p = base.double(); - } - return points; - } - - /** - * Implements w-ary non-adjacent form for calculating ec multiplication. - * @param n - * @param affinePoint optional 2d point to save cached precompute windows on it. - * @returns real and fake (for const-time) points - */ - private wNAF(n: bigint, affinePoint?: Point): { p: JacobianPoint; f: JacobianPoint } { - if (!affinePoint && this.equals(JacobianPoint.BASE)) affinePoint = Point.BASE; - const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1; - if (256 % W) { - throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2'); - } - - // Calculate precomputes on a first run, reuse them after - let precomputes = affinePoint && pointPrecomputes.get(affinePoint); - if (!precomputes) { - precomputes = this.precomputeWindow(W); - if (affinePoint && W !== 1) { - precomputes = JacobianPoint.normalizeZ(precomputes); - pointPrecomputes.set(affinePoint, precomputes); - } - } - - // Initialize real and fake points for const-time - let p = JacobianPoint.ZERO; - // Should be G (base) point, since otherwise f can be infinity point in the end - let f = JacobianPoint.BASE; - - const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W); // W=8 17 - const windowSize = 2 ** (W - 1); // W=8 128 - const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b11111111 for W=8 - const maxNumber = 2 ** W; // W=8 256 - const shiftBy = BigInt(W); // W=8 8 - - for (let window = 0; window < windows; window++) { - const offset = window * windowSize; - // Extract W bits. - let wbits = Number(n & mask); - - // Shift number by W bits. - n >>= shiftBy; - - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber; - n += _1n; - } - - // This code was first written with assumption that 'f' and 'p' will never be infinity point: - // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, - // there is negate now: it is possible that negated element from low value - // would be the same as high element, which will create carry into next window. - // It's not obvious how this can fail, but still worth investigating later. - - // Check if we're onto Zero point. - // Add random point inside current window to f. - const offset1 = offset; - const offset2 = offset + Math.abs(wbits) - 1; - const cond1 = window % 2 !== 0; - const cond2 = wbits < 0; - if (wbits === 0) { - // The most important part for const-time getPublicKey - f = f.add(constTimeNegate(cond1, precomputes[offset1])); - } else { - p = p.add(constTimeNegate(cond2, precomputes[offset2])); - } - } - // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() - // Even if the variable is still unused, there are some checks which will - // throw an exception, so compiler needs to prove they won't happen, which is hard. - // At this point there is a way to F be infinity-point even if p is not, - // which makes it less const-time: around 1 bigint multiply. - return { p, f }; - } - - /** - * Constant time multiplication. - * Uses wNAF method. Windowed method may be 10% faster, - * but takes 2x longer to generate and consumes 2x memory. - * @param scalar by which the point would be multiplied - * @param affinePoint optional point ot save cached precompute windows on it - * @returns New point - */ - multiply(scalar: number | bigint, affinePoint?: Point): JacobianPoint { - let n = normalizeScalar(scalar); - // Real point. - let point: JacobianPoint; - // Fake point, we use it to achieve constant-time multiplication. - let fake: JacobianPoint; - if (USE_ENDOMORPHISM) { - const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n); - let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint); - let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint); - k1p = constTimeNegate(k1neg, k1p); - k2p = constTimeNegate(k2neg, k2p); - k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z); - point = k1p.add(k2p); - fake = f1p.add(f2p); - } else { - const { p, f } = this.wNAF(n, affinePoint); - point = p; - fake = f; - } - // Normalize `z` for both points, but return only real one - return JacobianPoint.normalizeZ([point, fake])[0]; - } - - // Converts Jacobian point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z², y=y/z³) - toAffine(invZ?: bigint): Point { - const { x, y, z } = this; - const is0 = this.equals(JacobianPoint.ZERO); - // If invZ was 0, we return zero point. However we still want to execute - // all operations, so we replace invZ with a random number, 8. - if (invZ == null) invZ = is0 ? _8n : invert(z); - const iz1 = invZ; - const iz2 = mod(iz1 * iz1); - const iz3 = mod(iz2 * iz1); - const ax = mod(x * iz2); - const ay = mod(y * iz3); - const zz = mod(z * iz1); - if (is0) return Point.ZERO; - if (zz !== _1n) throw new Error('invZ was invalid'); - return new Point(ax, ay); - } -} - -// Const-time utility for wNAF -function constTimeNegate(condition: boolean, item: JacobianPoint) { - const neg = item.negate(); - return condition ? neg : item; +const isValidFE = (n: bigint) => typeof n === 'bigint' && 0n < n && n < CURVE.P; +const isValidGE = (n: bigint) => typeof n === 'bigint' && 0n < n && n < CURVE.n; +const weierstrass = (x: bigint) => mod(mod(x * mod(x * x)) + CURVE.a * x + CURVE.b); + +function assertBytes(a: any, len?: number) { + if (!(a instanceof Uint8Array)) throw new Error('ui8a expected'); + if (typeof len === 'number' && len > 0 && a.length !== len) throw new Error('len expected'); + return a; +} +const ensureBytes = (a: any, len?: number) => + assertBytes(typeof a === 'string' ? hexToBytes(a) : a, len); +function normalizePrivKey(privKey: Hex | bigint) { + if (typeof privKey !== 'bigint') privKey = bytesToNumber(ensureBytes(privKey, fLen)); + if (!isValidGE(privKey)) throw new Error(); + return privKey; } - -// Stores precomputed values for points. -const pointPrecomputes = new WeakMap(); - -/** - * Default Point works in default aka affine coordinates: (x, y) - */ export class Point { - /** - * Base point aka generator. public_key = Point.BASE * private_key - */ - static BASE: Point = new Point(CURVE.Gx, CURVE.Gy); - /** - * Identity point aka point at infinity. point = point + zero_point - */ - static ZERO: Point = new Point(_0n, _0n); - // We calculate precomputes for elliptic curve point multiplication - // using windowed method. This specifies window size and - // stores precomputed values. Usually only base point would be precomputed. - _WINDOW_SIZE?: number; - - constructor(readonly x: bigint, readonly y: bigint) {} - - // "Private method", don't use it directly - _setWindowSize(windowSize: number) { - this._WINDOW_SIZE = windowSize; - pointPrecomputes.delete(this); - } - - // Checks for y % 2 == 0 - hasEvenY() { - return this.y % _2n === _0n; - } - - /** - * Supports compressed Schnorr and ECDSA points - * @param bytes - * @returns Point instance - */ - private static fromCompressedHex(bytes: Uint8Array) { - const isShort = bytes.length === 32; - const x = bytesToNumber(isShort ? bytes : bytes.subarray(1)); - if (!isValidFieldElement(x)) throw new Error('Point is not on curve'); - const y2 = weierstrass(x); // y² = x³ + ax + b - let y = sqrtMod(y2); // y = y² ^ (p+1)/4 - const isYOdd = (y & _1n) === _1n; - if (isShort) { - // Schnorr - if (isYOdd) y = mod(-y); - } else { - // ECDSA - const isFirstByteOdd = (bytes[0] & 1) === 1; - if (isFirstByteOdd !== isYOdd) y = mod(-y); - } - const point = new Point(x, y); - point.assertValidity(); - return point; - } - - // Schnorr doesn't support uncompressed points, so this is only for ECDSA - private static fromUncompressedHex(bytes: Uint8Array) { - const x = bytesToNumber(bytes.subarray(1, fieldLen + 1)); - const y = bytesToNumber(bytes.subarray(fieldLen + 1, fieldLen * 2 + 1)); - const point = new Point(x, y); - point.assertValidity(); - return point; + static BASE = new Point(CURVE.Gx, CURVE.Gy); + static ZERO = new Point(0n, 0n); + static fromPrivateKey(privKey: Hex | bigint) { + return Point.BASE.multiply(normalizePrivKey(privKey)); } - - /** - * Converts hash string or Uint8Array to Point. - * @param hex schnorr or ECDSA hex - */ - static fromHex(hex: Hex): Point { - const bytes = ensureBytes(hex); - const len = bytes.length; - const header = bytes[0]; - // this.assertValidity() is done inside of those two functions - // Schnorr - if (len === fieldLen) return this.fromCompressedHex(bytes); - // ECDSA - if (len === compressedLen && (header === 0x02 || header === 0x03)) { - return this.fromCompressedHex(bytes); - } - if (len === uncompressedLen && header === 0x04) return this.fromUncompressedHex(bytes); - throw new Error( - `Point.fromHex: received invalid point. Expected 32-${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}` - ); - } - - // Multiplies generator point by privateKey. - static fromPrivateKey(privateKey: PrivKey) { - return Point.BASE.multiply(normalizePrivateKey(privateKey)); - } - - /** - * Recovers public key from ECDSA signature. - * https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Public_key_recovery - * ``` - * recover(r, s, h) where - * u1 = hs^-1 mod n - * u2 = sr^-1 mod n - * Q = u1⋅G + u2⋅R - * ``` - */ - static fromSignature(msgHash: Hex, signature: Sig, recovery: number): Point { - const { r, s } = normalizeSignature(signature); - if (![0, 1, 2, 3].includes(recovery)) throw new Error('Cannot recover: invalid recovery bit'); - const h = truncateHash(ensureBytes(msgHash)); - const { n } = CURVE; - const radj = recovery === 2 || recovery === 3 ? r + n : r; - const rinv = invert(radj, n); - // Q = u1⋅G + u2⋅R - const u1 = mod(-h * rinv, n); - const u2 = mod(s * rinv, n); - const prefix = recovery & 1 ? '03' : '02'; - const R = Point.fromHex(prefix + numTo32bStr(radj)); - const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); - if (!Q) throw new Error('Cannot recover signature: point at infinify'); - Q.assertValidity(); - return Q; - } - - toRawBytes(isCompressed = false): Uint8Array { - return hexToBytes(this.toHex(isCompressed)); - } - - toHex(isCompressed = false): string { - const x = numTo32bStr(this.x); - if (isCompressed) { - const prefix = this.hasEvenY() ? '02' : '03'; - return `${prefix}${x}`; - } else { - return `04${x}${numTo32bStr(this.y)}`; - } - } - - // Schnorr-related function - toHexX() { - return this.toHex(true).slice(2); - } - - toRawX() { - return this.toRawBytes(true).slice(1); - } - - // A point on curve is valid if it conforms to equation. - assertValidity(): void { - const msg = 'Point is not on elliptic curve'; + constructor(readonly x: bigint, readonly y: bigint) {} + assertValidity() { const { x, y } = this; - if (!isValidFieldElement(x) || !isValidFieldElement(y)) throw new Error(msg); - const left = mod(y * y); - const right = weierstrass(x); - if (mod(left - right) !== _0n) throw new Error(msg); + if (!isValidFE(x) || !isValidFE(y)) throw new Error(); + if (mod(mod(y * y) - weierstrass(x)) !== 0n) throw new Error(); + return this; } - - equals(other: Point): boolean { + equals(other: Point) { return this.x === other.x && this.y === other.y; } - - // Returns the same point with inverted `y` + double(): Point { + const { x: X1, y: Y1 } = this; + const lam = mod(3n * X1 ** 2n * invert(2n * Y1)); + const X3 = mod(lam * lam - 2n * X1); + const Y3 = mod(lam * (X1 - X3) - Y1); + return new Point(X3, Y3); + } + // https://hyperelliptic.org/EFD/g1p/auto-shortw.html + add(b: Point): Point { + const a = this; + const { x: X1, y: Y1 } = a; + const { x: X2, y: Y2 } = b; + if (X1 === 0n || Y1 === 0n) return b; + if (X2 === 0n || Y2 === 0n) return a; + if (X1 === X2 && Y1 === Y2) return this.double(); + if (X1 === X2 && Y1 === -Y2) return Point.ZERO; + const x2x1 = mod(X2 - X1); + if (x2x1 === 0n) return Point.ZERO; + const lam = mod((Y2 - Y1) * invert(x2x1)); + const X3 = mod(lam * lam - X1 - X2); + const Y3 = mod(lam * (X1 - X3) - Y1); + return new Point(X3, Y3); + } negate() { return new Point(this.x, mod(-this.y)); } - - // Adds point to itself - double() { - return JacobianPoint.fromAffine(this).double().toAffine(); - } - - // Adds point to other point - add(other: Point) { - return JacobianPoint.fromAffine(this).add(JacobianPoint.fromAffine(other)).toAffine(); - } - - // Subtracts other point from the point - subtract(other: Point) { - return this.add(other.negate()); + subtract(b: Point) { + return this.add(b.negate()); } - - multiply(scalar: number | bigint) { - return JacobianPoint.fromAffine(this).multiply(scalar, this).toAffine(); + multiply(n: bigint) { + if (!isValidGE(n)) throw new Error(); + let p = Point.ZERO; + for (let d: Point = this; n > 0n; d = d.double(), n >>= 1n) if (n & 1n) p = p.add(d); + return p; } - - /** - * Efficiently calculate `aP + bQ`. - * Unsafe, can expose private key, if used incorrectly. - * TODO: Utilize Shamir's trick - * @returns non-zero affine point - */ - multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined { - const P = JacobianPoint.fromAffine(this); - const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a); - const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b); - const sum = aP.add(bQ); - return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine(); - } -} - -function sliceDER(s: string): string { - // Proof: any([(i>=0x80) == (int(hex(i).replace('0x', '').zfill(2)[0], 16)>=8) for i in range(0, 256)]) - // Padding done by numberToHex - return Number.parseInt(s[0], 16) >= 8 ? '00' + s : s; -} - -function parseDERInt(data: Uint8Array) { - if (data.length < 2 || data[0] !== 0x02) { - throw new Error(`Invalid signature integer tag: ${bytesToHex(data)}`); + static fromHex(hex: Hex) { + hex = ensureBytes(hex); + let p: Point | undefined = undefined; + const head = hex[0]; + const tail = hex.subarray(1); + const x = sliceNum(tail, 0, fLen); + if (hex.length === 33 && [0x02, 0x03].includes(head)) { + if (!isValidFE(x)) throw new Error(); + let y = sqrt(weierstrass(x)); + const isYOdd = (y & 1n) === 1n; + const isFirstByteOdd = (head & 1) === 1; + if (isFirstByteOdd !== isYOdd) y = mod(-y); + p = new Point(x, y); + } + if (hex.length === 65 && head === 0x04) p = new Point(x, sliceNum(tail, fLen, 2 * fLen)); + if (!p) throw new Error(); + return p.assertValidity(); } - const len = data[1]; - const res = data.subarray(2, len + 2); - if (!len || res.length !== len) { - throw new Error(`Invalid signature integer: wrong length`); + toHex(isCompressed = false) { + const { x, y } = this; + const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; + return `${head}${numToFieldStr(x)}${isCompressed ? '' : numToFieldStr(y)}`; } - // Strange condition, its not about length, but about first bytes of number. - if (res[0] === 0x00 && res[1] <= 0x7f) { - throw new Error('Invalid signature integer: trailing length'); + toRawBytes(isCompressed = false) { + return hexToBytes(this.toHex(isCompressed)); } - return { data: bytesToNumber(res), left: data.subarray(len + 2) }; } -function parseDERSignature(data: Uint8Array) { - if (data.length < 2 || data[0] != 0x30) { - throw new Error(`Invalid signature tag: ${bytesToHex(data)}`); - } - if (data[1] !== data.length - 2) { - throw new Error('Invalid signature: incorrect length'); - } - const { data: r, left: sBytes } = parseDERInt(data.subarray(2)); - const { data: s, left: rBytesLeft } = parseDERInt(sBytes); - if (rBytesLeft.length) { - throw new Error(`Invalid signature: left bytes after parsing: ${bytesToHex(rBytesLeft)}`); - } - return { r, s }; +function mod(a: bigint, b: bigint = CURVE.P): bigint { + const result = a % b; + return result >= 0n ? result : b + result; } - -// Represents ECDSA signature with its (r, s) properties -export class Signature { - constructor(readonly r: bigint, readonly s: bigint) { - this.assertValidity(); - } - - // pair (32 bytes of r, 32 bytes of s) - static fromCompact(hex: Hex) { - const arr = hex instanceof Uint8Array; - const name = 'Signature.fromCompact'; - if (typeof hex !== 'string' && !arr) - throw new TypeError(`${name}: Expected string or Uint8Array`); - const str = arr ? bytesToHex(hex) : hex; - if (str.length !== 128) throw new Error(`${name}: Expected 64-byte hex`); - return new Signature(hexToNumber(str.slice(0, 64)), hexToNumber(str.slice(64, 128))); - } - - // DER encoded ECDSA signature - // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script - static fromDER(hex: Hex) { - const arr = hex instanceof Uint8Array; - if (typeof hex !== 'string' && !arr) - throw new TypeError(`Signature.fromDER: Expected string or Uint8Array`); - const { r, s } = parseDERSignature(arr ? hex : hexToBytes(hex)); - return new Signature(r, s); - } - - // Don't use this method - static fromHex(hex: Hex) { - return this.fromDER(hex); - } - - assertValidity(): void { - const { r, s } = this; - if (!isWithinCurveOrder(r)) throw new Error('Invalid Signature: r must be 0 < r < n'); - if (!isWithinCurveOrder(s)) throw new Error('Invalid Signature: s must be 0 < s < n'); - } - - // Default signatures are always low-s, to prevent malleability. - // sign(canonical: true) always produces low-s sigs. - // verify(strict: true) always fails for high-s. - // We don't provide `hasHighR` https://github.com/bitcoin/bitcoin/pull/13666 - hasHighS(): boolean { - const HALF = CURVE.n >> _1n; - return this.s > HALF; - } - - normalizeS(): Signature { - return this.hasHighS() ? new Signature(this.r, mod(-this.s, CURVE.n)) : this; - } - - // DER-encoded - toDERRawBytes() { - return hexToBytes(this.toDERHex()); - } - toDERHex() { - const sHex = sliceDER(numberToHexUnpadded(this.s)); - const rHex = sliceDER(numberToHexUnpadded(this.r)); - const sHexL = sHex.length / 2; - const rHexL = rHex.length / 2; - const sLen = numberToHexUnpadded(sHexL); - const rLen = numberToHexUnpadded(rHexL); - const length = numberToHexUnpadded(rHexL + sHexL + 4); - return `30${length}02${rLen}${rHex}02${sLen}${sHex}`; - } - - // Don't use these methods. Use toDER* or toCompact* for explicitness. - toRawBytes() { - return this.toDERRawBytes(); - } - toHex() { - return this.toDERHex(); - } - - // 32 bytes of r, then 32 bytes of s - toCompactRawBytes() { - return hexToBytes(this.toCompactHex()); +// Inverses number over modulo +function invert(number: bigint, md = CURVE.P): bigint { + if (number === 0n || md <= 0n) throw new Error(`invert: expected >0, got n=${number} mod=${md}`); + // Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/ + let a = mod(number, md); + let b = md; + // prettier-ignore + let x = 0n, y = 1n, u = 1n, v = 0n; + while (a !== 0n) { + const q = b / a; + const r = b % a; + const m = x - u * q; + const n = y - v * q; + // prettier-ignore + b = a, a = r, x = u, y = v, u = m, v = n; } - toCompactHex() { - return numTo32bStr(this.r) + numTo32bStr(this.s); + const gcd = b; + if (gcd !== 1n) throw new Error('invert: does not exist'); + return mod(x, md); +} +function pow(num: bigint, power: bigint, md: bigint): bigint { + if (md <= 0n || power < 0n) throw new Error('Expected power/modulo > 0'); + if (md === 1n) return 0n; + let res = 1n; + while (power > 0n) { + if (power & 1n) res = (res * num) % md; + num = (num * num) % md; + power >>= 1n; } + return res; } - -// Copies several Uint8Arrays into one. -function concatBytes(...arrays: Uint8Array[]): Uint8Array { - if (!arrays.every((b) => b instanceof Uint8Array)) throw new Error('Uint8Array list expected'); - if (arrays.length === 1) return arrays[0]; - const length = arrays.reduce((a, arr) => a + arr.length, 0); - const result = new Uint8Array(length); - for (let i = 0, pad = 0; i < arrays.length; i++) { - const arr = arrays[i]; - result.set(arr, pad); - pad += arr.length; - } - return result; +function sqrt(num: bigint) { + return pow(num, (CURVE.P + 1n) / 4n, CURVE.P); } -// Convert between types -// --------------------- - -const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); function bytesToHex(uint8a: Uint8Array): string { - if (!(uint8a instanceof Uint8Array)) throw new Error('Expected Uint8Array'); - // pre-caching improves the speed 6x + assertBytes(uint8a); let hex = ''; - for (let i = 0; i < uint8a.length; i++) { - hex += hexes[uint8a[i]]; - } + for (let i = 0; i < uint8a.length; i++) hex += uint8a[i].toString(16).padStart(2, '0'); return hex; } - -const POW_2_256 = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000'); -function numTo32bStr(num: bigint): string { - if (typeof num !== 'bigint') throw new Error('Expected bigint'); - if (!(_0n <= num && num < POW_2_256)) throw new Error('Expected number 0 <= n < 2^256'); - return num.toString(16).padStart(64, '0'); -} -function numTo32b(num: bigint): Uint8Array { - const b = hexToBytes(numTo32bStr(num)); - if (b.length !== 32) throw new Error('Error: expected 32 bytes'); - return b; -} - -function numberToHexUnpadded(num: number | bigint): string { - const hex = num.toString(16); - return hex.length & 1 ? `0${hex}` : hex; -} - function hexToNumber(hex: string): bigint { - if (typeof hex !== 'string') { - throw new TypeError('hexToNumber: expected string, got ' + typeof hex); - } - // Big Endian + if (typeof hex !== 'string') throw new TypeError(); return BigInt(`0x${hex}`); } - -// Caching slows it down 2-3x function hexToBytes(hex: string): Uint8Array { - if (typeof hex !== 'string') { - throw new TypeError('hexToBytes: expected string, got ' + typeof hex); - } - if (hex.length % 2) throw new Error('hexToBytes: received invalid unpadded hex' + hex.length); + if (typeof hex !== 'string') throw new TypeError(); + if (hex.length % 2) throw new Error(); const array = new Uint8Array(hex.length / 2); for (let i = 0; i < array.length; i++) { const j = i * 2; const hexByte = hex.slice(j, j + 2); const byte = Number.parseInt(hexByte, 16); - if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence'); + if (Number.isNaN(byte) || byte < 0) throw new Error(); array[i] = byte; } return array; } - -// Big Endian -function bytesToNumber(bytes: Uint8Array): bigint { - return hexToNumber(bytesToHex(bytes)); +const bytesToNumber = (b: Uint8Array): bigint => hexToNumber(bytesToHex(b)); +const sliceNum = (b: Uint8Array, from: number, to: number) => bytesToNumber(b.slice(from, to)); +function numToField(num: bigint): Uint8Array { + if (typeof num !== 'bigint') throw new Error(); + if (!(0n <= num && num < 2n ** 256n)) throw new Error(); + return hexToBytes(num.toString(16).padStart(2 * fLen, '0')); } - -function ensureBytes(hex: Hex): Uint8Array { - // Uint8Array.from() instead of hash.slice() because node.js Buffer - // is instance of Uint8Array, and its slice() creates **mutable** copy - return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex); +const numToFieldStr = (num: bigint): string => bytesToHex(numToField(num)); +function concatBytes(...arrays: Uint8Array[]): Uint8Array { + arrays.every((b) => assertBytes(b)); + if (arrays.length === 1) return arrays[0]; + const length = arrays.reduce((a, arr) => a + arr.length, 0); + const result = new Uint8Array(length); + for (let i = 0, pad = 0; i < arrays.length; i++) { + const arr = arrays[i]; + result.set(arr, pad); + pad += arr.length; + } + return result; } -function normalizeScalar(num: number | bigint): bigint { - if (typeof num === 'number' && Number.isSafeInteger(num) && num > 0) return BigInt(num); - if (typeof num === 'bigint' && isWithinCurveOrder(num)) return num; - throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n'); +function bits2int_2(bytes: Uint8Array) { + const delta = bytes.length * 8 - 256; + const num = bytesToNumber(bytes); + return delta > 0 ? num >> BigInt(delta) : num; } - -// ------------------------- - -// Calculates a modulo b -function mod(a: bigint, b: bigint = CURVE.P): bigint { - const result = a % b; - return result >= _0n ? result : b + result; +function truncateHash(hash: Uint8Array): bigint { + const h = bits2int_2(hash); + const { n } = CURVE; + return h >= n ? h - n : h; } - -// Does x ^ (2 ^ power). E.g. 30 ^ (2 ^ 4) -function pow2(x: bigint, power: bigint): bigint { - const { P } = CURVE; - let res = x; - while (power-- > _0n) { - res *= res; - res %= P; - } - return res; +function isBiggerThanHalfOrder(number: bigint) { + const half = CURVE.n >> 1n; + return number > half; } -/** - * Allows to compute square root √y 2x faster. - * To calculate √y, we need to exponentiate it to a very big number: - * `y² = x³ + ax + b; y = y² ^ (p+1)/4` - * We are unwrapping the loop and multiplying it bit-by-bit. - * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] - */ -function sqrtMod(x: bigint): bigint { - const { P } = CURVE; - 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) * b3) % P; - const b9 = (pow2(b6, _3n) * b3) % P; - const b11 = (pow2(b9, _2n) * b2) % P; - const b22 = (pow2(b11, _11n) * b11) % P; - const b44 = (pow2(b22, _22n) * b22) % P; - const b88 = (pow2(b44, _44n) * b44) % P; - const b176 = (pow2(b88, _88n) * b88) % P; - const b220 = (pow2(b176, _44n) * b44) % P; - const b223 = (pow2(b220, _3n) * b3) % P; - const t1 = (pow2(b223, _23n) * b22) % P; - const t2 = (pow2(t1, _6n) * b2) % P; - const rt = pow2(t2, _2n); - const xc = (rt * rt) % P; - if (xc !== x) throw new Error('Cannot find square root'); - return rt; +export function getPublicKey(privKey: Hex | bigint, isCompressed = false) { + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); } - -// Inverses number over modulo -function invert(number: bigint, modulo: bigint = CURVE.P): bigint { - if (number === _0n || modulo <= _0n) { - throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`); +export class Signature { + constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { + this.assertValidity(); } - // Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/ - let a = mod(number, modulo); - let b = modulo; - // prettier-ignore - let x = _0n, y = _1n, u = _1n, v = _0n; - while (a !== _0n) { - const q = b / a; - const r = b % a; - const m = x - u * q; - const n = y - v * q; - // prettier-ignore - b = a, a = r, x = u, y = v, u = m, v = n; + assertValidity(): Signature { + if (!isValidGE(this.r)) throw new Error(); + if (!isValidGE(this.s)) throw new Error(); + return this; + } + static fromCompact(hex: Hex) { + hex = ensureBytes(hex, 64); + return new Signature(sliceNum(hex, 0, fLen), sliceNum(hex, fLen, 2 * fLen)); + } + static fromKMD(kBytes: Uint8Array, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { + const { n } = CURVE; + const k = bits2int_2(kBytes); + if (!isValidGE(k)) return; + const kinv = invert(k, n); + const q = Point.BASE.multiply(k); + const r = mod(q.x, n); + if (r === 0n) return; + const s = mod(kinv * mod(m + mod(d * r, n), n), n); + if (s === 0n) return; + let normS = s; + let recovery = (q.x === r ? 0 : 2) | Number(q.y & 1n); + if (lowS && isBiggerThanHalfOrder(s)) { + normS = mod(-s, CURVE.n); + recovery ^= 1; + } + return new Signature(r, normS, recovery); + } + toCompactRawBytes() { + return hexToBytes(this.toCompactHex()); + } + toCompactHex() { + return numToFieldStr(this.r) + numToFieldStr(this.s); } - const gcd = b; - if (gcd !== _1n) throw new Error('invert: does not exist'); - return mod(x, modulo); } -/** - * Takes a list of numbers, efficiently inverts all of them. - * @param nums list of bigints - * @param p modulo - * @returns list of inverted bigints - * @example - * invertBatch([1n, 2n, 4n], 21n); - * // => [1n, 11n, 16n] - */ -function invertBatch(nums: bigint[], p: bigint = CURVE.P): bigint[] { - const scratch = new Array(nums.length); - // Walk from first to last, multiply them by each other MOD p - const lastMultiplied = nums.reduce((acc, num, i) => { - if (num === _0n) return acc; - scratch[i] = acc; - return mod(acc * num, p); - }, _1n); - // Invert last element - const inverted = invert(lastMultiplied, p); - // Walk from last to first, multiply them by inverted each other MOD p - nums.reduceRight((acc, num, i) => { - if (num === _0n) return acc; - scratch[i] = mod(acc * scratch[i], p); - return mod(acc * num, p); - }, inverted); - return scratch; +// RFC6979 methods +function bits2int(bytes: Uint8Array): bigint { + assertBytes(bytes); + const slice = bytes.length > fLen ? bytes.slice(0, fLen) : bytes; + return bytesToNumber(slice); } - -// Can be replaced by bytesToNumber(). Placeholder for non-sha256 hashes -function bits2int_2(bytes: Uint8Array) { - const delta = bytes.length * 8 - groupLen * 8; // 256-256=0 for sha256/secp256k1 - const num = bytesToNumber(bytes); - return delta > 0 ? num >> BigInt(delta) : num; +function bits2octets(bytes: Uint8Array): Uint8Array { + const z1 = bits2int(bytes); + const z2 = mod(z1, CURVE.n); + return int2octets(z2 < 0n ? z1 : z2); } - -// Ensures ECDSA message hashes are 32 bytes and < curve order -function truncateHash(hash: Uint8Array, truncateOnly = false): bigint { - const h = bits2int_2(hash); - if (truncateOnly) return h; - const { n } = CURVE; - return h >= n ? h - n : h; +function int2octets(num: bigint): Uint8Array { + return numToField(num); } -// RFC6979 related code -type RecoveredSig = { sig: Signature; recovery: number }; -type U8A = Uint8Array; - -type Sha256FnSync = undefined | ((...messages: Uint8Array[]) => Uint8Array); -type HmacFnSync = undefined | ((key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array); -let _sha256Sync: Sha256FnSync; -let _hmacSha256Sync: HmacFnSync; +// Global symbol available in browsers only. Ensure we do not depend on @types/dom +declare const self: Record | undefined; +const crypto: { node?: any; web?: any } = { + node: typeof require === 'function' && require('crypto'), + web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, +}; +async function hmac(key: Uint8Array, ...messages: Uint8Array[]): Promise { + const msgs = concatBytes(...messages); + if (crypto.web) { + // prettier-ignore + const ckey = await crypto.web.subtle.importKey( + 'raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign'] + ); + return new Uint8Array(await crypto.web.subtle.sign('HMAC', ckey, msgs)); + } else if (crypto.node) { + return Uint8Array.from(crypto.node.createHmac('sha256', key).update(msgs).digest()); + } else { + throw new Error("The environment doesn't have hmac-sha256 function"); + } +} +function randomBytes(bytesLength: number): Uint8Array { + if (crypto.web) { + return crypto.web.getRandomValues(new Uint8Array(bytesLength)); + } else if (crypto.node) { + return Uint8Array.from(crypto.node.randomBytes(bytesLength)); + } else { + throw new Error("The environment doesn't have randomBytes function"); + } +} -// Minimal HMAC-DRBG (NIST 800-90) for signatures -// Used only for RFC6979, does not fully implement DRBG spec. +// Minimal HMAC-DRBG (NIST 800-90) used only for RFC6979 signatures class HmacDrbg { k: Uint8Array; v: Uint8Array; counter: number; - constructor(public hashLen: number, public qByteLen: number) { - if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number'); - if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number'); - + constructor(public hashLen = fLen, public qByteLen = fLen) { // Step B, Step C: set hashLen to 8*ceil(hlen/8) this.v = new Uint8Array(hashLen).fill(1); this.k = new Uint8Array(hashLen).fill(0); this.counter = 0; } private hmac(...values: Uint8Array[]) { - return utils.hmacSha256(this.k, ...values); - } - private hmacSync(...values: Uint8Array[]) { - return _hmacSha256Sync!(this.k, ...values); - } - private checkSync() { - if (typeof _hmacSha256Sync !== 'function') throw new ShaError('hmacSha256Sync needs to be set'); + return hmac(this.k, ...values); } incr() { if (this.counter >= 1000) throw new Error('Tried 1,000 k values for sign(), all were invalid'); this.counter += 1; } - // We concatenate extraData into seed async reseed(seed = new Uint8Array()) { this.k = await this.hmac(this.v, Uint8Array.from([0x00]), seed); this.v = await this.hmac(this.v); @@ -998,15 +315,6 @@ class HmacDrbg { this.k = await this.hmac(this.v, Uint8Array.from([0x01]), seed); this.v = await this.hmac(this.v); } - reseedSync(seed = new Uint8Array()) { - this.checkSync(); - this.k = this.hmacSync(this.v, Uint8Array.from([0x00]), seed); - this.v = this.hmacSync(this.v); - if (seed.length === 0) return; - this.k = this.hmacSync(this.v, Uint8Array.from([0x01]), seed); - this.v = this.hmacSync(this.v); - } - async generate(): Promise { this.incr(); let len = 0; @@ -1019,679 +327,84 @@ class HmacDrbg { } return concatBytes(...out); } - generateSync(): Uint8Array { - this.checkSync(); - this.incr(); - let len = 0; - const out: Uint8Array[] = []; - while (len < this.qByteLen) { - this.v = this.hmacSync(this.v); - const sl = this.v.slice(); - out.push(sl); - len += this.v.length; - } - return concatBytes(...out); - } - // There is no need in clean() method - // It's useless, there are no guarantees with JS GC - // whether bigints are removed even if you clean Uint8Arrays. -} - -// Valid scalars are [1, n-1] -function isWithinCurveOrder(num: bigint): boolean { - return _0n < num && num < CURVE.n; -} - -// Valid field elements are [1, p-1] -function isValidFieldElement(num: bigint): boolean { - return _0n < num && num < CURVE.P; -} - -/** - * Converts signature params into point & r/s, checks them for validity. - * k must be in range [1, n-1] - * @param k signature's k param: deterministic in our case, random in non-rfc6979 sigs - * @param m message that would be signed - * @param d private key - * @returns Signature with its point on curve Q OR undefined if params were invalid - */ -function kmdToSig(kBytes: Uint8Array, m: bigint, d: bigint, lowS = true): RecoveredSig | undefined { - const { n } = CURVE; - const k = truncateHash(kBytes, true); - if (!isWithinCurveOrder(k)) return; - // Important: all mod() calls in the function must be done over `n` - const kinv = invert(k, n); - const q = Point.BASE.multiply(k); - // r = x mod n - const r = mod(q.x, n); - if (r === _0n) return; - // s = (m + dr)/k mod n where x/k == x*inv(k) - const s = mod(kinv * mod(m + d * r, n), n); - if (s === _0n) return; - - let sig = new Signature(r, s); - // Recovery bit is usually 0 or 1; rarely it's 2 or 3, when q.x > n - let recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n); - if (lowS && sig.hasHighS()) { - sig = sig.normalizeS(); - recovery ^= 1; - } - return { sig, recovery }; -} - -function normalizePrivateKey(key: PrivKey): bigint { - let num: bigint; - if (typeof key === 'bigint') { - num = key; - } else if (typeof key === 'number' && Number.isSafeInteger(key) && key > 0) { - num = BigInt(key); - } else if (typeof key === 'string') { - if (key.length !== 2 * groupLen) throw new Error('Expected 32 bytes of private key'); - num = hexToNumber(key); - } else if (key instanceof Uint8Array) { - if (key.length !== groupLen) throw new Error('Expected 32 bytes of private key'); - num = bytesToNumber(key); - } else { - throw new TypeError('Expected valid private key'); - } - if (!isWithinCurveOrder(num)) throw new Error('Expected private key: 0 < key < n'); - return num; -} - -/** - * Normalizes hex, bytes, Point to Point. Checks for curve equation. - */ -function normalizePublicKey(publicKey: PubKey): Point { - if (publicKey instanceof Point) { - publicKey.assertValidity(); - return publicKey; - } else { - return Point.fromHex(publicKey); - } -} - -/** - * Signatures can be in 64-byte compact representation, - * or in (variable-length)-byte DER representation. - * Since DER could also be 64 bytes, we check for it first. - */ -function normalizeSignature(signature: Sig): Signature { - if (signature instanceof Signature) { - signature.assertValidity(); - return signature; - } - try { - return Signature.fromDER(signature); - } catch (error) { - return Signature.fromCompact(signature); - } } -/** - * Computes public key for secp256k1 private key. - * @param privateKey 32-byte private key - * @param isCompressed whether to return compact, or full key - * @returns Public key, full by default; short when isCompressed=true - */ -export function getPublicKey(privateKey: PrivKey, isCompressed = false): Uint8Array { - return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed); -} - -/** - * Recovers public key from signature and recovery bit. Throws on invalid sig/hash. - * @param msgHash message hash - * @param signature DER or compact sig - * @param recovery 0 or 1 - * @param isCompressed whether to return compact, or full key - * @returns Public key, full by default; short when isCompressed=true - */ -export function recoverPublicKey( - msgHash: Hex, - signature: Sig, - recovery: number, - isCompressed = false -): Uint8Array { - return Point.fromSignature(msgHash, signature, recovery).toRawBytes(isCompressed); -} - -/** - * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. - */ -function isProbPub(item: PrivKey | PubKey): boolean { - const arr = item instanceof Uint8Array; - const str = typeof item === 'string'; - const len = (arr || str) && (item as Hex).length; - if (arr) return len === compressedLen || len === uncompressedLen; - if (str) return len === compressedLen * 2 || len === uncompressedLen * 2; - if (item instanceof Point) return true; - return false; -} - -/** - * ECDH (Elliptic Curve Diffie Hellman) implementation. - * 1. Checks for validity of private key - * 2. Checks for the public key of being on-curve - * @param privateA private key - * @param publicB different public key - * @param isCompressed whether to return compact, or full key - * @returns shared public key - */ -export function getSharedSecret( - privateA: PrivKey, - publicB: PubKey, - isCompressed = false -): Uint8Array { - if (isProbPub(privateA)) throw new TypeError('getSharedSecret: first arg must be private key'); - if (!isProbPub(publicB)) throw new TypeError('getSharedSecret: second arg must be public key'); - const b = normalizePublicKey(publicB); - b.assertValidity(); - return b.multiply(normalizePrivateKey(privateA)).toRawBytes(isCompressed); -} - -type Entropy = Hex | true; -type OptsOther = { canonical?: boolean; der?: boolean; extraEntropy?: Entropy }; -type OptsRecov = { recovered: true } & OptsOther; -type OptsNoRecov = { recovered?: false } & OptsOther; -type Opts = { recovered?: boolean } & OptsOther; -type SignOutput = Uint8Array | [Uint8Array, number]; - -// RFC6979 methods -function bits2int(bytes: Uint8Array) { - const slice = bytes.length > fieldLen ? bytes.slice(0, fieldLen) : bytes; - return bytesToNumber(slice); -} -function bits2octets(bytes: Uint8Array): Uint8Array { - const z1 = bits2int(bytes); - const z2 = mod(z1, CURVE.n); - return int2octets(z2 < _0n ? z1 : z2); -} -function int2octets(num: bigint): Uint8Array { - return numTo32b(num); // prohibits >32 bytes -} - -// Steps A, D of RFC6979 3.2 -// Creates RFC6979 seed; converts msg/privKey to numbers. -function initSigArgs(msgHash: Hex, privateKey: PrivKey, extraEntropy?: Entropy) { - if (msgHash == null) throw new Error(`sign: expected valid message hash, not "${msgHash}"`); - // Step A is ignored, since we already provide hash instead of msg - const h1 = ensureBytes(msgHash); - const d = normalizePrivateKey(privateKey); - // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - const seedArgs = [int2octets(d), bits2octets(h1)]; - // RFC6979 3.6: additional k' could be provided - if (extraEntropy != null) { - if (extraEntropy === true) extraEntropy = utils.randomBytes(fieldLen); - const e = ensureBytes(extraEntropy); - if (e.length !== fieldLen) throw new Error(`sign: Expected ${fieldLen} bytes of extra data`); - seedArgs.push(e); - } - // seed is constructed from private key and message - // Step D - // V, 0x00 are done in HmacDRBG constructor. +export async function sign(msgHash: Hex, privKey: Hex, opts = stdOpts): Promise { + if (opts?.der === true) throw new Error(); + if (opts?.extraEntropy) throw new Error(); + if (opts?.lowS == null) opts.lowS = true; + const _h1 = numToField(truncateHash(ensureBytes(msgHash))); // Steps A, D of RFC6979 3.2. + const d = normalizePrivKey(privKey); + if (!isValidGE(d)) throw new Error(); + const seedArgs = [int2octets(d), bits2octets(_h1)]; const seed = concatBytes(...seedArgs); - const m = bits2int(h1); - return { seed, m, d }; -} - -// Takes signature with its recovery bit, normalizes it -// Produces DER/compact signature and proper recovery bit -function finalizeSig(recSig: RecoveredSig, opts: OptsNoRecov | OptsRecov): SignOutput { - const { sig, recovery } = recSig; - const { der, recovered } = Object.assign({ canonical: true, der: true }, opts); - const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes(); - return recovered ? [hashed, recovery] : hashed; -} - -/** - * Signs message hash (not message: you need to hash it by yourself). - * We don't auto-hash because some users would want non-SHA256 hash. - * We are always using deterministic signatures (RFC6979 3.1) instead of - * letting user specify random k. - * HMAC-DRBG generates k, then calculates sig point Q & signature r, s based on it. - * Could receive extra entropy k' as per RFC6979 3.6 Additional data. - * k' is not generated by default, because of backwards-compatibility concerns. - * We strongly recommend to pass {extraEntropy: true}. - * - * low-s signatures are generated by default. If you don't want it, use canonical: false. - * - * ``` - * sign(m, d, k) where - * (x, y) = G × k - * r = x mod n - * s = (m + dr)/k mod n - * ``` - * @param opts `recovered, canonical, der, extraEntropy` - */ -async function sign(msgHash: Hex, privKey: PrivKey, opts: OptsRecov): Promise<[U8A, number]>; -async function sign(msgHash: Hex, privKey: PrivKey, opts?: OptsNoRecov): Promise; -async function sign(msgHash: Hex, privKey: PrivKey, opts: Opts = {}): Promise { - // Steps A, D of RFC6979 3.2. - const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); - // Steps B, C, D, E, F, G - const drbg = new HmacDrbg(hashLen, groupLen); + const m = bits2int(_h1); + const drbg = new HmacDrbg(); // Steps B, C, D, E, F, G of RFC6979 3.2. await drbg.reseed(seed); - // Step H3, repeat until k is in range [1, n-1] - let sig: RecoveredSig | undefined; - while (!(sig = kmdToSig(await drbg.generate(), m, d, opts.canonical))) await drbg.reseed(); - return finalizeSig(sig, opts); + let sig: Signature | undefined; // Step H3, repeat until k is in range [1, n-1] + while (!(sig = Signature.fromKMD(await drbg.generate(), m, d, !!opts?.lowS))) await drbg.reseed(); + return sig; } -/** - * Signs message hash (not message: you need to hash it by yourself). - * Synchronous version of `sign()`: see its documentation. - * @param opts `recovered, canonical, der, extraEntropy` - */ -function signSync(msgHash: Hex, privKey: PrivKey, opts: OptsRecov): [U8A, number]; -function signSync(msgHash: Hex, privKey: PrivKey, opts?: OptsNoRecov): U8A; -function signSync(msgHash: Hex, privKey: PrivKey, opts: Opts = {}): SignOutput { - // Steps A, D of RFC6979 3.2. - const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy); - // Steps B, C, D, E, F, G - const drbg = new HmacDrbg(hashLen, groupLen); - drbg.reseedSync(seed); - // Step H3, repeat until k is in range [1, n-1] - let sig: RecoveredSig | undefined; - while (!(sig = kmdToSig(drbg.generateSync(), m, d, opts.canonical))) drbg.reseedSync(); - return finalizeSig(sig, opts); -} -export { sign, signSync }; - -type VOpts = { strict?: boolean }; -const vopts: VOpts = { strict: true }; - -/** - * Verifies a signature against message hash and public key. - * Rejects non-canonical / high-s signatures by default: to override, - * specify option `{strict: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: - * - * ``` - * verify(r, s, h, P) where - * U1 = hs^-1 mod n - * U2 = rs^-1 mod n - * R = U1⋅G - U2⋅P - * mod(R.x, n) == r - * ``` - */ -export function verify(signature: Sig, msgHash: Hex, publicKey: PubKey, opts = vopts): boolean { - let sig; +type Sig = Hex | Signature; +export function verify(sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boolean { + if (opts?.lowS == null) opts.lowS = true; + let sig_: Signature; try { - sig = normalizeSignature(signature); - msgHash = ensureBytes(msgHash); + sig_ = sig instanceof Signature ? sig.assertValidity() : Signature.fromCompact(sig); } catch (error) { return false; } - const { r, s } = sig; - if (opts.strict && sig.hasHighS()) return false; - const h = truncateHash(msgHash); + if (!sig_) return false; + const { r, s } = sig_; + if (opts?.lowS && isBiggerThanHalfOrder(s)) return false; + const h = truncateHash(ensureBytes(msgHash, fLen)); - let P; + let P: Point; try { - P = normalizePublicKey(publicKey); + P = pubKey instanceof Point ? pubKey.assertValidity() : Point.fromHex(pubKey); } catch (error) { return false; } const { n } = CURVE; - const sinv = invert(s, n); // s^-1 - // R = u1⋅G - u2⋅P - const u1 = mod(h * sinv, n); - const u2 = mod(r * sinv, n); - - // Some implementations compare R.x in jacobian, without inversion. - // The speed-up is <5%, so we don't complicate the code. - const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2); - if (!R) return false; - const v = mod(R.x, n); - return v === r; -} - -// Schnorr signatures are superior to ECDSA from above. -// Below is Schnorr-specific code as per BIP0340. -function schnorrChallengeFinalize(ch: Uint8Array): bigint { - return mod(bytesToNumber(ch), CURVE.n); -} - -class SchnorrSignature { - constructor(readonly r: bigint, readonly s: bigint) { - this.assertValidity(); - } - static fromHex(hex: Hex) { - const bytes = ensureBytes(hex); - if (bytes.length !== 64) - throw new TypeError(`SchnorrSignature.fromHex: expected 64 bytes, not ${bytes.length}`); - const r = bytesToNumber(bytes.subarray(0, 32)); - const s = bytesToNumber(bytes.subarray(32, 64)); - return new SchnorrSignature(r, s); - } - assertValidity() { - const { r, s } = this; - if (!isValidFieldElement(r) || !isWithinCurveOrder(s)) throw new Error('Invalid signature'); - } - toHex(): string { - return numTo32bStr(this.r) + numTo32bStr(this.s); - } - toRawBytes(): Uint8Array { - return hexToBytes(this.toHex()); - } -} - -// Schnorr's pubkey is just `x` of Point -// BIP340 -function schnorrGetPublicKey(privateKey: PrivKey): Uint8Array { - return Point.fromPrivateKey(privateKey).toRawX(); -} - -// We are abstracting the signature creation process into the class -// because we need to provide two identical methods: async & sync. Usage: -// new InternalSchnorrSignature(msg, privKey, auxRand).calc() -class InternalSchnorrSignature { - private m: Uint8Array; - private px: Uint8Array; - private d: bigint; - private rand: Uint8Array; - - constructor(message: Hex, privateKey: PrivKey, auxRand: Hex = utils.randomBytes()) { - if (message == null) throw new TypeError(`sign: Expected valid message, not "${message}"`); - this.m = ensureBytes(message); - // checks for isWithinCurveOrder - const { x, scalar } = this.getScalar(normalizePrivateKey(privateKey)); - this.px = x; - this.d = scalar; - this.rand = ensureBytes(auxRand); - if (this.rand.length !== 32) throw new TypeError('sign: Expected 32 bytes of aux randomness'); - } - - private getScalar(priv: bigint) { - const point = Point.fromPrivateKey(priv); - const scalar = point.hasEvenY() ? priv : CURVE.n - priv; - return { point, scalar, x: point.toRawX() }; - } - - private initNonce(d: bigint, t0h: Uint8Array): Uint8Array { - return numTo32b(d ^ bytesToNumber(t0h)); - } - private finalizeNonce(k0h: Uint8Array) { - const k0 = mod(bytesToNumber(k0h), CURVE.n); - if (k0 === _0n) throw new Error('sign: Creation of signature failed. k is zero'); - const { point: R, x: rx, scalar: k } = this.getScalar(k0); - return { R, rx, k }; - } - private finalizeSig(R: Point, k: bigint, e: bigint, d: bigint): Uint8Array { - return new SchnorrSignature(R.x, mod(k + e * d, CURVE.n)).toRawBytes(); - } - private error() { - throw new Error('sign: Invalid signature produced'); - } - - async calc() { - const { m, d, px, rand } = this; - const tag = utils.taggedHash; - const t = this.initNonce(d, await tag(TAGS.aux, rand)); - const { R, rx, k } = this.finalizeNonce(await tag(TAGS.nonce, t, px, m)); - const e = schnorrChallengeFinalize(await tag(TAGS.challenge, rx, px, m)); - const sig = this.finalizeSig(R, k, e, d); - if (!(await schnorrVerify(sig, m, px))) this.error(); - return sig; - } - calcSync() { - const { m, d, px, rand } = this; - const tag = utils.taggedHashSync; - const t = this.initNonce(d, tag(TAGS.aux, rand)); - const { R, rx, k } = this.finalizeNonce(tag(TAGS.nonce, t, px, m)); - const e = schnorrChallengeFinalize(tag(TAGS.challenge, rx, px, m)); - const sig = this.finalizeSig(R, k, e, d); - if (!schnorrVerifySync(sig, m, px)) this.error(); - return sig; - } -} - -/** - * Creates Schnorr signature. Improved security: verifies itself before producing an output. - * @param msg message (not message hash) - * @param privateKey private key - * @param auxRand random bytes that would be added to k. Bad RNG won't break it. - */ -async function schnorrSign(msg: Hex, privKey: PrivKey, auxRand?: Hex): Promise { - return new InternalSchnorrSignature(msg, privKey, auxRand).calc(); -} - -/** - * Synchronously creates Schnorr signature. Improved security: verifies itself before - * producing an output. - * @param msg message (not message hash) - * @param privateKey private key - * @param auxRand random bytes that would be added to k. Bad RNG won't break it. - */ -function schnorrSignSync(msg: Hex, privKey: PrivKey, auxRand?: Hex): Uint8Array { - return new InternalSchnorrSignature(msg, privKey, auxRand).calcSync(); -} - -function initSchnorrVerify(signature: Hex, message: Hex, publicKey: Hex) { - const raw = signature instanceof SchnorrSignature; - const sig: SchnorrSignature = raw ? signature : SchnorrSignature.fromHex(signature); - if (raw) sig.assertValidity(); // just in case - - return { - ...sig, - m: ensureBytes(message), - P: normalizePublicKey(publicKey), - }; -} - -function finalizeSchnorrVerify(r: bigint, P: Point, s: bigint, e: bigint): boolean { - // R = s⋅G - e⋅P - // -eP == (n-e)P - const R = Point.BASE.multiplyAndAddUnsafe(P, normalizePrivateKey(s), mod(-e, CURVE.n)); - if (!R || !R.hasEvenY() || R.x !== r) return false; - return true; -} - -/** - * Verifies Schnorr signature. - */ -async function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): Promise { + let R: Point; try { - const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey); - const e = schnorrChallengeFinalize( - await utils.taggedHash(TAGS.challenge, numTo32b(r), P.toRawX(), m) - ); - return finalizeSchnorrVerify(r, P, s, e); + const sinv = invert(s, n); // R = u1⋅G + u2⋅P + R = Point.BASE.multiply(mod(h * sinv, n)).add(P.multiply(mod(r * sinv, n))); } catch (error) { return false; } + if (R.equals(Point.ZERO)) return false; + const v = mod(R.x, n); + return v === r; } - -/** - * Verifies Schnorr signature synchronously. - */ -function schnorrVerifySync(signature: Hex, message: Hex, publicKey: Hex): boolean { - try { - const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey); - const e = schnorrChallengeFinalize( - utils.taggedHashSync(TAGS.challenge, numTo32b(r), P.toRawX(), m) - ); - return finalizeSchnorrVerify(r, P, s, e); - } catch (error) { - if (error instanceof ShaError) throw error; - return false; - } +export function getSharedSecret(privA: Hex, pubB: Hex, isCompressed?: boolean) { + return Point.fromHex(pubB).multiply(normalizePrivKey(privA)).toRawBytes(isCompressed); } -export const schnorr = { - Signature: SchnorrSignature, - getPublicKey: schnorrGetPublicKey, - sign: schnorrSign, - verify: schnorrVerify, - signSync: schnorrSignSync, - verifySync: schnorrVerifySync, -}; - -// Enable precomputes. Slows down first publicKey computation by 20ms. -Point.BASE._setWindowSize(8); - -// Global symbol available in browsers only. Ensure we do not depend on @types/dom -declare const self: Record | undefined; -const crypto: { node?: any; web?: any } = { - node: nodeCrypto, - web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, -}; - -const TAGS = { - challenge: 'BIP0340/challenge', - aux: 'BIP0340/aux', - nonce: 'BIP0340/nonce', -} as const; -/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ -const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {}; - export const utils = { - bytesToHex, - hexToBytes, - concatBytes, mod, invert, - - isValidPrivateKey(privateKey: PrivKey) { - try { - normalizePrivateKey(privateKey); - return true; - } catch (error) { - return false; - } - }, - _bigintTo32Bytes: numTo32b, - _normalizePrivateKey: normalizePrivateKey, - - /** - * Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private key, with the modulo bias being neglible. - * As per FIPS 186 B.4.1. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * @param hash hash output from sha512, or a similar function - * @returns valid private key - */ + concatBytes, + hexToBytes, + bytesToHex, + bytesToNumber, + numToField, hashToPrivateKey: (hash: Hex): Uint8Array => { hash = ensureBytes(hash); - const minLen = groupLen + 8; - if (hash.length < minLen || hash.length > 1024) { - throw new Error(`Expected valid bytes of private key as per FIPS 186`); - } - const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n; - return numTo32b(num); - }, - - randomBytes: (bytesLength: number = 32): Uint8Array => { - if (crypto.web) { - return crypto.web.getRandomValues(new Uint8Array(bytesLength)); - } else if (crypto.node) { - const { randomBytes } = crypto.node; - return Uint8Array.from(randomBytes(bytesLength)); - } else { - throw new Error("The environment doesn't have randomBytes function"); - } - }, - - // Takes curve order + 64 bits from CSPRNG - // so that modulo bias is neglible, matches FIPS 186 B.4.1. - randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)), - - /** - * 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it. - * 2. Precomputes point multiplication table. Is done by default on first `getPublicKey()` call. - * If you want your first getPublicKey to take 0.16ms instead of 20ms, make sure to call - * utils.precompute() somewhere without arguments first. - * @param windowSize 2, 4, 8, 16 - * @returns cached point - */ - precompute(windowSize = 8, point = Point.BASE): Point { - const cached = point === Point.BASE ? point : new Point(point.x, point.y); - cached._setWindowSize(windowSize); - cached.multiply(_3n); - return cached; - }, - - sha256: async (...messages: Uint8Array[]): Promise => { - if (crypto.web) { - const buffer = await crypto.web.subtle.digest('SHA-256', concatBytes(...messages)); - return new Uint8Array(buffer); - } else if (crypto.node) { - const { createHash } = crypto.node; - const hash = createHash('sha256'); - messages.forEach((m) => hash.update(m)); - return Uint8Array.from(hash.digest()); - } else { - throw new Error("The environment doesn't have sha256 function"); - } - }, - - hmacSha256: async (key: Uint8Array, ...messages: Uint8Array[]): Promise => { - if (crypto.web) { - // prettier-ignore - const ckey = await crypto.web.subtle.importKey( - 'raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign'] - ); - const message = concatBytes(...messages); - const buffer = await crypto.web.subtle.sign('HMAC', ckey, message); - return new Uint8Array(buffer); - } else if (crypto.node) { - const { createHmac } = crypto.node; - const hash = createHmac('sha256', key); - messages.forEach((m) => hash.update(m)); - return Uint8Array.from(hash.digest()); - } else { - throw new Error("The environment doesn't have hmac-sha256 function"); - } + const minLen = fLen + 8; + if (hash.length < minLen || hash.length > 1024) throw new Error(); + const num = mod(bytesToNumber(hash), CURVE.n - 1n) + 1n; + return numToField(num); }, - - // See Object.defineProp below - sha256Sync: undefined as Sha256FnSync, - hmacSha256Sync: undefined as HmacFnSync, - - taggedHash: async (tag: string, ...messages: Uint8Array[]): Promise => { - let tagP = TAGGED_HASH_PREFIXES[tag]; - if (tagP === undefined) { - const tagH = await utils.sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))); - tagP = concatBytes(tagH, tagH); - TAGGED_HASH_PREFIXES[tag] = tagP; - } - - return utils.sha256(tagP, ...messages); - }, - - taggedHashSync: (tag: string, ...messages: Uint8Array[]): Uint8Array => { - if (typeof _sha256Sync !== 'function') - throw new ShaError('sha256Sync is undefined, you need to set it'); - let tagP = TAGGED_HASH_PREFIXES[tag]; - if (tagP === undefined) { - const tagH = _sha256Sync(Uint8Array.from(tag, (c) => c.charCodeAt(0))); - tagP = concatBytes(tagH, tagH); - TAGGED_HASH_PREFIXES[tag] = tagP; + randomBytes, + // FIPS 186 B.4.1. + randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(fLen + 8)), + isValidPrivateKey: (key: Hex) => { + try { + return !!normalizePrivKey(key); + } catch (e) { + return false; } - - return _sha256Sync(tagP, ...messages); }, - - // For tests - _JacobianPoint: JacobianPoint, }; - -// Make sure sync hash could only be set once. -Object.defineProperties(utils, { - sha256Sync: { - configurable: false, - get() { - return _sha256Sync; - }, - set(val) { - if (!_sha256Sync) _sha256Sync = val; - }, - }, - hmacSha256Sync: { - configurable: false, - get() { - return _hmacSha256Sync; - }, - set(val) { - if (!_hmacSha256Sync) _hmacSha256Sync = val; - }, - }, -}); From 6d752c68f50275e46023cff310763db86138c81d Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 13 Jan 2023 22:11:56 +0000 Subject: [PATCH 012/145] micro-noble-secp. Iteration 2: 8681 --- index.ts | 190 ++++++++++++++++++++++++++++++++------------------- package.json | 1 + 2 files changed, 121 insertions(+), 70 deletions(-) diff --git a/index.ts b/index.ts index ef09430..533d0dd 100644 --- a/index.ts +++ b/index.ts @@ -1,10 +1,11 @@ +const B256 = 2n ** 256n; export const CURVE = { - P: 2n ** 256n - 2n ** 32n - 977n, - n: 2n ** 256n - 432420386565659656852420866394968145599n, + P: B256 - 2n ** 32n - 977n, + n: B256 - 0x14551231950b75fc4402da1732fc9bebfn, a: 0n, b: 7n, - Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n, - Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n, + Gx: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n, + Gy: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n, }; const fLen = 32; // field/group byte length const stdOpts: { lowS?: boolean; der?: boolean; extraEntropy?: any } = { lowS: true }; @@ -13,11 +14,11 @@ const isValidFE = (n: bigint) => typeof n === 'bigint' && 0n < n && n < CURVE.P; const isValidGE = (n: bigint) => typeof n === 'bigint' && 0n < n && n < CURVE.n; const weierstrass = (x: bigint) => mod(mod(x * mod(x * x)) + CURVE.a * x + CURVE.b); -function assertBytes(a: any, len?: number) { +const assertBytes = (a: any, len?: number) => { if (!(a instanceof Uint8Array)) throw new Error('ui8a expected'); if (typeof len === 'number' && len > 0 && a.length !== len) throw new Error('len expected'); return a; -} +}; const ensureBytes = (a: any, len?: number) => assertBytes(typeof a === 'string' ? hexToBytes(a) : a, len); function normalizePrivKey(privKey: Hex | bigint) { @@ -25,6 +26,91 @@ function normalizePrivKey(privKey: Hex | bigint) { if (!isValidGE(privKey)) throw new Error(); return privKey; } +const assertPrjPoint = (p: any) => { + if (!(p instanceof ProjP)) throw new Error(); +}; +class ProjP { + static readonly G = new ProjP(CURVE.Gx, CURVE.Gy, 1n); + static readonly I = new ProjP(0n, 1n, 0n); + static fromAffine(p: Point) { + if (!(p instanceof Point)) throw new Error(); + return new ProjP(p.x, p.y, 1n); + } + constructor(readonly x: bigint, readonly y: bigint, readonly z: bigint) {} + eql(other: ProjP): boolean { + assertPrjPoint(other); + const { x: X1, y: Y1, z: Z1 } = this; + const { x: X2, y: Y2, z: Z2 } = other; + return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); + } + dbl() { + return this.add(this); + } + add(other: ProjP) { + assertPrjPoint(other); + const { x: X1, y: Y1, z: Z1 } = this; + const { x: X2, y: Y2, z: Z2 } = other; + let X3 = 0n, Y3 = 0n, Z3 = 0n; // prettier-ignore + const a = CURVE.a; + const b3 = mod(CURVE.b * 3n); + let t0 = mod(X1 * X2); // step 1 + let t1 = mod(Y1 * Y2); + let t2 = mod(Z1 * Z2); + let t3 = mod(X1 + Y1); + let t4 = mod(X2 + Y2); // step 5 + t3 = mod(t3 * t4); + t4 = mod(t0 + t1); + t3 = mod(t3 - t4); + t4 = mod(X1 + Z1); + let t5 = mod(X2 + Z2); // step 10 + t4 = mod(t4 * t5); + t5 = mod(t0 + t2); + t4 = mod(t4 - t5); + t5 = mod(Y1 + Z1); + X3 = mod(Y2 + Z2); // step 15 + t5 = mod(t5 * X3); + X3 = mod(t1 + t2); + t5 = mod(t5 - X3); + Z3 = mod(a * t4); + X3 = mod(b3 * t2); // step 20 + Z3 = mod(X3 + Z3); + X3 = mod(t1 - Z3); + Z3 = mod(t1 + Z3); + Y3 = mod(X3 * Z3); + t1 = mod(t0 + t0); // step 25 + t1 = mod(t1 + t0); + t2 = mod(a * t2); + t4 = mod(b3 * t4); + t1 = mod(t1 + t2); + t2 = mod(t0 - t2); // step 30 + t2 = mod(a * t2); + t4 = mod(t4 + t2); + t0 = mod(t1 * t4); + Y3 = mod(Y3 + t0); + t0 = mod(t5 * t4); // step 35 + X3 = mod(t3 * X3); + X3 = mod(X3 - t0); + t0 = mod(t3 * t1); + Z3 = mod(t5 * Z3); + Z3 = mod(Z3 + t0); // step 40 + return new ProjP(X3, Y3, Z3); + } + mul(n: bigint) { + if (!isValidGE(n)) throw new Error(); + let p = ProjP.I; + for (let d: ProjP = this; n > 0n; d = d.dbl(), n >>= 1n) { + if (n & 1n) p = p.add(d); + } + return p; + } + aff() { + const { x, y, z } = this; + if (this.eql(ProjP.I)) return Point.ZERO; + const iz = invert(this.z); + if (mod(z * iz) !== 1n) throw new Error(); + return new Point(mod(x * iz), mod(y * iz)); + } +} export class Point { static BASE = new Point(CURVE.Gx, CURVE.Gy); static ZERO = new Point(0n, 0n); @@ -32,7 +118,7 @@ export class Point { return Point.BASE.multiply(normalizePrivKey(privKey)); } constructor(readonly x: bigint, readonly y: bigint) {} - assertValidity() { + ok() { const { x, y } = this; if (!isValidFE(x) || !isValidFE(y)) throw new Error(); if (mod(mod(y * y) - weierstrass(x)) !== 0n) throw new Error(); @@ -41,40 +127,14 @@ export class Point { equals(other: Point) { return this.x === other.x && this.y === other.y; } - double(): Point { - const { x: X1, y: Y1 } = this; - const lam = mod(3n * X1 ** 2n * invert(2n * Y1)); - const X3 = mod(lam * lam - 2n * X1); - const Y3 = mod(lam * (X1 - X3) - Y1); - return new Point(X3, Y3); - } - // https://hyperelliptic.org/EFD/g1p/auto-shortw.html - add(b: Point): Point { - const a = this; - const { x: X1, y: Y1 } = a; - const { x: X2, y: Y2 } = b; - if (X1 === 0n || Y1 === 0n) return b; - if (X2 === 0n || Y2 === 0n) return a; - if (X1 === X2 && Y1 === Y2) return this.double(); - if (X1 === X2 && Y1 === -Y2) return Point.ZERO; - const x2x1 = mod(X2 - X1); - if (x2x1 === 0n) return Point.ZERO; - const lam = mod((Y2 - Y1) * invert(x2x1)); - const X3 = mod(lam * lam - X1 - X2); - const Y3 = mod(lam * (X1 - X3) - Y1); - return new Point(X3, Y3); - } negate() { return new Point(this.x, mod(-this.y)); } - subtract(b: Point) { - return this.add(b.negate()); + add(rhs: Point) { + return ProjP.fromAffine(this).add(ProjP.fromAffine(rhs)).aff(); } multiply(n: bigint) { - if (!isValidGE(n)) throw new Error(); - let p = Point.ZERO; - for (let d: Point = this; n > 0n; d = d.double(), n >>= 1n) if (n & 1n) p = p.add(d); - return p; + return ProjP.fromAffine(this).mul(n).aff(); } static fromHex(hex: Hex) { hex = ensureBytes(hex); @@ -92,7 +152,7 @@ export class Point { } if (hex.length === 65 && head === 0x04) p = new Point(x, sliceNum(tail, fLen, 2 * fLen)); if (!p) throw new Error(); - return p.assertValidity(); + return p.ok(); } toHex(isCompressed = false) { const { x, y } = this; @@ -150,11 +210,11 @@ function bytesToHex(uint8a: Uint8Array): string { return hex; } function hexToNumber(hex: string): bigint { - if (typeof hex !== 'string') throw new TypeError(); + if (typeof hex !== 'string') throw new Error(); return BigInt(`0x${hex}`); } function hexToBytes(hex: string): Uint8Array { - if (typeof hex !== 'string') throw new TypeError(); + if (typeof hex !== 'string') throw new Error(); if (hex.length % 2) throw new Error(); const array = new Uint8Array(hex.length / 2); for (let i = 0; i < array.length; i++) { @@ -170,7 +230,7 @@ const bytesToNumber = (b: Uint8Array): bigint => hexToNumber(bytesToHex(b)); const sliceNum = (b: Uint8Array, from: number, to: number) => bytesToNumber(b.slice(from, to)); function numToField(num: bigint): Uint8Array { if (typeof num !== 'bigint') throw new Error(); - if (!(0n <= num && num < 2n ** 256n)) throw new Error(); + if (!(0n <= num && num < B256)) throw new Error(); return hexToBytes(num.toString(16).padStart(2 * fLen, '0')); } const numToFieldStr = (num: bigint): string => bytesToHex(numToField(num)); @@ -294,38 +354,26 @@ class HmacDrbg { k: Uint8Array; v: Uint8Array; counter: number; - constructor(public hashLen = fLen, public qByteLen = fLen) { + constructor() { // Step B, Step C: set hashLen to 8*ceil(hlen/8) - this.v = new Uint8Array(hashLen).fill(1); - this.k = new Uint8Array(hashLen).fill(0); + this.v = new Uint8Array(fLen).fill(1); + this.k = new Uint8Array(fLen).fill(0); this.counter = 0; } - private hmac(...values: Uint8Array[]) { - return hmac(this.k, ...values); - } - incr() { - if (this.counter >= 1000) throw new Error('Tried 1,000 k values for sign(), all were invalid'); - this.counter += 1; - } - async reseed(seed = new Uint8Array()) { - this.k = await this.hmac(this.v, Uint8Array.from([0x00]), seed); - this.v = await this.hmac(this.v); + const hk = (...vs: Uint8Array[]) => hmac(this.k, ...vs); + const hv = (...vs: Uint8Array[]) => hk(this.v, ...vs); + this.k = await hv(Uint8Array.from([0x00]), seed); + this.v = await hv(); if (seed.length === 0) return; - this.k = await this.hmac(this.v, Uint8Array.from([0x01]), seed); - this.v = await this.hmac(this.v); + this.k = await hv(Uint8Array.from([0x01]), seed); + this.v = await hv(); } async generate(): Promise { - this.incr(); - let len = 0; - const out: Uint8Array[] = []; - while (len < this.qByteLen) { - this.v = await this.hmac(this.v); - const sl = this.v.slice(); - out.push(sl); - len += this.v.length; - } - return concatBytes(...out); + if (this.counter >= 1000) throw new Error('Tried 1,000 k values for sign(), all were invalid'); + this.counter += 1; + this.v = await hmac(this.k, this.v); + return this.v; } } @@ -362,19 +410,21 @@ export function verify(sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boo let P: Point; try { - P = pubKey instanceof Point ? pubKey.assertValidity() : Point.fromHex(pubKey); + P = pubKey instanceof Point ? pubKey.ok() : Point.fromHex(pubKey); } catch (error) { return false; } const { n } = CURVE; - let R: Point; + let R: Point | undefined = undefined; try { - const sinv = invert(s, n); // R = u1⋅G + u2⋅P - R = Point.BASE.multiply(mod(h * sinv, n)).add(P.multiply(mod(r * sinv, n))); + const is = invert(s, n); // R = u1⋅G + u2⋅P + const u1 = mod(h * is, n); + const u2 = mod(r * is, n); + R = Point.BASE.multiply(u1).add(P.multiply(u2)); } catch (error) { return false; } - if (R.equals(Point.ZERO)) return false; + if (!R) return false; const v = mod(R.x, n); return v === r; } diff --git a/package.json b/package.json index 5fb67d9..da9798f 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "micro-bmark": "0.2.0", "prettier": "2.6.2", "rollup": "2.75.5", + "terser": "^5.16.1", "ts-jest": "28.0.4", "typescript": "4.7.3" }, From bc87ff5e28ccb6a4a95b405fa0d59c316cd6263a Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 13 Jan 2023 22:12:36 +0000 Subject: [PATCH 013/145] micro-noble-secp. Iteration 3: 7418 --- index.ts | 340 +++++++++++++++++++++++++-------------------------- package.json | 3 +- 2 files changed, 169 insertions(+), 174 deletions(-) diff --git a/index.ts b/index.ts index 533d0dd..c518ec0 100644 --- a/index.ts +++ b/index.ts @@ -1,44 +1,45 @@ +/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ const B256 = 2n ** 256n; -export const CURVE = { - P: B256 - 2n ** 32n - 977n, - n: B256 - 0x14551231950b75fc4402da1732fc9bebfn, - a: 0n, - b: 7n, - Gx: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n, - Gy: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n, -}; +const P = B256 - 2n ** 32n - 977n; +const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; +const a = 0n; +const b = 7n; +const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; +const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; +export const CURVE = { P, n: N, a, b, Gx, Gy }; const fLen = 32; // field/group byte length const stdOpts: { lowS?: boolean; der?: boolean; extraEntropy?: any } = { lowS: true }; type Hex = Uint8Array | string; -const isValidFE = (n: bigint) => typeof n === 'bigint' && 0n < n && n < CURVE.P; -const isValidGE = (n: bigint) => typeof n === 'bigint' && 0n < n && n < CURVE.n; -const weierstrass = (x: bigint) => mod(mod(x * mod(x * x)) + CURVE.a * x + CURVE.b); - -const assertBytes = (a: any, len?: number) => { - if (!(a instanceof Uint8Array)) throw new Error('ui8a expected'); - if (typeof len === 'number' && len > 0 && a.length !== len) throw new Error('len expected'); +const fe = (n: bigint) => typeof n === 'bigint' && 0n < n && n < P; +const ge = (n: bigint) => typeof n === 'bigint' && 0n < n && n < N; +const weierstrass = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); +const err = (): never => { + throw new TypeError(); +}; +const isBytes = (a: any, len?: number): Uint8Array => { + if (!(a instanceof Uint8Array)) err(); + if (typeof len === 'number' && len > 0 && a.length !== len) err(); return a; }; -const ensureBytes = (a: any, len?: number) => - assertBytes(typeof a === 'string' ? hexToBytes(a) : a, len); -function normalizePrivKey(privKey: Hex | bigint) { - if (typeof privKey !== 'bigint') privKey = bytesToNumber(ensureBytes(privKey, fLen)); - if (!isValidGE(privKey)) throw new Error(); +const ensureBytes = (a: any, len?: number) => isBytes(typeof a === 'string' ? h2b(a) : a, len); +const normPriv = (privKey: Hex | bigint) => { + if (typeof privKey !== 'bigint') privKey = b2n(ensureBytes(privKey, fLen)); + if (!ge(privKey)) err(); return privKey; -} -const assertPrjPoint = (p: any) => { - if (!(p instanceof ProjP)) throw new Error(); }; -class ProjP { - static readonly G = new ProjP(CURVE.Gx, CURVE.Gy, 1n); - static readonly I = new ProjP(0n, 1n, 0n); - static fromAffine(p: Point) { - if (!(p instanceof Point)) throw new Error(); - return new ProjP(p.x, p.y, 1n); +const isProj = (p: any) => { + if (!(p instanceof Proj)) err(); +}; +class Proj { + static readonly G = new Proj(Gx, Gy, 1n); + static readonly I = new Proj(0n, 1n, 0n); + static frAff(p: Point) { + if (!(p instanceof Point)) err(); + return new Proj(p.x, p.y, 1n); } constructor(readonly x: bigint, readonly y: bigint, readonly z: bigint) {} - eql(other: ProjP): boolean { - assertPrjPoint(other); + eql(other: Proj): boolean { + isProj(other); const { x: X1, y: Y1, z: Z1 } = this; const { x: X2, y: Y2, z: Z2 } = other; return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); @@ -46,13 +47,13 @@ class ProjP { dbl() { return this.add(this); } - add(other: ProjP) { - assertPrjPoint(other); + add(other: Proj) { + isProj(other); const { x: X1, y: Y1, z: Z1 } = this; const { x: X2, y: Y2, z: Z2 } = other; let X3 = 0n, Y3 = 0n, Z3 = 0n; // prettier-ignore - const a = CURVE.a; - const b3 = mod(CURVE.b * 3n); + const { a, b } = CURVE; + const b3 = mod(b * 3n); let t0 = mod(X1 * X2); // step 1 let t1 = mod(Y1 * Y2); let t2 = mod(Z1 * Z2); @@ -93,35 +94,35 @@ class ProjP { t0 = mod(t3 * t1); Z3 = mod(t5 * Z3); Z3 = mod(Z3 + t0); // step 40 - return new ProjP(X3, Y3, Z3); + return new Proj(X3, Y3, Z3); } mul(n: bigint) { - if (!isValidGE(n)) throw new Error(); - let p = ProjP.I; - for (let d: ProjP = this; n > 0n; d = d.dbl(), n >>= 1n) { + if (!ge(n)) err(); + let p = Proj.I; + for (let d: Proj = this; n > 0n; d = d.dbl(), n >>= 1n) { if (n & 1n) p = p.add(d); } return p; } aff() { const { x, y, z } = this; - if (this.eql(ProjP.I)) return Point.ZERO; - const iz = invert(this.z); - if (mod(z * iz) !== 1n) throw new Error(); + if (this.eql(Proj.I)) return Point.ZERO; + const iz = inv(this.z); + if (mod(z * iz) !== 1n) err(); return new Point(mod(x * iz), mod(y * iz)); } } export class Point { - static BASE = new Point(CURVE.Gx, CURVE.Gy); + static BASE = new Point(Gx, Gy); static ZERO = new Point(0n, 0n); static fromPrivateKey(privKey: Hex | bigint) { - return Point.BASE.multiply(normalizePrivKey(privKey)); + return G.multiply(normPriv(privKey)); } constructor(readonly x: bigint, readonly y: bigint) {} ok() { const { x, y } = this; - if (!isValidFE(x) || !isValidFE(y)) throw new Error(); - if (mod(mod(y * y) - weierstrass(x)) !== 0n) throw new Error(); + if (!fe(x) || !fe(y)) err(); + if (mod(mod(y * y) - weierstrass(x)) !== 0n) err(); return this; } equals(other: Point) { @@ -131,10 +132,10 @@ export class Point { return new Point(this.x, mod(-this.y)); } add(rhs: Point) { - return ProjP.fromAffine(this).add(ProjP.fromAffine(rhs)).aff(); + return Proj.frAff(this).add(Proj.frAff(rhs)).aff(); } multiply(n: bigint) { - return ProjP.fromAffine(this).mul(n).aff(); + return Proj.frAff(this).mul(n).aff(); } static fromHex(hex: Hex) { hex = ensureBytes(hex); @@ -143,7 +144,7 @@ export class Point { const tail = hex.subarray(1); const x = sliceNum(tail, 0, fLen); if (hex.length === 33 && [0x02, 0x03].includes(head)) { - if (!isValidFE(x)) throw new Error(); + if (!fe(x)) err(); let y = sqrt(weierstrass(x)); const isYOdd = (y & 1n) === 1n; const isFirstByteOdd = (head & 1) === 1; @@ -151,8 +152,8 @@ export class Point { p = new Point(x, y); } if (hex.length === 65 && head === 0x04) p = new Point(x, sliceNum(tail, fLen, 2 * fLen)); - if (!p) throw new Error(); - return p.ok(); + if (!p) err(); + return p!.ok(); } toHex(isCompressed = false) { const { x, y } = this; @@ -160,22 +161,20 @@ export class Point { return `${head}${numToFieldStr(x)}${isCompressed ? '' : numToFieldStr(y)}`; } toRawBytes(isCompressed = false) { - return hexToBytes(this.toHex(isCompressed)); + return h2b(this.toHex(isCompressed)); } } +const G = Point.BASE; -function mod(a: bigint, b: bigint = CURVE.P): bigint { - const result = a % b; - return result >= 0n ? result : b + result; -} +const mod = (a: bigint, b: bigint = P) => { + const r = a % b; + return r >= 0n ? r : b + r; +}; // Inverses number over modulo -function invert(number: bigint, md = CURVE.P): bigint { - if (number === 0n || md <= 0n) throw new Error(`invert: expected >0, got n=${number} mod=${md}`); - // Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/ - let a = mod(number, md); - let b = md; +const inv = (number: bigint, md = P): bigint => { + if (number === 0n || md <= 0n) throw new Error(`n=${number} mod=${md}`); // prettier-ignore - let x = 0n, y = 1n, u = 1n, v = 0n; + let a = mod(number, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { const q = b / a; const r = b % a; @@ -187,9 +186,9 @@ function invert(number: bigint, md = CURVE.P): bigint { const gcd = b; if (gcd !== 1n) throw new Error('invert: does not exist'); return mod(x, md); -} -function pow(num: bigint, power: bigint, md: bigint): bigint { - if (md <= 0n || power < 0n) throw new Error('Expected power/modulo > 0'); +}; +const pow = (num: bigint, power: bigint, md: bigint): bigint => { + if (md <= 0n || power < 0n) err(); if (md === 1n) return 0n; let res = 1n; while (power > 0n) { @@ -198,44 +197,44 @@ function pow(num: bigint, power: bigint, md: bigint): bigint { power >>= 1n; } return res; -} -function sqrt(num: bigint) { - return pow(num, (CURVE.P + 1n) / 4n, CURVE.P); -} +}; +const sqrt = (num: bigint) => { + return pow(num, (P + 1n) / 4n, P); +}; -function bytesToHex(uint8a: Uint8Array): string { - assertBytes(uint8a); +const b2h = (uint8a: Uint8Array): string => { + isBytes(uint8a); let hex = ''; for (let i = 0; i < uint8a.length; i++) hex += uint8a[i].toString(16).padStart(2, '0'); return hex; -} -function hexToNumber(hex: string): bigint { - if (typeof hex !== 'string') throw new Error(); +}; +const h2n = (hex: string): bigint => { + if (typeof hex !== 'string') err(); return BigInt(`0x${hex}`); -} -function hexToBytes(hex: string): Uint8Array { - if (typeof hex !== 'string') throw new Error(); - if (hex.length % 2) throw new Error(); +}; +const h2b = (hex: string): Uint8Array => { + if (typeof hex !== 'string') err(); + if (hex.length % 2) err(); const array = new Uint8Array(hex.length / 2); for (let i = 0; i < array.length; i++) { const j = i * 2; const hexByte = hex.slice(j, j + 2); const byte = Number.parseInt(hexByte, 16); - if (Number.isNaN(byte) || byte < 0) throw new Error(); + if (Number.isNaN(byte) || byte < 0) err(); array[i] = byte; } return array; -} -const bytesToNumber = (b: Uint8Array): bigint => hexToNumber(bytesToHex(b)); -const sliceNum = (b: Uint8Array, from: number, to: number) => bytesToNumber(b.slice(from, to)); -function numToField(num: bigint): Uint8Array { - if (typeof num !== 'bigint') throw new Error(); - if (!(0n <= num && num < B256)) throw new Error(); - return hexToBytes(num.toString(16).padStart(2 * fLen, '0')); -} -const numToFieldStr = (num: bigint): string => bytesToHex(numToField(num)); -function concatBytes(...arrays: Uint8Array[]): Uint8Array { - arrays.every((b) => assertBytes(b)); +}; +const b2n = (b: Uint8Array): bigint => h2n(b2h(b)); +const sliceNum = (b: Uint8Array, from: number, to: number) => b2n(b.slice(from, to)); +const numToField = (num: bigint): Uint8Array => { + if (typeof num !== 'bigint') err(); + if (!(0n <= num && num < B256)) err(); + return h2b(num.toString(16).padStart(2 * fLen, '0')); +}; +const numToFieldStr = (num: bigint): string => b2h(numToField(num)); +const concatBytes = (...arrays: Uint8Array[]): Uint8Array => { + arrays.every((b) => isBytes(b)); if (arrays.length === 1) return arrays[0]; const length = arrays.reduce((a, arr) => a + arr.length, 0); const result = new Uint8Array(length); @@ -245,33 +244,32 @@ function concatBytes(...arrays: Uint8Array[]): Uint8Array { pad += arr.length; } return result; -} +}; -function bits2int_2(bytes: Uint8Array) { +const bits2int_2 = (bytes: Uint8Array) => { const delta = bytes.length * 8 - 256; - const num = bytesToNumber(bytes); + const num = b2n(bytes); return delta > 0 ? num >> BigInt(delta) : num; -} -function truncateHash(hash: Uint8Array): bigint { +}; +const truncH = (hash: Uint8Array): bigint => { const h = bits2int_2(hash); - const { n } = CURVE; - return h >= n ? h - n : h; -} -function isBiggerThanHalfOrder(number: bigint) { - const half = CURVE.n >> 1n; - return number > half; -} + return h >= N ? h - N : h; +}; +const moreThanHalf = (n: bigint) => { + const h = N >> 1n; + return n > h; +}; -export function getPublicKey(privKey: Hex | bigint, isCompressed = false) { +export const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); -} +}; export class Signature { constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { - this.assertValidity(); + this.ok(); } - assertValidity(): Signature { - if (!isValidGE(this.r)) throw new Error(); - if (!isValidGE(this.s)) throw new Error(); + ok(): Signature { + if (!ge(this.r)) err(); + if (!ge(this.s)) err(); return this; } static fromCompact(hex: Hex) { @@ -279,25 +277,24 @@ export class Signature { return new Signature(sliceNum(hex, 0, fLen), sliceNum(hex, fLen, 2 * fLen)); } static fromKMD(kBytes: Uint8Array, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { - const { n } = CURVE; const k = bits2int_2(kBytes); - if (!isValidGE(k)) return; - const kinv = invert(k, n); - const q = Point.BASE.multiply(k); - const r = mod(q.x, n); + if (!ge(k)) return; + const kinv = inv(k, N); + const q = G.multiply(k); + const r = mod(q.x, N); if (r === 0n) return; - const s = mod(kinv * mod(m + mod(d * r, n), n), n); + const s = mod(kinv * mod(m + mod(d * r, N), N), N); if (s === 0n) return; let normS = s; let recovery = (q.x === r ? 0 : 2) | Number(q.y & 1n); - if (lowS && isBiggerThanHalfOrder(s)) { - normS = mod(-s, CURVE.n); + if (lowS && moreThanHalf(s)) { + normS = mod(-s, N); recovery ^= 1; } return new Signature(r, normS, recovery); } toCompactRawBytes() { - return hexToBytes(this.toCompactHex()); + return h2b(this.toCompactHex()); } toCompactHex() { return numToFieldStr(this.r) + numToFieldStr(this.s); @@ -305,47 +302,45 @@ export class Signature { } // RFC6979 methods -function bits2int(bytes: Uint8Array): bigint { - assertBytes(bytes); - const slice = bytes.length > fLen ? bytes.slice(0, fLen) : bytes; - return bytesToNumber(slice); -} -function bits2octets(bytes: Uint8Array): Uint8Array { - const z1 = bits2int(bytes); - const z2 = mod(z1, CURVE.n); - return int2octets(z2 < 0n ? z1 : z2); -} -function int2octets(num: bigint): Uint8Array { - return numToField(num); -} +const b2i = (b: Uint8Array): bigint => { + isBytes(b); + const sl = b.length > fLen ? b.slice(0, fLen) : b; + return b2n(sl); +}; +const b2o = (bytes: Uint8Array): Uint8Array => { + const z1 = b2i(bytes); + const z2 = mod(z1, N); + return i2o(z2 < 0n ? z1 : z2); +}; +const i2o = (num: bigint): Uint8Array => numToField(num); // Global symbol available in browsers only. Ensure we do not depend on @types/dom declare const self: Record | undefined; -const crypto: { node?: any; web?: any } = { +const cr: { node?: any; web?: any } = { node: typeof require === 'function' && require('crypto'), web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, }; async function hmac(key: Uint8Array, ...messages: Uint8Array[]): Promise { const msgs = concatBytes(...messages); - if (crypto.web) { + if (cr.web) { // prettier-ignore - const ckey = await crypto.web.subtle.importKey( + const ckey = await cr.web.subtle.importKey( 'raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign'] ); - return new Uint8Array(await crypto.web.subtle.sign('HMAC', ckey, msgs)); - } else if (crypto.node) { - return Uint8Array.from(crypto.node.createHmac('sha256', key).update(msgs).digest()); + return new Uint8Array(await cr.web.subtle.sign('HMAC', ckey, msgs)); + } else if (cr.node) { + return Uint8Array.from(cr.node.createHmac('sha256', key).update(msgs).digest()); } else { - throw new Error("The environment doesn't have hmac-sha256 function"); + throw new Error('crypto required'); } } function randomBytes(bytesLength: number): Uint8Array { - if (crypto.web) { - return crypto.web.getRandomValues(new Uint8Array(bytesLength)); - } else if (crypto.node) { - return Uint8Array.from(crypto.node.randomBytes(bytesLength)); + if (cr.web) { + return cr.web.getRandomValues(new Uint8Array(bytesLength)); + } else if (cr.node) { + return Uint8Array.from(cr.node.randomBytes(bytesLength)); } else { - throw new Error("The environment doesn't have randomBytes function"); + throw new Error('crypto required'); } } @@ -360,7 +355,7 @@ class HmacDrbg { this.k = new Uint8Array(fLen).fill(0); this.counter = 0; } - async reseed(seed = new Uint8Array()) { + async seed(seed = new Uint8Array()) { const hk = (...vs: Uint8Array[]) => hmac(this.k, ...vs); const hv = (...vs: Uint8Array[]) => hk(this.v, ...vs); this.k = await hv(Uint8Array.from([0x00]), seed); @@ -369,8 +364,8 @@ class HmacDrbg { this.k = await hv(Uint8Array.from([0x01]), seed); this.v = await hv(); } - async generate(): Promise { - if (this.counter >= 1000) throw new Error('Tried 1,000 k values for sign(), all were invalid'); + async gen(): Promise { + if (this.counter >= 1000) err(); this.counter += 1; this.v = await hmac(this.k, this.v); return this.v; @@ -378,19 +373,19 @@ class HmacDrbg { } export async function sign(msgHash: Hex, privKey: Hex, opts = stdOpts): Promise { - if (opts?.der === true) throw new Error(); - if (opts?.extraEntropy) throw new Error(); + if (opts?.der === true) err(); + if (opts?.extraEntropy) err(); if (opts?.lowS == null) opts.lowS = true; - const _h1 = numToField(truncateHash(ensureBytes(msgHash))); // Steps A, D of RFC6979 3.2. - const d = normalizePrivKey(privKey); - if (!isValidGE(d)) throw new Error(); - const seedArgs = [int2octets(d), bits2octets(_h1)]; + const _h1 = numToField(truncH(ensureBytes(msgHash))); // Steps A, D of RFC6979 3.2. + const d = normPriv(privKey); + if (!ge(d)) err(); + const seedArgs = [i2o(d), b2o(_h1)]; const seed = concatBytes(...seedArgs); - const m = bits2int(_h1); + const m = b2i(_h1); const drbg = new HmacDrbg(); // Steps B, C, D, E, F, G of RFC6979 3.2. - await drbg.reseed(seed); + await drbg.seed(seed); let sig: Signature | undefined; // Step H3, repeat until k is in range [1, n-1] - while (!(sig = Signature.fromKMD(await drbg.generate(), m, d, !!opts?.lowS))) await drbg.reseed(); + while (!(sig = Signature.fromKMD(await drbg.gen(), m, d, !!opts?.lowS))) await drbg.seed(); return sig; } @@ -399,14 +394,14 @@ export function verify(sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boo if (opts?.lowS == null) opts.lowS = true; let sig_: Signature; try { - sig_ = sig instanceof Signature ? sig.assertValidity() : Signature.fromCompact(sig); + sig_ = sig instanceof Signature ? sig.ok() : Signature.fromCompact(sig); } catch (error) { return false; } if (!sig_) return false; const { r, s } = sig_; - if (opts?.lowS && isBiggerThanHalfOrder(s)) return false; - const h = truncateHash(ensureBytes(msgHash, fLen)); + if (opts?.lowS && moreThanHalf(s)) return false; + const h = truncH(ensureBytes(msgHash, fLen)); let P: Point; try { @@ -414,37 +409,36 @@ export function verify(sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boo } catch (error) { return false; } - const { n } = CURVE; let R: Point | undefined = undefined; try { - const is = invert(s, n); // R = u1⋅G + u2⋅P - const u1 = mod(h * is, n); - const u2 = mod(r * is, n); - R = Point.BASE.multiply(u1).add(P.multiply(u2)); + const is = inv(s, N); // R = u1⋅G + u2⋅P + const u1 = mod(h * is, N); + const u2 = mod(r * is, N); + R = G.multiply(u1).add(P.multiply(u2)); } catch (error) { return false; } if (!R) return false; - const v = mod(R.x, n); + const v = mod(R.x, N); return v === r; } -export function getSharedSecret(privA: Hex, pubB: Hex, isCompressed?: boolean) { - return Point.fromHex(pubB).multiply(normalizePrivKey(privA)).toRawBytes(isCompressed); -} +export const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed?: boolean) => { + return Point.fromHex(pubB).multiply(normPriv(privA)).toRawBytes(isCompressed); +}; export const utils = { mod, - invert, + invert: inv, concatBytes, - hexToBytes, - bytesToHex, - bytesToNumber, + hexToBytes: h2b, + bytesToHex: b2h, + bytesToNumber: b2n, numToField, hashToPrivateKey: (hash: Hex): Uint8Array => { hash = ensureBytes(hash); const minLen = fLen + 8; - if (hash.length < minLen || hash.length > 1024) throw new Error(); - const num = mod(bytesToNumber(hash), CURVE.n - 1n) + 1n; + if (hash.length < minLen || hash.length > 1024) err(); + const num = mod(b2n(hash), N - 1n) + 1n; return numToField(num); }, randomBytes, @@ -452,7 +446,7 @@ export const utils = { randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(fLen + 8)), isValidPrivateKey: (key: Hex) => { try { - return !!normalizePrivKey(key); + return !!normPriv(key); } catch (e) { return false; } diff --git a/package.json b/package.json index da9798f..1d6179f 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "format": "prettier --print-width 100 --single-quote --write index.ts", "test": "jest", "coverage": "jest --coverage", - "bench": "node test/benchmark.js" + "bench": "node test/benchmark.js", + "min": "terser --ecma 2020 -m -c < lib/esm/index.js" }, "author": "Paul Miller (https://paulmillr.com)", "homepage": "https://paulmillr.com/noble/", From 01d014dabfdd5c4b5e765d86150df57ba2a1951a Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 14 Jan 2023 03:05:24 +0000 Subject: [PATCH 014/145] Add some comments. Iteration 4: 7071, 368LOC --- index.ts | 573 +++++++++++++++++++++----------------------------- package.json | 4 +- test/index.ts | 42 ++-- 3 files changed, 267 insertions(+), 352 deletions(-) diff --git a/index.ts b/index.ts index c518ec0..18bd26c 100644 --- a/index.ts +++ b/index.ts @@ -1,243 +1,182 @@ /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ -const B256 = 2n ** 256n; -const P = B256 - 2n ** 32n - 977n; -const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; -const a = 0n; -const b = 7n; -const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; -const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; +const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve +const P = B256 - 2n ** 32n - 977n; // curve's field +const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order +const a = 0n; // a equation's param +const b = 7n; // b equation's param +const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x +const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y export const CURVE = { P, n: N, a, b, Gx, Gy }; -const fLen = 32; // field/group byte length +const fLen = 32; // field/group byte length const stdOpts: { lowS?: boolean; der?: boolean; extraEntropy?: any } = { lowS: true }; -type Hex = Uint8Array | string; -const fe = (n: bigint) => typeof n === 'bigint' && 0n < n && n < P; -const ge = (n: bigint) => typeof n === 'bigint' && 0n < n && n < N; -const weierstrass = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); -const err = (): never => { - throw new TypeError(); -}; -const isBytes = (a: any, len?: number): Uint8Array => { - if (!(a instanceof Uint8Array)) err(); - if (typeof len === 'number' && len > 0 && a.length !== len) err(); +type Hex = Uint8Array | string; // accepted: bytes/hex +const bg = (n: any): n is bigint => typeof n === 'bigint'; // is big integer +const str = (s: any): s is string => typeof s === 'string'; +const u8a = (content?: any) => new Uint8Array(content) // creates Uint8Array byte arrays +const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut +const fe = (n: bigint) => bg(n) && 0n < n && n < P; // is field element +const ge = (n: bigint) => bg(n) && 0n < n && n < N; // is group element +const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula +const err = (m = ''): never => { throw new Error(m); }; // throws error +const isBytes = (a: any, len?: number): Uint8Array => { // asserts Uint8Array + if (!(a instanceof Uint8Array) || (typeof len === 'number' && len > 0 && a.length !== len)) err(); return a; }; -const ensureBytes = (a: any, len?: number) => isBytes(typeof a === 'string' ? h2b(a) : a, len); -const normPriv = (privKey: Hex | bigint) => { - if (typeof privKey !== 'bigint') privKey = b2n(ensureBytes(privKey, fLen)); - if (!ge(privKey)) err(); - return privKey; -}; -const isProj = (p: any) => { - if (!(p instanceof Proj)) err(); +const ensureBytes = (a: any, len?: number) => isBytes(str(a) ? h2b(a) : a, len); +const normPriv = (p: Hex | bigint): bigint => { // normalize private key + if (!bg(p)) p = b2n(ensureBytes(p, fLen)); // convert to bigint when bytes + if (!ge(p)) err(); // check if bigint is in range + return p; }; -class Proj { - static readonly G = new Proj(Gx, Gy, 1n); - static readonly I = new Proj(0n, 1n, 0n); - static frAff(p: Point) { - if (!(p instanceof Point)) err(); - return new Proj(p.x, p.y, 1n); - } - constructor(readonly x: bigint, readonly y: bigint, readonly z: bigint) {} - eql(other: Proj): boolean { - isProj(other); +const isPoint = (p: any) => (p instanceof Point ? p : err()); // is projective point +export class Point { // Point in 3d xyz projective coords + static readonly G = new Point(Gx, Gy, 1n); // generator / base point + static readonly I = new Point(0n, 1n, 0n); // identity / zero point + constructor(readonly x: bigint, readonly y: bigint, readonly z = 1n) {} // z is optional + eql(other: Point): boolean { // equality check const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = other; + const { x: X2, y: Y2, z: Z2 } = isPoint(other); // isPoint() checks class equality return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); } - dbl() { - return this.add(this); - } - add(other: Proj) { - isProj(other); - const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = other; - let X3 = 0n, Y3 = 0n, Z3 = 0n; // prettier-ignore - const { a, b } = CURVE; + neg() { return new Point(this.x, mod(-this.y), this.z); } // creates negative version of the point + dbl() { return this.add(this); } // point doubling + add(other: Point) { // addition, exception-free formula + const { x: X1, y: Y1, z: Z1 } = this; // from Renes-Costello-Batina + const { x: X2, y: Y2, z: Z2 } = isPoint(other); + let X3 = 0n, Y3 = 0n, Z3 = 0n; const b3 = mod(b * 3n); - let t0 = mod(X1 * X2); // step 1 - let t1 = mod(Y1 * Y2); - let t2 = mod(Z1 * Z2); - let t3 = mod(X1 + Y1); - let t4 = mod(X2 + Y2); // step 5 - t3 = mod(t3 * t4); - t4 = mod(t0 + t1); - t3 = mod(t3 - t4); - t4 = mod(X1 + Z1); - let t5 = mod(X2 + Z2); // step 10 - t4 = mod(t4 * t5); - t5 = mod(t0 + t2); - t4 = mod(t4 - t5); - t5 = mod(Y1 + Z1); - X3 = mod(Y2 + Z2); // step 15 - t5 = mod(t5 * X3); - X3 = mod(t1 + t2); - t5 = mod(t5 - X3); - Z3 = mod(a * t4); - X3 = mod(b3 * t2); // step 20 - Z3 = mod(X3 + Z3); - X3 = mod(t1 - Z3); - Z3 = mod(t1 + Z3); - Y3 = mod(X3 * Z3); - t1 = mod(t0 + t0); // step 25 - t1 = mod(t1 + t0); - t2 = mod(a * t2); - t4 = mod(b3 * t4); - t1 = mod(t1 + t2); - t2 = mod(t0 - t2); // step 30 - t2 = mod(a * t2); - t4 = mod(t4 + t2); - t0 = mod(t1 * t4); - Y3 = mod(Y3 + t0); - t0 = mod(t5 * t4); // step 35 - X3 = mod(t3 * X3); - X3 = mod(X3 - t0); - t0 = mod(t3 * t1); - Z3 = mod(t5 * Z3); - Z3 = mod(Z3 + t0); // step 40 - return new Proj(X3, Y3, Z3); - } - mul(n: bigint) { - if (!ge(n)) err(); - let p = Proj.I; - for (let d: Proj = this; n > 0n; d = d.dbl(), n >>= 1n) { - if (n & 1n) p = p.add(d); + let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); // step 1 + let t4 = mod(X2 + Y2); // step 5 + t3 = mod(t3 * t4); t4 = mod(t0 + t1); t3 = mod(t3 - t4); t4 = mod(X1 + Z1); + let t5 = mod(X2 + Z2); // step 10 + t4 = mod(t4 * t5); t5 = mod(t0 + t2); t4 = mod(t4 - t5); t5 = mod(Y1 + Z1); + X3 = mod(Y2 + Z2); // step 15 + t5 = mod(t5 * X3); X3 = mod(t1 + t2); t5 = mod(t5 - X3); Z3 = mod(a * t4); + X3 = mod(b3 * t2); // step 20 + Z3 = mod(X3 + Z3); X3 = mod(t1 - Z3); Z3 = mod(t1 + Z3); Y3 = mod(X3 * Z3); + t1 = mod(t0 + t0); // step 25 + t1 = mod(t1 + t0); t2 = mod(a * t2); t4 = mod(b3 * t4); t1 = mod(t1 + t2); + t2 = mod(t0 - t2); // step 30 + t2 = mod(a * t2); t4 = mod(t4 + t2); t0 = mod(t1 * t4); Y3 = mod(Y3 + t0); + t0 = mod(t5 * t4); // step 35 + X3 = mod(t3 * X3); X3 = mod(X3 - t0); t0 = mod(t3 * t1); Z3 = mod(t5 * Z3); + Z3 = mod(Z3 + t0); // step 40 + return new Point(X3, Y3, Z3); + } + mul(n: bigint) { // multiplies point by scalar n + if (!ge(n)) err(); // n must be 0 < n < CURVE.n + let p = Point.I; let f = Point.G // init identity / zero point & fake point + for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder + if (n & 1n) p = p.add(d); else; f = f.add(d); // add to fake point when bit is not present } return p; } - aff() { + aff(): { x: bigint; y: bigint } { // converts point to 2d xy affine point const { x, y, z } = this; - if (this.eql(Proj.I)) return Point.ZERO; - const iz = inv(this.z); - if (mod(z * iz) !== 1n) err(); - return new Point(mod(x * iz), mod(y * iz)); - } -} -export class Point { - static BASE = new Point(Gx, Gy); - static ZERO = new Point(0n, 0n); - static fromPrivateKey(privKey: Hex | bigint) { - return G.multiply(normPriv(privKey)); - } - constructor(readonly x: bigint, readonly y: bigint) {} - ok() { - const { x, y } = this; - if (!fe(x) || !fe(y)) err(); - if (mod(mod(y * y) - weierstrass(x)) !== 0n) err(); + if (this.eql(Point.I)) return { x: 0n, y: 0n }; // fast-path for zero point + if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is + const iz = inv(z); // z^-1: invert z + if (mod(z * iz) !== 1n) err(); // (z * z^-1) must be 1, otherwise bad math + return { x: mod(x * iz), y: mod(y * iz) }; // x = x*z^-1; y = y*z^-1 + } + ok(): Point { // checks if the point is valid and on-curve + const { x, y } = this.aff(); // convert to 2d xy affine point + if (!fe(x) || !fe(y)) err(); // x and y must be in range 0 < n < P + const l = mod(y * y); // y² + const r = crv(x); // x³ + ax + b + if (mod(l - r) !== 0n) err(); // y² = x³ + ax + b, must be equal return this; } - equals(other: Point) { - return this.x === other.x && this.y === other.y; - } - negate() { - return new Point(this.x, mod(-this.y)); - } - add(rhs: Point) { - return Proj.frAff(this).add(Proj.frAff(rhs)).aff(); - } - multiply(n: bigint) { - return Proj.frAff(this).mul(n).aff(); - } - static fromHex(hex: Hex) { - hex = ensureBytes(hex); + static fromHex(hex: Hex): Point { // convert Uint8Array or hex string to Point + hex = ensureBytes(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; - const head = hex[0]; - const tail = hex.subarray(1); - const x = sliceNum(tail, 0, fLen); - if (hex.length === 33 && [0x02, 0x03].includes(head)) { - if (!fe(x)) err(); - let y = sqrt(weierstrass(x)); - const isYOdd = (y & 1n) === 1n; - const isFirstByteOdd = (head & 1) === 1; - if (isFirstByteOdd !== isYOdd) y = mod(-y); - p = new Point(x, y); - } - if (hex.length === 65 && head === 0x04) p = new Point(x, sliceNum(tail, fLen, 2 * fLen)); - if (!p) err(); - return p!.ok(); - } - toHex(isCompressed = false) { - const { x, y } = this; - const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; - return `${head}${numToFieldStr(x)}${isCompressed ? '' : numToFieldStr(y)}`; - } - toRawBytes(isCompressed = false) { - return h2b(this.toHex(isCompressed)); + const head = hex[0]; // first byte serves as prefix + const tail = hex.subarray(1); // the actual data + const x = sliceNum(tail, 0, fLen); // next 32 bytes are x coordinate + if (hex.length === 33 && [2, 3].includes(head)) { // compressed points are 33 bytes & start + if (!fe(x)) err(); // with byte 0x02 or 0x03. Check if 0 { - const r = a % b; - return r >= 0n ? r : b + r; -}; -// Inverses number over modulo -const inv = (number: bigint, md = P): bigint => { - if (number === 0n || md <= 0n) throw new Error(`n=${number} mod=${md}`); - // prettier-ignore +const G = Point.G; // Generator point +const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division +const inv = (number: bigint, md = P): bigint => { // modular inversion, euclidean gcd algo + if (number === 0n || md <= 0n) err(`n=${number} mod=${md}`); // can be invalid let a = mod(number, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { const q = b / a; const r = b % a; const m = x - u * q; const n = y - v * q; - // prettier-ignore b = a, a = r, x = u, y = v, u = m, v = n; } - const gcd = b; - if (gcd !== 1n) throw new Error('invert: does not exist'); + if (b !== 1n) err('invert: does not exist'); // b is gcd at this point return mod(x, md); }; -const pow = (num: bigint, power: bigint, md: bigint): bigint => { - if (md <= 0n || power < 0n) err(); - if (md === 1n) return 0n; - let res = 1n; - while (power > 0n) { - if (power & 1n) res = (res * num) % md; +const pow = (num: bigint, p: bigint, md: bigint): bigint => { // modular exponentiation num^p + if (md <= 0n || p < 0n) err(); // exponentiation by squaring + if (md === 1n) return 0n; // the ladder can leak exponent bits + let res = 1n; // and is vulnerable to timing attacks + for (; p > 0n; p >>= 1n) { + if (p & 1n) res = (res * num) % md; num = (num * num) % md; - power >>= 1n; } return res; }; -const sqrt = (num: bigint) => { - return pow(num, (P + 1n) / 4n, P); -}; - -const b2h = (uint8a: Uint8Array): string => { - isBytes(uint8a); - let hex = ''; +const sqrt = (n: bigint) => { // √(y) = y^((p+1)/4) for fields P = 3 mod 4 + const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square + return mod(r * r) === n ? r : err(); // Roots from 1;24,51,10 to Dan Shanks" +} +const b2h = (uint8a: Uint8Array): string => { // bytes to hex string. Every uint8array + isBytes(uint8a); // item is number [0, 255] + let hex = ''; // convert number to hex string & pad with 0 for (let i = 0; i < uint8a.length; i++) hex += uint8a[i].toString(16).padStart(2, '0'); - return hex; -}; -const h2n = (hex: string): bigint => { - if (typeof hex !== 'string') err(); - return BigInt(`0x${hex}`); -}; -const h2b = (hex: string): Uint8Array => { - if (typeof hex !== 'string') err(); - if (hex.length % 2) err(); - const array = new Uint8Array(hex.length / 2); + return hex; // byte 2 will become 02, etc +}; // hex to number +const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); +const h2b = (hex: string): Uint8Array => { // hex to bytes. error if not string, + if (!str(hex) || hex.length % 2) err(); // or has odd length like 3, 5 + const array = u8a(hex.length / 2); // create result array for (let i = 0; i < array.length; i++) { const j = i * 2; - const hexByte = hex.slice(j, j + 2); - const byte = Number.parseInt(hexByte, 16); - if (Number.isNaN(byte) || byte < 0) err(); + const hexByte = hex.slice(j, j + 2); // substr seems slower + const byte = Number.parseInt(hexByte, 16); // parse every string part, convert to + if (Number.isNaN(byte) || byte < 0) err(); // Number. Error if NaN or < 0 array[i] = byte; } return array; }; -const b2n = (b: Uint8Array): bigint => h2n(b2h(b)); -const sliceNum = (b: Uint8Array, from: number, to: number) => b2n(b.slice(from, to)); -const numToField = (num: bigint): Uint8Array => { - if (typeof num !== 'bigint') err(); - if (!(0n <= num && num < B256)) err(); +const b2n = (b: Uint8Array): bigint => h2n(b2h(b)); // bytes to number +const sliceNum = (b: Uint8Array, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes +const n2b = (num: bigint): Uint8Array => { // number to bytes + if (!bg(num) || num < 0n || num >= B256) err(); // must be 0 <= num < B256 return h2b(num.toString(16).padStart(2 * fLen, '0')); }; -const numToFieldStr = (num: bigint): string => b2h(numToField(num)); -const concatBytes = (...arrays: Uint8Array[]): Uint8Array => { +const numToFieldStr = (num: bigint): string => b2h(n2b(num)); +const catBytes = (...arrays: Uint8Array[]) => { // concatenate Uint8Array-s arrays.every((b) => isBytes(b)); if (arrays.length === 1) return arrays[0]; const length = arrays.reduce((a, arr) => a + arr.length, 0); - const result = new Uint8Array(length); + const result = u8a(length); for (let i = 0, pad = 0; i < arrays.length; i++) { const arr = arrays[i]; result.set(arr, pad); @@ -246,205 +185,179 @@ const concatBytes = (...arrays: Uint8Array[]): Uint8Array => { return result; }; -const bits2int_2 = (bytes: Uint8Array) => { - const delta = bytes.length * 8 - 256; +const bits2int_2 = (bytes: Uint8Array) => { // bytes to bigint + const delta = bytes.length * 8 - 256; // truncates bits const num = b2n(bytes); return delta > 0 ? num >> BigInt(delta) : num; }; -const truncH = (hash: Uint8Array): bigint => { +const truncH = (hash: Uint8Array): bigint => { // truncate hash const h = bits2int_2(hash); return h >= N ? h - N : h; }; -const moreThanHalf = (n: bigint) => { +const moreThanHalf = (n: bigint) => { // if a number is bigger than CURVE.n/2 const h = N >> 1n; return n > h; }; -export const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { - return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); +export const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { // calculate public + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; -export class Signature { - constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { +export class Signature { // calculates signature + constructor(readonly r: bigint, readonly s: bigint, readonly rec?: number) { this.ok(); } - ok(): Signature { - if (!ge(this.r)) err(); - if (!ge(this.s)) err(); + ok(): Signature { // validates signature + if (!ge(this.r)) err(); // 0 < r < CURVE.n + if (!ge(this.s)) err(); // 0 < s < CURVE.n return this; } - static fromCompact(hex: Hex) { - hex = ensureBytes(hex, 64); + static fromCompact(hex: Hex) { // create signature from 64b compact repr + hex = ensureBytes(hex, 64); // compact repr is (32-byte r)+(32-byte s) return new Signature(sliceNum(hex, 0, fLen), sliceNum(hex, fLen, 2 * fLen)); } static fromKMD(kBytes: Uint8Array, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { - const k = bits2int_2(kBytes); - if (!ge(k)) return; - const kinv = inv(k, N); - const q = G.multiply(k); - const r = mod(q.x, N); - if (r === 0n) return; - const s = mod(kinv * mod(m + mod(d * r, N), N), N); - if (s === 0n) return; - let normS = s; - let recovery = (q.x === r ? 0 : 2) | Number(q.y & 1n); - if (lowS && moreThanHalf(s)) { - normS = mod(-s, N); - recovery ^= 1; + const k = bits2int_2(kBytes); // Utility method for RFC6979 k generation + if (!ge(k)) return; // Check 0 < k < CURVE.n + const ik = inv(k, N); // k^-1 over CURVE.n, NOT CURVE.P + const q = G.mul(k).aff(); // q = Gk + const r = mod(q.x, N); // r = q.x mod CURVE.n + if (r === 0n) return; // invalid + const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1 * m + dr mod CURVE.n + if (s === 0n) return; // invalid + let normS = s; // normalized s + let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit + if (lowS && moreThanHalf(s)) { // if option lowS was passed, + normS = mod(-s, N); // ensure s is always in the bottom half + rec ^= 1; // of CURVE.n } - return new Signature(r, normS, recovery); - } - toCompactRawBytes() { - return h2b(this.toCompactHex()); - } - toCompactHex() { - return numToFieldStr(this.r) + numToFieldStr(this.s); + return new Signature(r, normS, rec); } + toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr + toCompactHex() { return numToFieldStr(this.r) + numToFieldStr(this.s); } // hex 64b compact repr } - -// RFC6979 methods -const b2i = (b: Uint8Array): bigint => { +const b2i = (b: Uint8Array): bigint => { // RFC6979 methods: bytes to int isBytes(b); - const sl = b.length > fLen ? b.slice(0, fLen) : b; - return b2n(sl); + const sl = b.length > fLen ? b.slice(0, fLen) : b; // slice + return b2n(sl); // call our own method }; -const b2o = (bytes: Uint8Array): Uint8Array => { +const b2o = (bytes: Uint8Array): Uint8Array => { // bits to octets const z1 = b2i(bytes); const z2 = mod(z1, N); return i2o(z2 < 0n ? z1 : z2); }; -const i2o = (num: bigint): Uint8Array => numToField(num); - -// Global symbol available in browsers only. Ensure we do not depend on @types/dom -declare const self: Record | undefined; -const cr: { node?: any; web?: any } = { - node: typeof require === 'function' && require('crypto'), - web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, +const i2o = (num: bigint): Uint8Array => n2b(num); // int to octets +declare const self: Record | undefined; // Typescript global symbol available in +const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependence on @types/dom + node: typeof require === 'function' && require('crypto'), // node.js require('crypto') + web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, // browser-only var }; -async function hmac(key: Uint8Array, ...messages: Uint8Array[]): Promise { - const msgs = concatBytes(...messages); - if (cr.web) { +const hmac = async (key: Uint8Array, ...messages: Uint8Array[]): Promise => { + const msgs = catBytes(...messages); // HMAC-SHA256 + if (cr.web) { // browser built-in version // prettier-ignore const ckey = await cr.web.subtle.importKey( 'raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign'] ); - return new Uint8Array(await cr.web.subtle.sign('HMAC', ckey, msgs)); - } else if (cr.node) { - return Uint8Array.from(cr.node.createHmac('sha256', key).update(msgs).digest()); + return u8a(await cr.web.subtle.sign('HMAC', ckey, msgs)); + } else if (cr.node) { // node.js built-in version + return u8fr(cr.node.createHmac('sha256', key).update(msgs).digest()); } else { throw new Error('crypto required'); } -} -function randomBytes(bytesLength: number): Uint8Array { - if (cr.web) { - return cr.web.getRandomValues(new Uint8Array(bytesLength)); - } else if (cr.node) { - return Uint8Array.from(cr.node.randomBytes(bytesLength)); +}; +const randomBytes = (bytesLength: number): Uint8Array => { // CSPRNG: secure generator + if (cr.web) { // browser built-in version + return cr.web.getRandomValues(u8a(bytesLength)); + } else if (cr.node) { // node.js built-in version + return u8fr(cr.node.randomBytes(bytesLength)); } else { - throw new Error('crypto required'); + throw new Error('crypto required'); // error when no CSPRNG } -} - -// Minimal HMAC-DRBG (NIST 800-90) used only for RFC6979 signatures -class HmacDrbg { - k: Uint8Array; +}; +class HmacDrbg { // Minimal HMAC-DRBG (NIST 800-90) + k: Uint8Array; // used only for RFC6979 signatures. v: Uint8Array; counter: number; - constructor() { - // Step B, Step C: set hashLen to 8*ceil(hlen/8) - this.v = new Uint8Array(fLen).fill(1); - this.k = new Uint8Array(fLen).fill(0); + constructor() { // Step B, Step C: set hashLen + this.v = u8a(fLen).fill(1); // to 8*ceil(hlen/8) + this.k = u8a(fLen).fill(0); this.counter = 0; } - async seed(seed = new Uint8Array()) { - const hk = (...vs: Uint8Array[]) => hmac(this.k, ...vs); - const hv = (...vs: Uint8Array[]) => hk(this.v, ...vs); - this.k = await hv(Uint8Array.from([0x00]), seed); + async seed(seed = u8a()) { // DRBG reseed() function + const hk = (...vs: Uint8Array[]) => hmac(this.k, ...vs); // hmac(k)(...values) + const hv = (...vs: Uint8Array[]) => hk(this.v, ...vs); // hmac(k)(v, ...values) + this.k = await hv(u8fr([0x00]), seed); this.v = await hv(); if (seed.length === 0) return; - this.k = await hv(Uint8Array.from([0x01]), seed); + this.k = await hv(u8fr([0x01]), seed); this.v = await hv(); } - async gen(): Promise { - if (this.counter >= 1000) err(); + async gen(): Promise { // DRBG generate() function + if (this.counter >= 1000) err(); // Something is wrong if counter is 1k this.counter += 1; this.v = await hmac(this.k, this.v); return this.v; } } - -export async function sign(msgHash: Hex, privKey: Hex, opts = stdOpts): Promise { - if (opts?.der === true) err(); - if (opts?.extraEntropy) err(); - if (opts?.lowS == null) opts.lowS = true; - const _h1 = numToField(truncH(ensureBytes(msgHash))); // Steps A, D of RFC6979 3.2. - const d = normPriv(privKey); - if (!ge(d)) err(); - const seedArgs = [i2o(d), b2o(_h1)]; - const seed = concatBytes(...seedArgs); - const m = b2i(_h1); - const drbg = new HmacDrbg(); // Steps B, C, D, E, F, G of RFC6979 3.2. - await drbg.seed(seed); - let sig: Signature | undefined; // Step H3, repeat until k is in range [1, n-1] +export const sign = async (msgHash: Hex, privKey: Hex, opts = stdOpts): Promise => { + if (opts?.der === true) err(); // RFC6979 ECDSA signature generation + if (opts?.extraEntropy) err(); // extraEntropy is not supported + if (opts?.lowS == null) opts.lowS = true; // generates low-s sigs by default + const _h1 = n2b(truncH(ensureBytes(msgHash))); // Steps A, D of RFC6979 3.2. + const d = normPriv(privKey); // d = normalize(privatekey) + if (!ge(d)) err(); // redundant check + const seedArgs = [i2o(d), b2o(_h1)]; // seed args for drbg + const seed = catBytes(...seedArgs); + const m = b2i(_h1); // convert msg to bigint + const drbg = new HmacDrbg(); // Steps B,C,D,E,F,G of RFC6979 3.2. + await drbg.seed(seed); // Reseed DRBG. Then Step H3: + let sig: Signature | undefined; // reseed until k is in range [1, n-1] while (!(sig = Signature.fromKMD(await drbg.gen(), m, d, !!opts?.lowS))) await drbg.seed(); return sig; } -type Sig = Hex | Signature; -export function verify(sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boolean { - if (opts?.lowS == null) opts.lowS = true; - let sig_: Signature; - try { +type Sig = Hex | Signature; // signature verification +export const verify = (sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boolean => { + if (opts?.lowS == null) opts.lowS = true; // lowS=true default + let sig_: Signature; // Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf + try { // verify(r, s, h, P) where u1 = hs^-1 mod n, u2 = rs^-1 mod n, sig_ = sig instanceof Signature ? sig.ok() : Signature.fromCompact(sig); - } catch (error) { - return false; - } + } catch (error) { return false; } // R = U1⋅G - U2⋅P, mod(R.x, n) == r if (!sig_) return false; const { r, s } = sig_; - if (opts?.lowS && moreThanHalf(s)) return false; - const h = truncH(ensureBytes(msgHash, fLen)); - + if (opts?.lowS && moreThanHalf(s)) return false; // lowS=true bans sig.s >= CURVE.n/2 + const h = truncH(ensureBytes(msgHash, fLen)); // truncate hash let P: Point; - try { + try { // Validate public key P = pubKey instanceof Point ? pubKey.ok() : Point.fromHex(pubKey); - } catch (error) { - return false; - } - let R: Point | undefined = undefined; + } catch (error) { return false; } + let R: { x: bigint; y: bigint } | undefined = undefined; try { - const is = inv(s, N); // R = u1⋅G + u2⋅P - const u1 = mod(h * is, N); - const u2 = mod(r * is, N); - R = G.multiply(u1).add(P.multiply(u2)); - } catch (error) { - return false; - } - if (!R) return false; + const is = inv(s, N); // s^-1 + const u1 = mod(h * is, N); // u1 = hs^-1 mod n + const u2 = mod(r * is, N); // u2 = rs^-1 mod n + R = G.mul(u1).add(P.mul(u2))?.aff(); // R = u1⋅G + u2⋅P + } catch (error) { return false; } + if (!R || R.x === 0n || R.y === 0n) return false; // stop if R is identity / zero point const v = mod(R.x, N); - return v === r; + return v === r; // mod(R.x, n) == r } export const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed?: boolean) => { - return Point.fromHex(pubB).multiply(normPriv(privA)).toRawBytes(isCompressed); + return Point.fromHex(pubB).mul(normPriv(privA)).toRawBytes(isCompressed); }; - -export const utils = { - mod, - invert: inv, - concatBytes, - hexToBytes: h2b, - bytesToHex: b2h, - bytesToNumber: b2n, - numToField, - hashToPrivateKey: (hash: Hex): Uint8Array => { - hash = ensureBytes(hash); - const minLen = fLen + 8; - if (hash.length < minLen || hash.length > 1024) err(); - const num = mod(b2n(hash), N - 1n) + 1n; - return numToField(num); - }, - randomBytes, - // FIPS 186 B.4.1. - randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(fLen + 8)), - isValidPrivateKey: (key: Hex) => { +const hashToPrivateKey = (hash: Hex): Uint8Array => { // FIPS 186 B.4.1 compliant key generation + hash = ensureBytes(hash); // produces private keys with modulo bias + const minLen = fLen + 8; // being neglible. + if (hash.length < minLen || hash.length > 1024) err(); + const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes + return n2b(num); +}; +export const utils = { // utilities + mod, invert: inv, // math utilities + concatBytes: catBytes, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, + hashToPrivateKey, randomBytes, // CSPRNG etc. + randomPrivateKey: (): Uint8Array => hashToPrivateKey(randomBytes(fLen + 8)), // FIPS 186 B.4.1. + isValidPrivateKey: (key: Hex) => { // checks if private key is valid try { return !!normPriv(key); } catch (e) { diff --git a/package.json b/package.json index 1d6179f..c611e0d 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "scripts": { "build": "tsc && tsc -p tsconfig.esm.json", "build:release": "rollup -c rollup.config.js", - "lint": "prettier --print-width 100 --single-quote --check index.ts", - "format": "prettier --print-width 100 --single-quote --write index.ts", + "lint": "prettier --print-width 100 --single-quote --check test/index.ts", + "format": "prettier --print-width 100 --single-quote --write test/index.ts", "test": "jest", "coverage": "jest --coverage", "bench": "node test/benchmark.js", diff --git a/test/index.ts b/test/index.ts index 0433537..0505308 100644 --- a/test/index.ts +++ b/test/index.ts @@ -39,17 +39,19 @@ describe('secp256k1', () => { .filter((line) => line) .map((line) => line.split(':')); for (let [priv, x, y] of data) { - const point = secp.Point.fromPrivateKey(BigInt(priv)); - expect(toBEHex(point.x)).toBe(x); - expect(toBEHex(point.y)).toBe(y); - - const point2 = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))); - expect(toBEHex(point2.x)).toBe(x); - expect(toBEHex(point2.y)).toBe(y); - - const point3 = secp.Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv))))); - expect(toBEHex(point3.x)).toBe(x); - expect(toBEHex(point3.y)).toBe(y); + const { x: x1, y: y1 } = secp.Point.fromPrivateKey(BigInt(priv)).aff(); + expect(toBEHex(x1)).toBe(x); + expect(toBEHex(y1)).toBe(y); + + const { x: x2, y: y2 } = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))).aff(); + expect(toBEHex(x2)).toBe(x); + expect(toBEHex(y2)).toBe(y); + + const { x: x3, y: y3 } = secp.Point.fromHex( + secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv)))) + ).aff(); + expect(toBEHex(x3)).toBe(x); + expect(toBEHex(y3)).toBe(y); } }); it('.getPublicKey() rejects invalid keys', () => { @@ -123,8 +125,8 @@ describe('secp256k1', () => { if (expected) { expect(p.add(q).toHex(true)).toBe(expected); } else { - if (p.equals(q.negate())) { - expect(p.add(q).toHex(true)).toBe(secp.Point.ZERO.toHex(true)); + if (p.eql(q.neg())) { + expect(p.add(q).toHex(true)).toBe(secp.Point.I.toHex(true)); } else { expect(() => p.add(q).toHex(true)).toThrowError(); } @@ -137,10 +139,10 @@ describe('secp256k1', () => { const { P, d, expected } = vector; const p = secp.Point.fromHex(P); if (expected) { - expect(p.multiply(hexToNumber(d)).toHex(true)).toBe(expected); + expect(p.mul(hexToNumber(d)).toHex(true)).toBe(expected); } else { expect(() => { - p.multiply(hexToNumber(d)).toHex(true); + p.mul(hexToNumber(d)).toHex(true); }).toThrowError(); } } @@ -150,7 +152,7 @@ describe('secp256k1', () => { if (hexToNumber(d) < secp.CURVE.n) { expect(() => { const p = secp.Point.fromHex(P); - p.multiply(hexToNumber(d)).toHex(true); + p.mul(hexToNumber(d)).toHex(true); }).toThrowError(); } } @@ -490,9 +492,9 @@ describe('secp256k1', () => { pointAddScalar: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { const P = secp.Point.fromHex(p); const t = normal(tweak); - const Q = P.add(secp.Point.BASE.multiply(t)); + const Q = P.add(secp.Point.G.mul(t)); // const Q = secp.Point.BASE.multiplyAndAddUnsafe(P, t, 1n); - if (!Q || Q.equals(secp.Point.ZERO)) throw new Error('Tweaked point at infinity'); + if (!Q || Q.eql(secp.Point.I)) throw new Error('Tweaked point at infinity'); return Q.toRawBytes(isCompressed); }, @@ -500,12 +502,12 @@ describe('secp256k1', () => { const P = secp.Point.fromHex(p); const h = typeof tweak === 'string' ? tweak : secp.utils.bytesToHex(tweak); const t = BigInt(`0x${h}`); - return P.multiply(t).toRawBytes(isCompressed); + return P.mul(t).toRawBytes(isCompressed); }, }; it('privateAdd()', () => { - // @ts-ignore + // @ts-ignore for (const vector of privates.valid.add) { const { a, b, expected } = vector; expect(secp.utils.bytesToHex(tweakUtils.privateAdd(a, b))).toBe(expected); From db19abb913d884786d9249b8afb31b198c34c1c3 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 14 Jan 2023 16:35:46 +0000 Subject: [PATCH 015/145] Benchmark. Iteration 5: 6953, 350LOC --- index.ts | 268 +++++++++++++++++++++------------------------- test/benchmark.js | 70 ++---------- 2 files changed, 132 insertions(+), 206 deletions(-) diff --git a/index.ts b/index.ts index 18bd26c..218a05b 100644 --- a/index.ts +++ b/index.ts @@ -6,30 +6,29 @@ const a = 0n; // a equation's param const b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = { P, n: N, a, b, Gx, Gy }; +const CURVE = { P, n: N, a, b, Gx, Gy }; const fLen = 32; // field/group byte length -const stdOpts: { lowS?: boolean; der?: boolean; extraEntropy?: any } = { lowS: true }; -type Hex = Uint8Array | string; // accepted: bytes/hex -const bg = (n: any): n is bigint => typeof n === 'bigint'; // is big integer -const str = (s: any): s is string => typeof s === 'string'; -const u8a = (content?: any) => new Uint8Array(content) // creates Uint8Array byte arrays +const stdo: { lowS?: boolean; der?: boolean; extraEntropy?: any; recovered?: any } = { lowS: true }; +type Bytes = Uint8Array; type Hex = Bytes | string; // accepted: bytes/hex +const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer +const str = (s: any): s is string => typeof s === 'string'; // is string +const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element +const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element +const u8a = (content?: any) => new Uint8Array(content); // creates Uint8Array byte arrays const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut -const fe = (n: bigint) => bg(n) && 0n < n && n < P; // is field element -const ge = (n: bigint) => bg(n) && 0n < n && n < N; // is group element const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula const err = (m = ''): never => { throw new Error(m); }; // throws error -const isBytes = (a: any, len?: number): Uint8Array => { // asserts Uint8Array +const isU8 = (a: any, len?: number): Bytes => { // is Uint8Array (of specific length) if (!(a instanceof Uint8Array) || (typeof len === 'number' && len > 0 && a.length !== len)) err(); return a; }; -const ensureBytes = (a: any, len?: number) => isBytes(str(a) ? h2b(a) : a, len); -const normPriv = (p: Hex | bigint): bigint => { // normalize private key - if (!bg(p)) p = b2n(ensureBytes(p, fLen)); // convert to bigint when bytes - if (!ge(p)) err(); // check if bigint is in range - return p; +const toU8 = (a: any, len?: number) => isU8(str(a) ? h2b(a) : a, len); +const toPriv = (p: Hex | bigint): bigint => { // normalize private key + if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes + return ge(p) ? p : err(); // check if bigint is in range }; -const isPoint = (p: any) => (p instanceof Point ? p : err()); // is projective point -export class Point { // Point in 3d xyz projective coords +const isPoint = (p: any) => (p instanceof Point ? p : err()); // is 3d point +class Point { // Point in 3d xyz projective coords static readonly G = new Point(Gx, Gy, 1n); // generator / base point static readonly I = new Point(0n, 1n, 0n); // identity / zero point constructor(readonly x: bigint, readonly y: bigint, readonly z = 1n) {} // z is optional @@ -65,15 +64,18 @@ export class Point { // Point in 3d xyz proje } mul(n: bigint) { // multiplies point by scalar n if (!ge(n)) err(); // n must be 0 < n < CURVE.n - let p = Point.I; let f = Point.G // init identity / zero point & fake point + let p = I; let f = G; // init identity / zero point & fake point for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder if (n & 1n) p = p.add(d); else; f = f.add(d); // add to fake point when bit is not present } return p; } + mulAddQ(R: Point, u1: bigint, u2: bigint) { + return this.mul(u1).add(R.mul(u2)).ok(); // Q = u1⋅G + u2⋅R + } aff(): { x: bigint; y: bigint } { // converts point to 2d xy affine point const { x, y, z } = this; - if (this.eql(Point.I)) return { x: 0n, y: 0n }; // fast-path for zero point + if (this.eql(I)) return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is const iz = inv(z); // z^-1: invert z if (mod(z * iz) !== 1n) err(); // (z * z^-1) must be 1, otherwise bad math @@ -84,55 +86,49 @@ export class Point { // Point in 3d xyz proje if (!fe(x) || !fe(y)) err(); // x and y must be in range 0 < n < P const l = mod(y * y); // y² const r = crv(x); // x³ + ax + b - if (mod(l - r) !== 0n) err(); // y² = x³ + ax + b, must be equal - return this; + return mod(l - r) === 0n ? this : err(); // y² = x³ + ax + b, must be equal } static fromHex(hex: Hex): Point { // convert Uint8Array or hex string to Point - hex = ensureBytes(hex); // converts hex string to Uint8Array + hex = toU8(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; - const head = hex[0]; // first byte serves as prefix - const tail = hex.subarray(1); // the actual data - const x = sliceNum(tail, 0, fLen); // next 32 bytes are x coordinate - if (hex.length === 33 && [2, 3].includes(head)) { // compressed points are 33 bytes & start + const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data + const x = slcNum(tail, 0, fLen), len = hex.length;// next 32 bytes are x coordinate + if (len === 33 && [2, 3].includes(head)) { // Compressed points: 33b, start if (!fe(x)) err(); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (number: bigint, md = P): bigint => { // modular inversion, euclidean gcd algo if (number === 0n || md <= 0n) err(`n=${number} mod=${md}`); // can be invalid let a = mod(number, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { - const q = b / a; - const r = b % a; - const m = x - u * q; - const n = y - v * q; + const q = b / a, r = b % a; + const m = x - u * q, n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } - if (b !== 1n) err('invert: does not exist'); // b is gcd at this point - return mod(x, md); + return b === 1n ? mod(x, md) : err('invert does not exist'); // b is gcd at this point }; -const pow = (num: bigint, p: bigint, md: bigint): bigint => { // modular exponentiation num^p +const pow = (num: bigint, p: bigint, md = P): bigint => { // modular exponentiation num^p if (md <= 0n || p < 0n) err(); // exponentiation by squaring if (md === 1n) return 0n; // the ladder can leak exponent bits let res = 1n; // and is vulnerable to timing attacks @@ -146,51 +142,42 @@ const sqrt = (n: bigint) => { // √(y) = y^((p+1)/4) const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square return mod(r * r) === n ? r : err(); // Roots from 1;24,51,10 to Dan Shanks" } -const b2h = (uint8a: Uint8Array): string => { // bytes to hex string. Every uint8array - isBytes(uint8a); // item is number [0, 255] - let hex = ''; // convert number to hex string & pad with 0 - for (let i = 0; i < uint8a.length; i++) hex += uint8a[i].toString(16).padStart(2, '0'); - return hex; // byte 2 will become 02, etc -}; // hex to number +const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0') +const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex + // hex to number const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); -const h2b = (hex: string): Uint8Array => { // hex to bytes. error if not string, - if (!str(hex) || hex.length % 2) err(); // or has odd length like 3, 5 - const array = u8a(hex.length / 2); // create result array +const h2b = (hex: string): Bytes => { // hex to bytes + const l = hex.length; // error if not string, + if (!str(hex) || l % 2) err(); // or has odd length like 3, 5. + const array = u8a(l / 2); // create result array for (let i = 0; i < array.length; i++) { const j = i * 2; const hexByte = hex.slice(j, j + 2); // substr seems slower - const byte = Number.parseInt(hexByte, 16); // parse every string part, convert to - if (Number.isNaN(byte) || byte < 0) err(); // Number. Error if NaN or < 0 + const byte = Number.parseInt(hexByte, 16); // parse every string part, convert to num + if (Number.isNaN(byte) || byte < 0) err(); // error if NaN or < 0 array[i] = byte; } return array; }; -const b2n = (b: Uint8Array): bigint => h2n(b2h(b)); // bytes to number -const sliceNum = (b: Uint8Array, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes -const n2b = (num: bigint): Uint8Array => { // number to bytes - if (!bg(num) || num < 0n || num >= B256) err(); // must be 0 <= num < B256 - return h2b(num.toString(16).padStart(2 * fLen, '0')); +const b2n = (b: Bytes): bigint => h2n(b2h(b)); // bytes to number +const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes +const n2b = (num: bigint): Bytes => { // number to bytes. must be 0 <= num < B256 + return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err(); }; -const numToFieldStr = (num: bigint): string => b2h(n2b(num)); -const catBytes = (...arrays: Uint8Array[]) => { // concatenate Uint8Array-s - arrays.every((b) => isBytes(b)); - if (arrays.length === 1) return arrays[0]; - const length = arrays.reduce((a, arr) => a + arr.length, 0); - const result = u8a(length); - for (let i = 0, pad = 0; i < arrays.length; i++) { - const arr = arrays[i]; - result.set(arr, pad); - pad += arr.length; - } - return result; +const n2h = (num: bigint): string => b2h(n2b(num)); // number to hex +const concat = (...list: Bytes[]) => { // concatenate Uint8Array-s + let pad = 0; + const res = u8a(list.reduce((sum, arr) => sum + arr.length, 0)); + list.forEach(arr => { res.set(isU8(arr), pad); pad += arr.length; }); + return res; }; -const bits2int_2 = (bytes: Uint8Array) => { // bytes to bigint +const bits2int_2 = (bytes: Bytes) => { // bytes to bigint const delta = bytes.length * 8 - 256; // truncates bits const num = b2n(bytes); return delta > 0 ? num >> BigInt(delta) : num; }; -const truncH = (hash: Uint8Array): bigint => { // truncate hash +const truncH = (hash: Bytes): bigint => { // truncate hash const h = bits2int_2(hash); return h >= N ? h - N : h; }; @@ -199,30 +186,28 @@ const moreThanHalf = (n: bigint) => { // if a number is bigger return n > h; }; -export const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { // calculate public - return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private +const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { // calculate public + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; -export class Signature { // calculates signature +class Signature { // calculates signature constructor(readonly r: bigint, readonly s: bigint, readonly rec?: number) { this.ok(); } ok(): Signature { // validates signature - if (!ge(this.r)) err(); // 0 < r < CURVE.n - if (!ge(this.s)) err(); // 0 < s < CURVE.n - return this; + return ge(this.r) && ge(this.s) ? this : err(); // 0 < r < CURVE.n; 0 < s < CURVE.n } static fromCompact(hex: Hex) { // create signature from 64b compact repr - hex = ensureBytes(hex, 64); // compact repr is (32-byte r)+(32-byte s) - return new Signature(sliceNum(hex, 0, fLen), sliceNum(hex, fLen, 2 * fLen)); + hex = toU8(hex, 64); // compact repr is (32-byte r)+(32-byte s) + return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } - static fromKMD(kBytes: Uint8Array, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { + static fromKMD(kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { const k = bits2int_2(kBytes); // Utility method for RFC6979 k generation if (!ge(k)) return; // Check 0 < k < CURVE.n - const ik = inv(k, N); // k^-1 over CURVE.n, NOT CURVE.P + const ik = inv(k, N); // k^-1 mod n, NOT mod P const q = G.mul(k).aff(); // q = Gk - const r = mod(q.x, N); // r = q.x mod CURVE.n + const r = mod(q.x, N); // r = q.x mod n if (r === 0n) return; // invalid - const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1 * m + dr mod CURVE.n + const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1 * m + dr mod n if (s === 0n) return; // invalid let normS = s; // normalized s let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit @@ -232,83 +217,79 @@ export class Signature { // calculates signature } return new Signature(r, normS, rec); } + recoverPublicKey(msgHash: Hex): Point { + const { r, s, rec } = this; + if (rec == null || ![0, 1, 2, 3].includes(rec)) err(); + const h = truncH(toU8(msgHash)); + const radj = rec === 2 || rec === 3 ? r + N : r; + if (radj >= P) err(); + const ir = inv(radj, N); + const R = Point.fromHex(`${(rec! & 1) === 0 ? '02' : '03'}${n2h(radj)}`); + return G.mulAddQ(R, mod(-h * ir, N), mod(s * ir, N)); // Q = u1⋅G + u2⋅R + } toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr - toCompactHex() { return numToFieldStr(this.r) + numToFieldStr(this.s); } // hex 64b compact repr + toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr } -const b2i = (b: Uint8Array): bigint => { // RFC6979 methods: bytes to int - isBytes(b); +const b2i = (b: Bytes): bigint => { // RFC6979 methods: bytes to int + isU8(b); const sl = b.length > fLen ? b.slice(0, fLen) : b; // slice return b2n(sl); // call our own method }; -const b2o = (bytes: Uint8Array): Uint8Array => { // bits to octets +const b2o = (bytes: Bytes): Bytes => { // bits to octets const z1 = b2i(bytes); const z2 = mod(z1, N); return i2o(z2 < 0n ? z1 : z2); }; -const i2o = (num: bigint): Uint8Array => n2b(num); // int to octets -declare const self: Record | undefined; // Typescript global symbol available in -const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependence on @types/dom +const i2o = (num: bigint): Bytes => n2b(num); // int to octets +declare const self: Record | undefined; // Typescript global symbol available in +const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependence on @types/dom node: typeof require === 'function' && require('crypto'), // node.js require('crypto') web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, // browser-only var }; -const hmac = async (key: Uint8Array, ...messages: Uint8Array[]): Promise => { - const msgs = catBytes(...messages); // HMAC-SHA256 +const hmac = async (key: Bytes, ...messages: Bytes[]): Promise => { + const msgs = concat(...messages); // HMAC-SHA256 if (cr.web) { // browser built-in version - // prettier-ignore - const ckey = await cr.web.subtle.importKey( - 'raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign'] - ); - return u8a(await cr.web.subtle.sign('HMAC', ckey, msgs)); + const s = cr.web.subtle; + const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); + return u8a(await s.sign('HMAC', k, msgs)); } else if (cr.node) { // node.js built-in version return u8fr(cr.node.createHmac('sha256', key).update(msgs).digest()); } else { throw new Error('crypto required'); } }; -const randomBytes = (bytesLength: number): Uint8Array => { // CSPRNG: secure generator - if (cr.web) { // browser built-in version - return cr.web.getRandomValues(u8a(bytesLength)); - } else if (cr.node) { // node.js built-in version - return u8fr(cr.node.randomBytes(bytesLength)); - } else { - throw new Error('crypto required'); // error when no CSPRNG - } +const randomBytes = (len: number): Bytes => { // CSPRNG: secure generator + return cr.web ? cr.web.getRandomValues(u8a(len)) : + cr.node ? u8fr(cr.node.randomBytes(len)) : err('crypto required'); }; class HmacDrbg { // Minimal HMAC-DRBG (NIST 800-90) - k: Uint8Array; // used only for RFC6979 signatures. - v: Uint8Array; - counter: number; + private k: Bytes; // used only for RFC6979 signatures. + private v: Bytes; // Does not implement full spec. + private i: number; // counter variable constructor() { // Step B, Step C: set hashLen - this.v = u8a(fLen).fill(1); // to 8*ceil(hlen/8) - this.k = u8a(fLen).fill(0); - this.counter = 0; + this.v = u8a(fLen).fill(1); this.k = u8a(fLen).fill(0); // to 8*ceil(hlen/8) + this.i = 0; } async seed(seed = u8a()) { // DRBG reseed() function - const hk = (...vs: Uint8Array[]) => hmac(this.k, ...vs); // hmac(k)(...values) - const hv = (...vs: Uint8Array[]) => hk(this.v, ...vs); // hmac(k)(v, ...values) - this.k = await hv(u8fr([0x00]), seed); - this.v = await hv(); + const h = (...vs: Bytes[]) => hmac(this.k, this.v, ...vs); // hmac(k)(v, ...values) + this.k = await h(u8fr([0x00]), seed); this.v = await h(); if (seed.length === 0) return; - this.k = await hv(u8fr([0x01]), seed); - this.v = await hv(); + this.k = await h(u8fr([0x01]), seed); this.v = await h(); } - async gen(): Promise { // DRBG generate() function - if (this.counter >= 1000) err(); // Something is wrong if counter is 1k - this.counter += 1; + async gen(): Promise { // DRBG generate() function + if (this.i >= 1000) err(); // Something is wrong if counter is 1k + this.i += 1; this.v = await hmac(this.k, this.v); return this.v; } } -export const sign = async (msgHash: Hex, privKey: Hex, opts = stdOpts): Promise => { - if (opts?.der === true) err(); // RFC6979 ECDSA signature generation - if (opts?.extraEntropy) err(); // extraEntropy is not supported +const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { + if (opts?.der === true || opts?.extraEntropy || opts?.recovered) err(); // RFC6979 ECDSA if (opts?.lowS == null) opts.lowS = true; // generates low-s sigs by default - const _h1 = n2b(truncH(ensureBytes(msgHash))); // Steps A, D of RFC6979 3.2. - const d = normPriv(privKey); // d = normalize(privatekey) - if (!ge(d)) err(); // redundant check - const seedArgs = [i2o(d), b2o(_h1)]; // seed args for drbg - const seed = catBytes(...seedArgs); - const m = b2i(_h1); // convert msg to bigint + const h1 = n2b(truncH(toU8(msgh))); // Steps A, D of RFC6979 3.2. + const d = toPriv(priv); // d = normalize(privatekey) + const seed = concat(i2o(d), b2o(h1)); // seed args for drbg + const m = b2i(h1); // convert msg to bigint const drbg = new HmacDrbg(); // Steps B,C,D,E,F,G of RFC6979 3.2. await drbg.seed(seed); // Reseed DRBG. Then Step H3: let sig: Signature | undefined; // reseed until k is in range [1, n-1] @@ -317,7 +298,7 @@ export const sign = async (msgHash: Hex, privKey: Hex, opts = stdOpts): Promise< } type Sig = Hex | Signature; // signature verification -export const verify = (sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boolean => { +const verify = (sig: Sig, msgh: Hex, pub: Hex, opts = stdo): boolean => { if (opts?.lowS == null) opts.lowS = true; // lowS=true default let sig_: Signature; // Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf try { // verify(r, s, h, P) where u1 = hs^-1 mod n, u2 = rs^-1 mod n, @@ -326,42 +307,43 @@ export const verify = (sig: Sig, msgHash: Hex, pubKey: Hex, opts = stdOpts): boo if (!sig_) return false; const { r, s } = sig_; if (opts?.lowS && moreThanHalf(s)) return false; // lowS=true bans sig.s >= CURVE.n/2 - const h = truncH(ensureBytes(msgHash, fLen)); // truncate hash + const h = truncH(toU8(msgh, fLen)); // truncate hash let P: Point; try { // Validate public key - P = pubKey instanceof Point ? pubKey.ok() : Point.fromHex(pubKey); + P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); } catch (error) { return false; } - let R: { x: bigint; y: bigint } | undefined = undefined; + let R: { x: bigint, y: bigint } | undefined = undefined; try { const is = inv(s, N); // s^-1 const u1 = mod(h * is, N); // u1 = hs^-1 mod n const u2 = mod(r * is, N); // u2 = rs^-1 mod n - R = G.mul(u1).add(P.mul(u2))?.aff(); // R = u1⋅G + u2⋅P + R = G.mulAddQ(P, u1, u2).ok().aff(); // R = u1⋅G + u2⋅P } catch (error) { return false; } - if (!R || R.x === 0n || R.y === 0n) return false; // stop if R is identity / zero point + if (!R) return false; // stop if R is identity / zero point const v = mod(R.x, N); return v === r; // mod(R.x, n) == r } -export const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed?: boolean) => { - return Point.fromHex(pubB).mul(normPriv(privA)).toRawBytes(isCompressed); +const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed?: boolean) => { + return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); }; -const hashToPrivateKey = (hash: Hex): Uint8Array => { // FIPS 186 B.4.1 compliant key generation - hash = ensureBytes(hash); // produces private keys with modulo bias +const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation + hash = toU8(hash); // produces private keys with modulo bias const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err(); const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); }; -export const utils = { // utilities +const utils = { // utilities mod, invert: inv, // math utilities - concatBytes: catBytes, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, + concatBytes: concat, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, hashToPrivateKey, randomBytes, // CSPRNG etc. - randomPrivateKey: (): Uint8Array => hashToPrivateKey(randomBytes(fLen + 8)), // FIPS 186 B.4.1. + randomPrivateKey: (): Bytes => hashToPrivateKey(randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { // checks if private key is valid try { - return !!normPriv(key); + return !!toPriv(key); } catch (e) { return false; } }, }; +export { getPublicKey, sign, verify, getSharedSecret, CURVE, Point, Signature, utils }; diff --git a/test/benchmark.js b/test/benchmark.js index 02e8e15..0fe5d16 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -1,85 +1,29 @@ const { run, mark, logMem } = require('micro-bmark'); const secp = require('..'); const { join } = require('path'); -const { hmac } = require('@noble/hashes/hmac'); -const { sha256 } = require('@noble/hashes/sha256'); const points = require('fs') .readFileSync(join(__dirname, './vectors/points.txt'), 'utf-8') .split('\n') .filter((a) => a) .slice(0, 1000); -const { concatBytes } = secp.utils; - -secp.utils.sha256Sync = (...msgs) => - sha256.create().update(concatBytes(...msgs)).digest(), -secp.utils.hmacSha256Sync = (key, ...msgs) => - hmac.create(sha256, key).update(concatBytes(...msgs)).digest(); - -// run([4, 8, 16], async (windowSize) => { -run(async (windowSize) => { - const samples = 1000; - //console.log(`-------\nBenchmarking window=${windowSize} samples=${samples}...`); - await mark(() => { - secp.utils.precompute(windowSize); - }); - +run(async () => { logMem(); console.log(); - - // await mark('getPublicKey 1 bit', samples * 10, () => { - // secp.getPublicKey('0000000000000000000000000000000000000000000000000000000000000003'); - // }); - - // await mark('getPublicKey 256 bit', samples * 10, () => { - // secp.getPublicKey('7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcb'); - // }); - await mark('getPublicKey(utils.randomPrivateKey())', 5000, () => { + await mark('getPublicKey(utils.randomPrivateKey())', 500, () => { secp.getPublicKey(secp.utils.randomPrivateKey(), true); }); - const priv = 'f6fc7fd5acaf8603709160d203253d5cd17daa307483877ad811ec8411df56d2'; const pub = secp.getPublicKey(priv, true); const priv2 = '2e63f49054e1e44ccc2e6ef6ce387936efb16158f89cc302a2426e0b7fd66f66'; const pub2 = secp.getPublicKey(priv2, true); const msg = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef'; const signature = await secp.sign(msg, priv); - - await mark('sign', 5000, async () => { - await secp.sign(msg, priv); - }); - - await mark('signSync (@noble/hashes)', 5000, () => secp.signSync(msg, priv)); - - await mark('verify', 1000, () => { - secp.verify(signature, msg, pub); - }); - - const [rsig, reco] = await secp.sign(msg, priv, { canonical: true, recovered: true }); - await mark('recoverPublicKey', 1000, () => { - secp.recoverPublicKey(msg, rsig, reco); - }); - - await mark('getSharedSecret aka ecdh', 600, () => { - secp.getSharedSecret(priv, pub2); - }); - - const pub2Pre = secp.utils.precompute(windowSize, secp.Point.fromHex(pub2)); - await mark('getSharedSecret (precomputed)', 5000, () => { - secp.getSharedSecret(priv, pub2Pre); - }); - + await mark('sign', 500, async () => secp.sign(msg, priv)); + await mark('verify', 200, () => secp.verify(signature, msg, pub)); + await mark('getSharedSecret', 500, () => secp.getSharedSecret(priv, pub2)); let i = 0; - await mark('Point.fromHex (decompression)', 10000, () => { - const p = points[i++ % points.length]; - secp.Point.fromHex(p); - }); - - const smsg = '0000000000000000000000000000000000000000000000000000000000000000'; - const spri = '0000000000000000000000000000000000000000000000000000000000000003'; - const spub = secp.Point.fromPrivateKey(spri); - const ssig = await secp.schnorr.sign(smsg, spri); - await mark('schnorr.sign', 500, () => secp.schnorr.sign(smsg, spri)); - await mark('schnorr.verify', 1000, () => secp.schnorr.verify(ssig, smsg, spub)); + let len = points.length; + await mark('Point.fromHex (decompression)', 10000, () => secp.Point.fromHex(points[i++ % len])); console.log(); logMem(); }); From ddcc56da974bc2c72dd9589ce0d4b8b1f0f2c4e2 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 14 Jan 2023 18:14:43 +0000 Subject: [PATCH 016/145] Speed-up verification. Iteration 6: 6967, 345LOC --- index.ts | 92 +++++++++++++++++++++++------------------------ test/benchmark.js | 4 --- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/index.ts b/index.ts index 218a05b..a4331e6 100644 --- a/index.ts +++ b/index.ts @@ -6,23 +6,23 @@ const a = 0n; // a equation's param const b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -const CURVE = { P, n: N, a, b, Gx, Gy }; -const fLen = 32; // field/group byte length +const CURVE = { P, n: N, a, b, Gx, Gy }; // Variables +const fLen = 32; // field / group byte length const stdo: { lowS?: boolean; der?: boolean; extraEntropy?: any; recovered?: any } = { lowS: true }; -type Bytes = Uint8Array; type Hex = Bytes | string; // accepted: bytes/hex +type Bytes = Uint8Array; type Hex = Bytes | string; // accepted inputs: bytes/hex const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: any): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const u8a = (content?: any) => new Uint8Array(content); // creates Uint8Array byte arrays +const u8a = (content?: any) => new Uint8Array(content); // creates Uint8Array const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula -const err = (m = ''): never => { throw new Error(m); }; // throws error +const err = (m = ''): never => { throw new Error(m); }; // throws error, slightly messes stack trace const isU8 = (a: any, len?: number): Bytes => { // is Uint8Array (of specific length) if (!(a instanceof Uint8Array) || (typeof len === 'number' && len > 0 && a.length !== len)) err(); return a; }; -const toU8 = (a: any, len?: number) => isU8(str(a) ? h2b(a) : a, len); +const toU8 = (a: any, len?: number) => isU8(str(a) ? h2b(a) : a, len); // (hex or ui8a) to ui8a const toPriv = (p: Hex | bigint): bigint => { // normalize private key if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err(); // check if bigint is in range @@ -37,12 +37,12 @@ class Point { // Point in 3d xyz proje const { x: X2, y: Y2, z: Z2 } = isPoint(other); // isPoint() checks class equality return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); } - neg() { return new Point(this.x, mod(-this.y), this.z); } // creates negative version of the point + neg() { return new Point(this.x, mod(-this.y), this.z); } // negate, flips point over y coord dbl() { return this.add(this); } // point doubling - add(other: Point) { // addition, exception-free formula - const { x: X1, y: Y1, z: Z1 } = this; // from Renes-Costello-Batina - const { x: X2, y: Y2, z: Z2 } = isPoint(other); - let X3 = 0n, Y3 = 0n, Z3 = 0n; + add(other: Point) { // point addition: complete, exception-free + const { x: X1, y: Y1, z: Z1 } = this; // formula from Renes-Costello-Batina + const { x: X2, y: Y2, z: Z2 } = isPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 + let X3 = 0n, Y3 = 0n, Z3 = 0n; // Cost: 12M + 0S + 3*a + 3*b3 + 23add const b3 = mod(b * 3n); let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); // step 1 let t4 = mod(X2 + Y2); // step 5 @@ -62,20 +62,21 @@ class Point { // Point in 3d xyz proje Z3 = mod(Z3 + t0); // step 40 return new Point(X3, Y3, Z3); } - mul(n: bigint) { // multiplies point by scalar n - if (!ge(n)) err(); // n must be 0 < n < CURVE.n - let p = I; let f = G; // init identity / zero point & fake point + mul(n: bigint, safe = true) { // multiply point by scalar n + if (!ge(n)) err(); // must be 0 < n < CURVE.n + let p = I, f = G; // init result point & fake point for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder - if (n & 1n) p = p.add(d); else; f = f.add(d); // add to fake point when bit is not present + if (n & 1n) p = p.add(d); // if bit is present, add to point + else if (safe) f = f.add(d); // if not, add to fake for timing safety } return p; } - mulAddQ(R: Point, u1: bigint, u2: bigint) { - return this.mul(u1).add(R.mul(u2)).ok(); // Q = u1⋅G + u2⋅R - } + mulAddQUns(R: Point, u1: bigint, u2: bigint) { // Q = u1⋅G + u2⋅R: double scalar mult. + return this.mul(u1).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for anything related + } // to private keys. Doesn't use Shamir trick aff(): { x: bigint; y: bigint } { // converts point to 2d xy affine point const { x, y, z } = this; - if (this.eql(I)) return { x: 0n, y: 0n }; // fast-path for zero point + if (this.eql(I)) return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is const iz = inv(z); // z^-1: invert z if (mod(z * iz) !== 1n) err(); // (z * z^-1) must be 1, otherwise bad math @@ -92,7 +93,7 @@ class Point { // Point in 3d xyz proje hex = toU8(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data - const x = slcNum(tail, 0, fLen), len = hex.length;// next 32 bytes are x coordinate + const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate if (len === 33 && [2, 3].includes(head)) { // Compressed points: 33b, start if (!fe(x)) err(); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; // mod division -const inv = (number: bigint, md = P): bigint => { // modular inversion, euclidean gcd algo - if (number === 0n || md <= 0n) err(`n=${number} mod=${md}`); // can be invalid - let a = mod(number, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; - while (a !== 0n) { - const q = b / a, r = b % a; +const inv = (num: bigint, md = P): bigint => { // modular inversion + if (num === 0n || md <= 0n) err(`n=${num} mod=${md}`);// can be invalid + let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; + while (a !== 0n) { // uses euclidean gcd algorithm + const q = b / a, r = b % a; // not constant-time const m = x - u * q, n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } return b === 1n ? mod(x, md) : err('invert does not exist'); // b is gcd at this point }; -const pow = (num: bigint, p: bigint, md = P): bigint => { // modular exponentiation num^p - if (md <= 0n || p < 0n) err(); // exponentiation by squaring +const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiation num^e + if (md <= 0n || e < 0n) err(); // exponentiation by squaring if (md === 1n) return 0n; // the ladder can leak exponent bits let res = 1n; // and is vulnerable to timing attacks - for (; p > 0n; p >>= 1n) { - if (p & 1n) res = (res * num) % md; + for (; e > 0n; e >>= 1n) { + if (e & 1n) res = (res * num) % md; num = (num * num) % md; } return res; }; -const sqrt = (n: bigint) => { // √(y) = y^((p+1)/4) for fields P = 3 mod 4 +const sqrt = (n: bigint) => { // √(n) = n^((p+1)/4) for fields P = 3 mod 4 const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square return mod(r * r) === n ? r : err(); // Roots from 1;24,51,10 to Dan Shanks" } const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0') const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex - // hex to number -const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); +const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); // hex to number const h2b = (hex: string): Bytes => { // hex to bytes const l = hex.length; // error if not string, if (!str(hex) || l % 2) err(); // or has odd length like 3, 5. - const array = u8a(l / 2); // create result array - for (let i = 0; i < array.length; i++) { + const arr = u8a(l / 2); // create result array + for (let i = 0; i < arr.length; i++) { const j = i * 2; - const hexByte = hex.slice(j, j + 2); // substr seems slower - const byte = Number.parseInt(hexByte, 16); // parse every string part, convert to num - if (Number.isNaN(byte) || byte < 0) err(); // error if NaN or < 0 - array[i] = byte; + const h = hex.slice(j, j + 2); // hexByte. slice is faster than substr + const b = Number.parseInt(h, 16); // byte, created from string part + if (Number.isNaN(b) || b < 0) err(); // byte must be valid 0 <= byte < 256 + arr[i] = b; } - return array; + return arr; }; const b2n = (b: Bytes): bigint => h2n(b2h(b)); // bytes to number const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes @@ -190,14 +190,10 @@ const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { // calcu return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; class Signature { // calculates signature - constructor(readonly r: bigint, readonly s: bigint, readonly rec?: number) { - this.ok(); - } - ok(): Signature { // validates signature - return ge(this.r) && ge(this.s) ? this : err(); // 0 < r < CURVE.n; 0 < s < CURVE.n - } + constructor(readonly r: bigint, readonly s: bigint, readonly rec?: number) { this.ok(); } + ok(): Signature { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n static fromCompact(hex: Hex) { // create signature from 64b compact repr - hex = toU8(hex, 64); // compact repr is (32-byte r)+(32-byte s) + hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } static fromKMD(kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { @@ -225,7 +221,7 @@ class Signature { // calculates signature if (radj >= P) err(); const ir = inv(radj, N); const R = Point.fromHex(`${(rec! & 1) === 0 ? '02' : '03'}${n2h(radj)}`); - return G.mulAddQ(R, mod(-h * ir, N), mod(s * ir, N)); // Q = u1⋅G + u2⋅R + return G.mulAddQUns(R, mod(-h * ir, N), mod(s * ir, N)); // Q = u1⋅G + u2⋅R } toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr @@ -317,7 +313,7 @@ const verify = (sig: Sig, msgh: Hex, pub: Hex, opts = stdo): boolean => { const is = inv(s, N); // s^-1 const u1 = mod(h * is, N); // u1 = hs^-1 mod n const u2 = mod(r * is, N); // u2 = rs^-1 mod n - R = G.mulAddQ(P, u1, u2).ok().aff(); // R = u1⋅G + u2⋅P + R = G.mulAddQUns(P, u1, u2).aff(); // R = u1⋅G + u2⋅P } catch (error) { return false; } if (!R) return false; // stop if R is identity / zero point const v = mod(R.x, N); diff --git a/test/benchmark.js b/test/benchmark.js index 0fe5d16..e166cfe 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -7,8 +7,6 @@ const points = require('fs') .filter((a) => a) .slice(0, 1000); run(async () => { - logMem(); - console.log(); await mark('getPublicKey(utils.randomPrivateKey())', 500, () => { secp.getPublicKey(secp.utils.randomPrivateKey(), true); }); @@ -24,6 +22,4 @@ run(async () => { let i = 0; let len = points.length; await mark('Point.fromHex (decompression)', 10000, () => secp.Point.fromHex(points[i++ % len])); - console.log(); - logMem(); }); From 56332e60d978f1988f1e4f9ad19c63c4c9924ef5 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 14 Jan 2023 21:41:58 +0100 Subject: [PATCH 017/145] wNAF precomputes, 10x faster sign. Iteration 7: 7458, 387LOC --- index.ts | 56 +++++++++++++++++++++++++++++++++++++++++------ test/benchmark.js | 6 ++--- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/index.ts b/index.ts index a4331e6..c2daa1e 100644 --- a/index.ts +++ b/index.ts @@ -28,6 +28,7 @@ const toPriv = (p: Hex | bigint): bigint => { // normalize private key return ge(p) ? p : err(); // check if bigint is in range }; const isPoint = (p: any) => (p instanceof Point ? p : err()); // is 3d point +let Gprec: Point[] | undefined = undefined; // Precomputes for base point G class Point { // Point in 3d xyz projective coords static readonly G = new Point(Gx, Gy, 1n); // generator / base point static readonly I = new Point(0n, 1n, 0n); // identity / zero point @@ -64,6 +65,7 @@ class Point { // Point in 3d xyz proje } mul(n: bigint, safe = true) { // multiply point by scalar n if (!ge(n)) err(); // must be 0 < n < CURVE.n + if (Gprec && this.eql(G)) return wNAF(n).p; // if base point, use precomputes let p = I, f = G; // init result point & fake point for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder if (n & 1n) p = p.add(d); // if bit is present, add to point @@ -114,7 +116,7 @@ class Point { // Point in 3d xyz proje return h2b(this.toHex(isCompressed)); // Re-use toHex(), convert hex to bytes } static fromPrivateKey(n: bigint | Hex) { // Create point from a private key. Multiply - return G.mul(toPriv(n)); // base generator point by bigint(n) + return G.mul(toPriv(n)); // base point by bigint(n) } } const { G, I } = Point; // Generator, identity points @@ -226,12 +228,12 @@ class Signature { // calculates signature toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr } -const b2i = (b: Bytes): bigint => { // RFC6979 methods: bytes to int +const b2i = (b: Bytes): bigint => { // RFC6979 bytes to int isU8(b); const sl = b.length > fLen ? b.slice(0, fLen) : b; // slice return b2n(sl); // call our own method }; -const b2o = (bytes: Bytes): Bytes => { // bits to octets +const b2o = (bytes: Bytes): Bytes => { // RFC6979 bits to octets const z1 = b2i(bytes); const z2 = mod(z1, N); return i2o(z2 < 0n ? z1 : z2); @@ -279,8 +281,8 @@ class HmacDrbg { // Minimal HMAC-DRBG (NI return this.v; } } -const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { - if (opts?.der === true || opts?.extraEntropy || opts?.recovered) err(); // RFC6979 ECDSA +const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { // RFC6979 ECDSA + if (opts?.der === true || opts?.extraEntropy || opts?.recovered) err(); // signature generation if (opts?.lowS == null) opts.lowS = true; // generates low-s sigs by default const h1 = n2b(truncH(toU8(msgh))); // Steps A, D of RFC6979 3.2. const d = toPriv(priv); // d = normalize(privatekey) @@ -293,7 +295,7 @@ const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { return sig; } -type Sig = Hex | Signature; // signature verification +type Sig = Hex | Signature; // ECDSA signature verification const verify = (sig: Sig, msgh: Hex, pub: Hex, opts = stdo): boolean => { if (opts?.lowS == null) opts.lowS = true; // lowS=true default let sig_: Signature; // Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf @@ -332,7 +334,7 @@ const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compli const utils = { // utilities mod, invert: inv, // math utilities concatBytes: concat, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, - hashToPrivateKey, randomBytes, // CSPRNG etc. + randomBytes, hashToPrivateKey, // CSPRNG etc. randomPrivateKey: (): Bytes => hashToPrivateKey(randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { // checks if private key is valid try { @@ -342,4 +344,44 @@ const utils = { // utilities } }, }; +const W = 8; // Precomputes-related code. W = window size +const precompute = () => { // They give 12x faster getPublicKey(), + const points: Point[] = [], wins = 256 / W + 1; // 10x sign(), 2x verify(). To achieve this, + let p = G, b = p; // app needs to spend 40ms+ to calculate + for (let w = 0; w < wins; w++) { // 65536 points related to base point G + b = p; // Points are stored in array and used + points.push(b); // any time Gx multiplication is done. + for (let i = 1; i < 2 ** (W - 1); i++) { b = b.add(p); points.push(b); } + p = b.dbl(); // Precomputes do not speed-up getSharedKey, + } // which multiplies user point by scalar, + return points; // when precomputes are using base point +} +const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method + if (256 % W) err(); // Compared to other point mult methods, + let comp = Gprec; // allows to store 2x less points by + if (!comp) err(); // using subtraction. + comp = comp!; + let p = I, f = G; // f must be G, or could become I in the end + const wins = 1 + 256 / W; // W=8 17 windows + const wsize = 2 ** (W - 1); // W=8 128 window size + const mask = BigInt(2 ** W - 1); // W=8 will create mask 0b11111111 + const maxNum = 2 ** W; // W=8 256 + const shiftBy = BigInt(W); // W=8 8 + for (let w = 0; w < wins; w++) { + const off = w * wsize; + let wbits = Number(n & mask); // extract W bits. + n >>= shiftBy; // shift number by W bits. + if (wbits > wsize) { wbits -= maxNum; n += 1n; } // split if bits>max: +224 => 256-32 + const off1 = off, off2 = off + Math.abs(wbits) - 1; // offsets + const cond1 = w % 2 !== 0, cond2 = wbits < 0; // conditions + const neg = (bool: boolean, item: Point) => bool ? item.neg() : item; // negate + if (wbits === 0) { + f = f.add(neg(cond1, comp[off1])); // bit is 0: add garbage to fake point + } else { + p = p.add(neg(cond2, comp[off2])); // bit is 1: add to result point + } + } + return { p, f } // return both real and fake points for JIT +}; +Gprec = precompute(); // <= you can disable precomputes by commenting-out the line export { getPublicKey, sign, verify, getSharedSecret, CURVE, Point, Signature, utils }; diff --git a/test/benchmark.js b/test/benchmark.js index e166cfe..1bdc249 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -7,7 +7,7 @@ const points = require('fs') .filter((a) => a) .slice(0, 1000); run(async () => { - await mark('getPublicKey(utils.randomPrivateKey())', 500, () => { + await mark('getPublicKey(utils.randomPrivateKey())', 5000, () => { secp.getPublicKey(secp.utils.randomPrivateKey(), true); }); const priv = 'f6fc7fd5acaf8603709160d203253d5cd17daa307483877ad811ec8411df56d2'; @@ -16,8 +16,8 @@ run(async () => { const pub2 = secp.getPublicKey(priv2, true); const msg = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef'; const signature = await secp.sign(msg, priv); - await mark('sign', 500, async () => secp.sign(msg, priv)); - await mark('verify', 200, () => secp.verify(signature, msg, pub)); + await mark('sign', 4000, async () => secp.sign(msg, priv)); + await mark('verify', 500, () => secp.verify(signature, msg, pub)); await mark('getSharedSecret', 500, () => secp.getSharedSecret(priv, pub2)); let i = 0; let len = points.length; From 15d54822fcd87cb13b00d45d494168fca06e1f42 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 14 Jan 2023 21:57:55 +0000 Subject: [PATCH 018/145] Bring back wychenproof vectors and pubkey recovery tests --- index.ts | 7 +- test/benchmark.js | 1 + test/index.ts | 180 +++++++++++++++++++++++++++++----------------- 3 files changed, 120 insertions(+), 68 deletions(-) diff --git a/index.ts b/index.ts index c2daa1e..a79917e 100644 --- a/index.ts +++ b/index.ts @@ -64,6 +64,7 @@ class Point { // Point in 3d xyz proje return new Point(X3, Y3, Z3); } mul(n: bigint, safe = true) { // multiply point by scalar n + if (!safe && n === 0n) return I; // In unsafe mode, allow zero if (!ge(n)) err(); // must be 0 < n < CURVE.n if (Gprec && this.eql(G)) return wNAF(n).p; // if base point, use precomputes let p = I, f = G; // init result point & fake point @@ -74,7 +75,7 @@ class Point { // Point in 3d xyz proje return p; } mulAddQUns(R: Point, u1: bigint, u2: bigint) { // Q = u1⋅G + u2⋅R: double scalar mult. - return this.mul(u1).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for anything related + return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related } // to private keys. Doesn't use Shamir trick aff(): { x: bigint; y: bigint } { // converts point to 2d xy affine point const { x, y, z } = this; @@ -223,7 +224,9 @@ class Signature { // calculates signature if (radj >= P) err(); const ir = inv(radj, N); const R = Point.fromHex(`${(rec! & 1) === 0 ? '02' : '03'}${n2h(radj)}`); - return G.mulAddQUns(R, mod(-h * ir, N), mod(s * ir, N)); // Q = u1⋅G + u2⋅R + const u1 = mod(-h * ir, N); + const u2 = mod(s * ir, N); + return G.mulAddQUns(R, u1, u2); // Q = u1⋅G + u2⋅R } toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr diff --git a/test/benchmark.js b/test/benchmark.js index 1bdc249..c01f204 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -19,6 +19,7 @@ run(async () => { await mark('sign', 4000, async () => secp.sign(msg, priv)); await mark('verify', 500, () => secp.verify(signature, msg, pub)); await mark('getSharedSecret', 500, () => secp.getSharedSecret(priv, pub2)); + await mark('recoverPublicKey', 500, () => signature.recoverPublicKey(msg)); let i = 0; let len = points.length; await mark('Point.fromHex (decompression)', 10000, () => secp.Point.fromHex(points[i++ % len])); diff --git a/test/index.ts b/test/index.ts index 0505308..084fca6 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,6 +1,7 @@ import * as fc from 'fast-check'; import * as secp from '..'; import { readFileSync } from 'fs'; +import { createHash } from 'crypto'; // import { createHash } from 'crypto'; import * as sysPath from 'path'; import * as ecdsa from './vectors/ecdsa.json'; @@ -24,6 +25,47 @@ const toBEHex = (n: number | bigint) => n.toString(16).padStart(64, '0'); const hex = secp.utils.bytesToHex; const hexToBytes = secp.utils.hexToBytes; +// const { Signature } = secp; +const { bytesToNumber: b2n, hexToBytes: h2b } = secp.utils; +const DER = { // asn.1 DER encoding utils + Err: class DERErr extends Error { constructor(m = '') { super(m); } }, + _parseInt(data: Uint8Array): { d: bigint; l: Uint8Array } { + const { Err: E } = DER; + if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag'); + const len = data[1]; + const res = data.subarray(2, len + 2); + if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length'); + if (res[0] === 0x00 && res[1] <= 0x7f) + throw new E('Invalid signature integer: trailing length'); + // ^ Weird condition: not about length, but about first bytes of number. + return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left + }, + toSig(hex: string) { // parse DER signature + const { Err: E } = DER; + const data = typeof(hex) === 'string' ? secp.utils.hexToBytes(hex) : hex; + let l = data.length; + if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); + if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); + const { d: r, l: sBytes } = DER._parseInt(data.subarray(2)); + const { d: s, l: rBytesLeft } = DER._parseInt(sBytes); + if (rBytesLeft.length) throw new E('Invalid signature: left bytes after parsing'); + return new secp.Signature(r, s); + }, + fromSig(sig: secp.Signature): Uint8Array { + return h2b(DER.hexFromSig(sig)) + }, + hexFromSig(sig: secp.Signature): string { + const slice = (s: string): string => Number.parseInt(s[0], 16) >= 8 ? '00' + s : s; // slice DER + const h = (num: number | bigint) => { + const hex = num.toString(16); return hex.length & 1 ? `0${hex}` : hex; + }; + const s = slice(h(sig.s)), r = slice(h(sig.r)); + const shl = s.length / 2, rhl = r.length / 2; + const sl = h(shl), rl = h(rhl); + return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; + }, +}; + function hexToNumber(hex: string): bigint { if (typeof hex !== 'string') { throw new TypeError('hexToNumber: expected string, got ' + typeof hex); @@ -390,43 +432,45 @@ describe('secp256k1', () => { // } // }); - // describe('.recoverPublicKey()', () => { - // it('should recover public key from recovery bit', async () => { - // const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; - // const privateKey = 123456789n; - // const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); - // const [signature, recovery] = await secp.sign(message, privateKey, { recovered: true }); - // const recoveredPubkey = secp.recoverPublicKey(message, signature, recovery); - // expect(recoveredPubkey).not.toBe(null); - // expect(hex(recoveredPubkey!)).toBe(publicKey); - // expect(secp.verify(signature, message, publicKey)).toBe(true); - // }); - // it('should not recover zero points', () => { - // const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; - // const sig = - // '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; - // const recovery = 0; - // expect(() => secp.recoverPublicKey(msgHash, sig, recovery)).toThrowError(); - // }); - // it('should handle all-zeros msghash', async () => { - // const privKey = secp.utils.randomPrivateKey(); - // const pub = secp.getPublicKey(privKey); - // const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; - // const [sig, rec] = await secp.sign(zeros, privKey, { recovered: true }); - // const recoveredKey = secp.recoverPublicKey(zeros, sig, rec); - // expect(recoveredKey).toEqual(pub); - // }); - // it('should handle RFC 6979 vectors', async () => { - // for (const vector of ecdsa.valid) { - // if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue; - // let [usig, rec] = await secp.sign(vector.m, vector.d, { der: false, recovered: true }); - // let sig = hex(usig); - // const vpub = secp.getPublicKey(vector.d); - // const recovered = secp.recoverPublicKey(vector.m, sig, rec)!; - // expect(hex(recovered)).toBe(hex(vpub)); - // } - // }); - // }); + describe('.recoverPublicKey()', () => { + it('should recover public key from recovery bit', async () => { + const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; + const privateKey = secp.utils.numToField(123456789n); + const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); + const sig = await secp.sign(message, privateKey); + const recoveredPubkey = sig.recoverPublicKey(message); + expect(recoveredPubkey).not.toBe(null); + expect(recoveredPubkey.toHex()).toBe(publicKey); + expect(secp.verify(sig, message, publicKey)).toBe(true); + }); + it('should not recover zero points', () => { + const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; + const sig = + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; + const recovery = 0; + const sigi = secp.Signature.fromCompact(sig); + const sigir = new secp.Signature(sigi.r, sigi.s, recovery); + expect(() => sigir.recoverPublicKey(msgHash)).toThrowError(); + }); + it('should handle all-zeros msghash', async () => { + const privKey = secp.utils.randomPrivateKey(); + const pub = secp.getPublicKey(privKey); + const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; + const sig = await secp.sign(zeros, privKey); + const recoveredKey = sig.recoverPublicKey(zeros); + expect(recoveredKey.toRawBytes()).toEqual(pub); + }); + it('should handle RFC 6979 vectors', async () => { + for (const vector of ecdsa.valid) { + if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue; + let sig = await secp.sign(vector.m, vector.d); + // let sig = hex(usig); + const vpub = secp.getPublicKey(vector.d); + const recovered = sig.recoverPublicKey(vector.m)!; + expect(recovered.toHex()).toBe(hex(vpub)); + } + }); + }); describe('.getSharedSecret()', () => { // TODO: Real implementation. @@ -547,35 +591,39 @@ describe('secp256k1', () => { }); }); - // describe('wychenproof vectors', () => { - // it('should pass all tests', async () => { - // for (let group of wp.testGroups) { - // const pubKey = secp.Point.fromHex(group.key.uncompressed); - // for (let test of group.tests) { - // const m = await secp.utils.sha256(hexToBytes(test.msg)); - // if (test.result === 'valid' || test.result === 'acceptable') { - // const verified = secp.verify(test.sig, m, pubKey); - // if (secp.Signature.fromDER(test.sig).hasHighS()) { - // expect(verified).toBeFalsy(); - // } else { - // expect(verified).toBeTruthy(); - // } - // } else if (test.result === 'invalid') { - // let failed = false; - // try { - // const verified = secp.verify(test.sig, m, pubKey); - // if (!verified) failed = true; - // } catch (error) { - // failed = true; - // } - // expect(failed).toBeTruthy(); - // } else { - // expect(false).toBeTruthy(); - // } - // } - // } - // }); - // }); + describe('wychenproof vectors', () => { + const sha256 = (m: Uint8Array) => Uint8Array.from(createHash('sha256').update(m).digest()) + it('should pass all tests', async () => { + for (let group of wp.testGroups) { + const pubKey = secp.Point.fromHex(group.key.uncompressed); + for (let test of group.tests) { + const m = sha256(hexToBytes(test.msg)); + if (test.result === 'valid' || test.result === 'acceptable') { + const parsed = DER.toSig(test.sig); + const verified = secp.verify(parsed, m, group.key.uncompressed); + if (parsed.s > (secp.CURVE.n >> 1n)) { + expect(verified).toBeFalsy(); + } else { + console.log('verified', test); + + expect(verified).toBeTruthy(); + } + } else if (test.result === 'invalid') { + let failed = false; + try { + const verified = secp.verify(test.sig, m, group.key.uncompressed); + if (!verified) failed = true; + } catch (error) { + failed = true; + } + expect(failed).toBeTruthy(); + } else { + expect(false).toBeTruthy(); + } + } + } + }); + }); }); // describe('JacobianPoint', () => { From 96b70b04d42efb21fdbcc0671dba8054a98698f8 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 17 Jan 2023 22:40:37 +0000 Subject: [PATCH 019/145] Sync methods, extraEntropy, Point->JPoint, error map. Iteration 8: 8040, 423LOC --- index.ts | 291 ++++++++++++++++++++++++++-------------------- package.json | 3 +- test/benchmark.js | 1 + test/index.ts | 206 ++++++++++++++++---------------- 4 files changed, 273 insertions(+), 228 deletions(-) diff --git a/index.ts b/index.ts index a79917e..b42d521 100644 --- a/index.ts +++ b/index.ts @@ -6,31 +6,30 @@ const a = 0n; // a equation's param const b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -const CURVE = { P, n: N, a, b, Gx, Gy }; // Variables +const CURVE = { P, n: N, a, b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length -const stdo: { lowS?: boolean; der?: boolean; extraEntropy?: any; recovered?: any } = { lowS: true }; type Bytes = Uint8Array; type Hex = Bytes | string; // accepted inputs: bytes/hex +const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula +const errs = {'':'', l: 'legacy', h: 'no sync hmac', i: 'no inv', c: 'no CSPRNG/hmac', t: 'type'}; +const err = (m: keyof typeof errs = '', sfx = ''): never => { throw new Error(errs[m]+sfx); }; const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: any): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element const u8a = (content?: any) => new Uint8Array(content); // creates Uint8Array const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut -const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula -const err = (m = ''): never => { throw new Error(m); }; // throws error, slightly messes stack trace -const isU8 = (a: any, len?: number): Bytes => { // is Uint8Array (of specific length) - if (!(a instanceof Uint8Array) || (typeof len === 'number' && len > 0 && a.length !== len)) err(); - return a; -}; +const isU8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) + !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err() : a; const toU8 = (a: any, len?: number) => isU8(str(a) ? h2b(a) : a, len); // (hex or ui8a) to ui8a const toPriv = (p: Hex | bigint): bigint => { // normalize private key if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err(); // check if bigint is in range }; +let Gpows: Point[] | undefined = undefined; // Precomputes for base point G +interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords const isPoint = (p: any) => (p instanceof Point ? p : err()); // is 3d point -let Gprec: Point[] | undefined = undefined; // Precomputes for base point G class Point { // Point in 3d xyz projective coords - static readonly G = new Point(Gx, Gy, 1n); // generator / base point + static readonly G = new Point(Gx, Gy, 1n); // generator / base point. static readonly I = new Point(0n, 1n, 0n); // identity / zero point constructor(readonly x: bigint, readonly y: bigint, readonly z = 1n) {} // z is optional eql(other: Point): boolean { // equality check @@ -66,7 +65,7 @@ class Point { // Point in 3d xyz proje mul(n: bigint, safe = true) { // multiply point by scalar n if (!safe && n === 0n) return I; // In unsafe mode, allow zero if (!ge(n)) err(); // must be 0 < n < CURVE.n - if (Gprec && this.eql(G)) return wNAF(n).p; // if base point, use precomputes + if (this.eql(G)) return wNAF(n).p; // Use precomputes for base point let p = I, f = G; // init result point & fake point for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder if (n & 1n) p = p.add(d); // if bit is present, add to point @@ -77,7 +76,7 @@ class Point { // Point in 3d xyz proje mulAddQUns(R: Point, u1: bigint, u2: bigint) { // Q = u1⋅G + u2⋅R: double scalar mult. return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related } // to private keys. Doesn't use Shamir trick - aff(): { x: bigint; y: bigint } { // converts point to 2d xy affine point + aff(): AffinePoint { // converts point to 2d xy affine point const { x, y, z } = this; if (this.eql(I)) return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is @@ -97,7 +96,7 @@ class Point { // Point in 3d xyz proje let p: Point | undefined = undefined; const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate - if (len === 33 && [2, 3].includes(head)) { // Compressed points: 33b, start + if (len === 33 && [0x02, 0x03].includes(head)) { // Compressed points: 33b, start if (!fe(x)) err(); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num: bigint, md = P): bigint => { // modular inversion - if (num === 0n || md <= 0n) err(`n=${num} mod=${md}`);// can be invalid + if (num === 0n || md <= 0n) err('i', ` n=${num} mod=${md}`); // negative exponent not supported let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { // uses euclidean gcd algorithm const q = b / a, r = b % a; // not constant-time const m = x - u * q, n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } - return b === 1n ? mod(x, md) : err('invert does not exist'); // b is gcd at this point + return b === 1n ? mod(x, md) : err('i'); // b is gcd at this point }; const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiation num^e if (md <= 0n || e < 0n) err(); // exponentiation by squaring @@ -145,7 +144,7 @@ const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiat const sqrt = (n: bigint) => { // √(n) = n^((p+1)/4) for fields P = 3 mod 4 const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square return mod(r * r) === n ? r : err(); // Roots from 1;24,51,10 to Dan Shanks" -} +}; const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0') const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); // hex to number @@ -163,31 +162,28 @@ const h2b = (hex: string): Bytes => { // hex to bytes return arr; }; const b2n = (b: Bytes): bigint => h2n(b2h(b)); // bytes to number -const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes +const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num: bigint): Bytes => { // number to bytes. must be 0 <= num < B256 return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err(); }; const n2h = (num: bigint): string => b2h(n2b(num)); // number to hex -const concat = (...list: Bytes[]) => { // concatenate Uint8Array-s +const concatB = (...list: Bytes[]) => { // concatenate Uint8Array-s let pad = 0; const res = u8a(list.reduce((sum, arr) => sum + arr.length, 0)); list.forEach(arr => { res.set(isU8(arr), pad); pad += arr.length; }); return res; }; -const bits2int_2 = (bytes: Bytes) => { // bytes to bigint +const b2n_2 = (bytes: Bytes) => { // bytes to bigint const delta = bytes.length * 8 - 256; // truncates bits const num = b2n(bytes); return delta > 0 ? num >> BigInt(delta) : num; }; const truncH = (hash: Bytes): bigint => { // truncate hash - const h = bits2int_2(hash); + const h = b2n_2(hash); return h >= N ? h - N : h; }; -const moreThanHalf = (n: bigint) => { // if a number is bigger than CURVE.n/2 - const h = N >> 1n; - return n > h; -}; +const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { // calculate public return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private @@ -199,34 +195,18 @@ class Signature { // calculates signature hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } - static fromKMD(kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined { - const k = bits2int_2(kBytes); // Utility method for RFC6979 k generation - if (!ge(k)) return; // Check 0 < k < CURVE.n - const ik = inv(k, N); // k^-1 mod n, NOT mod P - const q = G.mul(k).aff(); // q = Gk - const r = mod(q.x, N); // r = q.x mod n - if (r === 0n) return; // invalid - const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1 * m + dr mod n - if (s === 0n) return; // invalid - let normS = s; // normalized s - let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit - if (lowS && moreThanHalf(s)) { // if option lowS was passed, - normS = mod(-s, N); // ensure s is always in the bottom half - rec ^= 1; // of CURVE.n - } - return new Signature(r, normS, rec); - } - recoverPublicKey(msgHash: Hex): Point { - const { r, s, rec } = this; - if (rec == null || ![0, 1, 2, 3].includes(rec)) err(); - const h = truncH(toU8(msgHash)); - const radj = rec === 2 || rec === 3 ? r + N : r; - if (radj >= P) err(); - const ir = inv(radj, N); - const R = Point.fromHex(`${(rec! & 1) === 0 ? '02' : '03'}${n2h(radj)}`); - const u1 = mod(-h * ir, N); - const u2 = mod(s * ir, N); - return G.mulAddQUns(R, u1, u2); // Q = u1⋅G + u2⋅R + recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery + const { r, s, rec } = this; // section 4.1.6 of secg.org/sec1-v2.pdf + if (rec == null || ![0, 1, 2, 3].includes(rec)) err(); // also can just grind through all values + const h = truncH(toU8(msgh)); // Truncate hash + const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n + if (radj >= P) err(); // ensure q.x is still a field element + const prefix = (rec! & 1) === 0 ? '02' : '03'; // prefix is 0x02 or 0x03 + const R = Point.fromHex(`${prefix}${n2h(radj)}`); // concat prefix + hex repr of r + const ir = inv(radj, N); // r^-1 + const u1 = mod(-h * ir, N); // -hr^-1 + const u2 = mod(s * ir, N); // sr^-1 + return G.mulAddQUns(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) } toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr @@ -247,73 +227,122 @@ const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependen node: typeof require === 'function' && require('crypto'), // node.js require('crypto') web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, // browser-only var }; -const hmac = async (key: Bytes, ...messages: Bytes[]): Promise => { - const msgs = concat(...messages); // HMAC-SHA256 +const hmac = async (key: Bytes, ...msgs: Bytes[]): Promise => { + const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! if (cr.web) { // browser built-in version const s = cr.web.subtle; const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); - return u8a(await s.sign('HMAC', k, msgs)); + return u8a(await s.sign('HMAC', k, m)); } else if (cr.node) { // node.js built-in version - return u8fr(cr.node.createHmac('sha256', key).update(msgs).digest()); + return u8fr(cr.node.createHmac('sha256', key).update(m).digest()); } else { - throw new Error('crypto required'); + return err('c'); } }; -const randomBytes = (len: number): Bytes => { // CSPRNG: secure generator - return cr.web ? cr.web.getRandomValues(u8a(len)) : - cr.node ? u8fr(cr.node.randomBytes(len)) : err('crypto required'); +type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); +let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it +const stdo: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() +const vstdo = { lowS: true }; // standard opts for verify() +type PSA = [Bytes, bigint, bigint, boolean]; // return type of prepSig() +const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC6979 sig generation + if (['der', 'recovered', 'canonical'].some(k => k in opts)) err('l'); // Ban legacy options + let low = opts?.lowS; // generates low-s sigs by default + if (low == null) low = true; // RFC6979 3.2: we skip step A, because + const h1 = n2b(truncH(toU8(msgh))); // the message hash is already provided + const d = toPriv(priv); // validate private key, convert to bigint + const seed = [i2o(d), b2o(h1)]; // Step D of RFC6979 3.2 + let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) + if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + if (ent === true) ent = utils.randomBytes(fLen); // if true, use CSPRNG to generate data + const e = toU8(ent); // convert Hex|Bytes to Bytes + if (e.length !== fLen) err(); // Expected 32 bytes of extra data + seed.push(e); + } + const m = b2i(h1); // convert msg to bigint + return [concatB(...seed), m, d, low]; }; -class HmacDrbg { // Minimal HMAC-DRBG (NIST 800-90) - private k: Bytes; // used only for RFC6979 signatures. - private v: Bytes; // Does not implement full spec. - private i: number; // counter variable - constructor() { // Step B, Step C: set hashLen - this.v = u8a(fLen).fill(1); this.k = u8a(fLen).fill(0); // to 8*ceil(hlen/8) - this.i = 0; +const kmd2sig = (kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined => { + const k = b2n_2(kBytes); // Utility method for RFC6979 k generation + if (!ge(k)) return; // Check 0 < k < CURVE.n + const ik = inv(k, N); // k^-1 mod n, NOT mod P + const q = G.mul(k).aff(); // q = Gk + const r = mod(q.x, N); // r = q.x mod n + if (r === 0n) return; // invalid + const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1 * m + dr mod n + if (s === 0n) return; // invalid + let normS = s; // normalized s + let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit + if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always + normS = mod(-s, N); // in the bottom half of CURVE.n + rec ^= 1; } - async seed(seed = u8a()) { // DRBG reseed() function - const h = (...vs: Bytes[]) => hmac(this.k, this.v, ...vs); // hmac(k)(v, ...values) - this.k = await h(u8fr([0x00]), seed); this.v = await h(); + return new Signature(r, normS, rec); +}; +const hmacDrbgA = async (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMAC-DRBG async + let v = u8a(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8a(fLen).fill(0); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same + let i = 0; // Iterations counter, will throw when over 1000 + const h = (...b: Bytes[]) => hmac(k, v, ...b); // hmac(k)(v, ...values) + const reseed = async (seed = u8a()) => { // HMAC-DRBG reseed() function. Steps D-G + k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) + v = await h(); // v = hmac(K || V) if (seed.length === 0) return; - this.k = await h(u8fr([0x01]), seed); this.v = await h(); - } - async gen(): Promise { // DRBG generate() function - if (this.i >= 1000) err(); // Something is wrong if counter is 1k - this.i += 1; - this.v = await hmac(this.k, this.v); - return this.v; - } -} -const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { // RFC6979 ECDSA - if (opts?.der === true || opts?.extraEntropy || opts?.recovered) err(); // signature generation - if (opts?.lowS == null) opts.lowS = true; // generates low-s sigs by default - const h1 = n2b(truncH(toU8(msgh))); // Steps A, D of RFC6979 3.2. - const d = toPriv(priv); // d = normalize(privatekey) - const seed = concat(i2o(d), b2o(h1)); // seed args for drbg - const m = b2i(h1); // convert msg to bigint - const drbg = new HmacDrbg(); // Steps B,C,D,E,F,G of RFC6979 3.2. - await drbg.seed(seed); // Reseed DRBG. Then Step H3: - let sig: Signature | undefined; // reseed until k is in range [1, n-1] - while (!(sig = Signature.fromKMD(await drbg.gen(), m, d, !!opts?.lowS))) await drbg.seed(); + k = await h(u8fr([0x01]), seed); // k = hmac(K || V || 0x01 || seed) + v = await h(); // v = hmac(K || V) + }; + const gen = async () => { // HMAC-DRBG generate() function + if (i++ >= 1000) err(); + v = await hmac(k, v); // v = hmac(K || V) + return v; + }; + await reseed(seed); // Steps D-G + let sig: Signature | undefined = undefined; // Step H: grind until k is in [1..n-1] + while (!(sig = kmd2sig(await gen(), m, d, lowS))) await reseed(); return sig; -} - -type Sig = Hex | Signature; // ECDSA signature verification -const verify = (sig: Sig, msgh: Hex, pub: Hex, opts = stdo): boolean => { - if (opts?.lowS == null) opts.lowS = true; // lowS=true default - let sig_: Signature; // Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf - try { // verify(r, s, h, P) where u1 = hs^-1 mod n, u2 = rs^-1 mod n, +}; +const hmacDrbgS = (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMAC-DRBG sync + let v = u8a(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8a(fLen).fill(0); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let i = 0; // Iterations counter, will throw when over 1000 + if (!_hmacSync) err('h'); + const h = (...b: Bytes[]) => _hmacSync!(k, v, ...b); // hmac(k)(v, ...values) + const reseed = (seed = u8a()) => { // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) + v = h(); // v = hmac(k || v) + if (seed.length === 0) return; + k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) + v = h(); // v = hmac(k || v) + }; + const gen = () => { // HMAC-DRBG generate() function + if (i++ >= 1000) err(); + v = h(); // v = hmac(k || v) + return v; + }; + reseed(seed); + let sig: Signature | undefined = undefined; // Steps D-G + while (!(sig = kmd2sig(gen(), m, d, lowS))) reseed(); // Step H: grind until k is in [1..n-1] + return sig; +}; +const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { + return hmacDrbgA(...prepSig(msgh, priv, opts)); +}; +const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { // Synchronous version of sign + return hmacDrbgS(...prepSig(msgh, priv, opts)); +}; +const verify = (sig: Hex | Signature, msgh: Hex, pub: Hex, opts = vstdo): boolean => { + let { lowS } = opts; // ECDSA signature verification + if (lowS == null) lowS = true; // Default lowS=true + if ('strict' in opts) err('l'); // legacy param + let sig_: Signature, h: bigint, P: Point; // section 4.1.4 from secg.org/sec1-v2.pdf + try { sig_ = sig instanceof Signature ? sig.ok() : Signature.fromCompact(sig); - } catch (error) { return false; } // R = U1⋅G - U2⋅P, mod(R.x, n) == r + h = truncH(toU8(msgh, fLen)); // Truncate hash + P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key + } catch (e) { return false; } // Check sig for validity in both cases if (!sig_) return false; const { r, s } = sig_; - if (opts?.lowS && moreThanHalf(s)) return false; // lowS=true bans sig.s >= CURVE.n/2 - const h = truncH(toU8(msgh, fLen)); // truncate hash - let P: Point; - try { // Validate public key - P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); - } catch (error) { return false; } - let R: { x: bigint, y: bigint } | undefined = undefined; + if (lowS && moreThanHalfN(s)) return false; // lowS bans sig.s >= CURVE.n/2 + let R: AffinePoint; try { const is = inv(s, N); // s^-1 const u1 = mod(h * is, N); // u1 = hs^-1 mod n @@ -334,26 +363,31 @@ const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compli const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); }; -const utils = { // utilities +const ut = { // utilities mod, invert: inv, // math utilities - concatBytes: concat, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, - randomBytes, hashToPrivateKey, // CSPRNG etc. - randomPrivateKey: (): Bytes => hashToPrivateKey(randomBytes(fLen + 8)), // FIPS 186 B.4.1. - isValidPrivateKey: (key: Hex) => { // checks if private key is valid - try { - return !!toPriv(key); - } catch (e) { - return false; - } + concatBytes: concatB, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, + randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) + return cr.web ? cr.web.getRandomValues(u8a(len)) : + cr.node ? u8fr(cr.node.randomBytes(len)) : err('c'); // throw when unavailable }, + hashToPrivateKey, + hmacSha256Sync: _hmacSync, // undefined by default + randomPrivateKey: (): Bytes => hashToPrivateKey(ut.randomBytes(fLen + 8)), // FIPS 186 B.4.1. + isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, }; +Object.defineProperties(ut, { + hmacSha256Sync: { + configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, + }, +}); const W = 8; // Precomputes-related code. W = window size const precompute = () => { // They give 12x faster getPublicKey(), - const points: Point[] = [], wins = 256 / W + 1; // 10x sign(), 2x verify(). To achieve this, - let p = G, b = p; // app needs to spend 40ms+ to calculate - for (let w = 0; w < wins; w++) { // 65536 points related to base point G - b = p; // Points are stored in array and used - points.push(b); // any time Gx multiplication is done. + const points: Point[] = []; // 10x sign(), 2x verify(). To achieve this, + const windows = 256 / W + 1; // app needs to spend 40ms+ to calculate + let p = G, b = p; // 65536 points related to base point G + for (let w = 0; w < windows; w++) { // Points are stored in array and used + b = p; // any time Gx multiplication is done. + points.push(b); // They consume 16-32 MiB of RAM. for (let i = 1; i < 2 ** (W - 1); i++) { b = b.add(p); points.push(b); } p = b.dbl(); // Precomputes do not speed-up getSharedKey, } // which multiplies user point by scalar, @@ -361,16 +395,14 @@ const precompute = () => { // They give 12x faster } const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method if (256 % W) err(); // Compared to other point mult methods, - let comp = Gprec; // allows to store 2x less points by - if (!comp) err(); // using subtraction. - comp = comp!; + const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction let p = I, f = G; // f must be G, or could become I in the end - const wins = 1 + 256 / W; // W=8 17 windows + const windows = 1 + 256 / W; // W=8 17 windows const wsize = 2 ** (W - 1); // W=8 128 window size const mask = BigInt(2 ** W - 1); // W=8 will create mask 0b11111111 const maxNum = 2 ** W; // W=8 256 const shiftBy = BigInt(W); // W=8 8 - for (let w = 0; w < wins; w++) { + for (let w = 0; w < windows; w++) { const off = w * wsize; let wbits = Number(n & mask); // extract W bits. n >>= shiftBy; // shift number by W bits. @@ -385,6 +417,7 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo } } return { p, f } // return both real and fake points for JIT -}; -Gprec = precompute(); // <= you can disable precomputes by commenting-out the line -export { getPublicKey, sign, verify, getSharedSecret, CURVE, Point, Signature, utils }; +}; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() +export const JPoint = Point; +export const utils = ut; +export { getPublicKey, sign, signSync, verify, getSharedSecret, CURVE, Signature }; diff --git a/package.json b/package.json index c611e0d..675cc35 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "test": "jest", "coverage": "jest --coverage", "bench": "node test/benchmark.js", - "min": "terser --ecma 2020 -m -c < lib/esm/index.js" + "min": "terser --ecma 2020 -m -c < lib/esm/index.js", + "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts`LOC\"" }, "author": "Paul Miller (https://paulmillr.com)", "homepage": "https://paulmillr.com/noble/", diff --git a/test/benchmark.js b/test/benchmark.js index c01f204..fb14de0 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -7,6 +7,7 @@ const points = require('fs') .filter((a) => a) .slice(0, 1000); run(async () => { + secp.getPublicKey(secp.utils.randomPrivateKey(), true); // warmup await mark('getPublicKey(utils.randomPrivateKey())', 5000, () => { secp.getPublicKey(secp.utils.randomPrivateKey(), true); }); diff --git a/test/index.ts b/test/index.ts index 084fca6..39fab64 100644 --- a/test/index.ts +++ b/test/index.ts @@ -24,11 +24,17 @@ const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyz const toBEHex = (n: number | bigint) => n.toString(16).padStart(64, '0'); const hex = secp.utils.bytesToHex; const hexToBytes = secp.utils.hexToBytes; +const Point = secp.JPoint; // const { Signature } = secp; const { bytesToNumber: b2n, hexToBytes: h2b } = secp.utils; -const DER = { // asn.1 DER encoding utils - Err: class DERErr extends Error { constructor(m = '') { super(m); } }, +const DER = { + // asn.1 DER encoding utils + Err: class DERErr extends Error { + constructor(m = '') { + super(m); + } + }, _parseInt(data: Uint8Array): { d: bigint; l: Uint8Array } { const { Err: E } = DER; if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag'); @@ -38,11 +44,12 @@ const DER = { // asn.1 DER encoding utils if (res[0] === 0x00 && res[1] <= 0x7f) throw new E('Invalid signature integer: trailing length'); // ^ Weird condition: not about length, but about first bytes of number. - return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left + return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left }, - toSig(hex: string) { // parse DER signature + toSig(hex: string) { + // parse DER signature const { Err: E } = DER; - const data = typeof(hex) === 'string' ? secp.utils.hexToBytes(hex) : hex; + const data = typeof hex === 'string' ? secp.utils.hexToBytes(hex) : hex; let l = data.length; if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); @@ -52,16 +59,20 @@ const DER = { // asn.1 DER encoding utils return new secp.Signature(r, s); }, fromSig(sig: secp.Signature): Uint8Array { - return h2b(DER.hexFromSig(sig)) + return h2b(DER.hexFromSig(sig)); }, hexFromSig(sig: secp.Signature): string { - const slice = (s: string): string => Number.parseInt(s[0], 16) >= 8 ? '00' + s : s; // slice DER + const slice = (s: string): string => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER const h = (num: number | bigint) => { - const hex = num.toString(16); return hex.length & 1 ? `0${hex}` : hex; + const hex = num.toString(16); + return hex.length & 1 ? `0${hex}` : hex; }; - const s = slice(h(sig.s)), r = slice(h(sig.r)); - const shl = s.length / 2, rhl = r.length / 2; - const sl = h(shl), rl = h(rhl); + const s = slice(h(sig.s)), + r = slice(h(sig.r)); + const shl = s.length / 2, + rhl = r.length / 2; + const sl = h(shl), + rl = h(rhl); return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; }, }; @@ -81,15 +92,15 @@ describe('secp256k1', () => { .filter((line) => line) .map((line) => line.split(':')); for (let [priv, x, y] of data) { - const { x: x1, y: y1 } = secp.Point.fromPrivateKey(BigInt(priv)).aff(); + const { x: x1, y: y1 } = Point.fromPrivateKey(BigInt(priv)).aff(); expect(toBEHex(x1)).toBe(x); expect(toBEHex(y1)).toBe(y); - const { x: x2, y: y2 } = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))).aff(); + const { x: x2, y: y2 } = Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))).aff(); expect(toBEHex(x2)).toBe(x); expect(toBEHex(y2)).toBe(y); - const { x: x3, y: y3 } = secp.Point.fromHex( + const { x: x3, y: y3 } = Point.fromHex( secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv)))) ).aff(); expect(toBEHex(x3)).toBe(x); @@ -126,9 +137,9 @@ describe('secp256k1', () => { for (const vector of points.valid.isPoint) { const { P, expected } = vector; if (expected) { - secp.Point.fromHex(P); + Point.fromHex(P); } else { - expect(() => secp.Point.fromHex(P)).toThrowError(); + expect(() => Point.fromHex(P)).toThrowError(); } } }); @@ -136,7 +147,7 @@ describe('secp256k1', () => { it('.fromPrivateKey()', () => { for (const vector of points.valid.pointFromScalar) { const { d, expected } = vector; - let p = secp.Point.fromPrivateKey(d); + let p = Point.fromPrivateKey(d); expect(p.toHex(true)).toBe(expected); } }); @@ -144,7 +155,7 @@ describe('secp256k1', () => { it('#toHex(compressed)', () => { for (const vector of points.valid.pointCompress) { const { P, compress, expected } = vector; - let p = secp.Point.fromHex(P); + let p = Point.fromHex(P); expect(p.toHex(compress)).toBe(expected); } }); @@ -152,9 +163,9 @@ describe('secp256k1', () => { it('#toHex() roundtrip', () => { fc.assert( fc.property(FC_BIGINT, (x) => { - const point1 = secp.Point.fromPrivateKey(x); + const point1 = Point.fromPrivateKey(x); const hex = point1.toHex(true); - expect(secp.Point.fromHex(hex).toHex(true)).toBe(hex); + expect(Point.fromHex(hex).toHex(true)).toBe(hex); }) ); }); @@ -162,13 +173,13 @@ describe('secp256k1', () => { it('#add(other)', () => { for (const vector of points.valid.pointAdd) { const { P, Q, expected } = vector; - let p = secp.Point.fromHex(P); - let q = secp.Point.fromHex(Q); + let p = Point.fromHex(P); + let q = Point.fromHex(Q); if (expected) { expect(p.add(q).toHex(true)).toBe(expected); } else { if (p.eql(q.neg())) { - expect(p.add(q).toHex(true)).toBe(secp.Point.I.toHex(true)); + expect(p.add(q).toHex(true)).toBe(Point.I.toHex(true)); } else { expect(() => p.add(q).toHex(true)).toThrowError(); } @@ -179,7 +190,7 @@ describe('secp256k1', () => { it('#multiply(privateKey)', () => { for (const vector of points.valid.pointMultiply) { const { P, d, expected } = vector; - const p = secp.Point.fromHex(P); + const p = Point.fromHex(P); if (expected) { expect(p.mul(hexToNumber(d)).toHex(true)).toBe(expected); } else { @@ -193,14 +204,14 @@ describe('secp256k1', () => { const { P, d } = vector; if (hexToNumber(d) < secp.CURVE.n) { expect(() => { - const p = secp.Point.fromHex(P); + const p = Point.fromHex(P); p.mul(hexToNumber(d)).toHex(true); }).toThrowError(); } } for (const num of [0n, 0, -1n, -1, 1.1]) { // @ts-ignore - expect(() => secp.Point.BASE.multiply(num)).toThrowError(); + expect(() => Point.G.multiply(num)).toThrowError(); } }); @@ -227,20 +238,20 @@ describe('secp256k1', () => { ); }); - // it('.fromDERHex() roundtrip', () => { - // fc.assert( - // fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { - // const sig = new secp.Signature(r, s); - // expect(secp.Signature.fromDER(sig.toDERHex())).toEqual(sig); - // }) - // ); - // }); + it('.fromDERHex() roundtrip', () => { + fc.assert( + fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { + const sig = new secp.Signature(r, s); + expect(DER.toSig(DER.hexFromSig(sig))).toEqual(sig); + }) + ); + }); }); describe('.sign()', () => { it('should create deterministic signatures with RFC 6979', async () => { for (const vector of ecdsa.valid) { - let usig = await secp.sign(vector.m, vector.d, { der: false }); + let usig = await secp.sign(vector.m, vector.d); let sig = usig.toCompactHex(); const vsig = vector.signature; expect(sig.slice(0, 64)).toBe(vsig.slice(0, 64)); @@ -251,7 +262,7 @@ describe('secp256k1', () => { it('should not create invalid deterministic signatures with RFC 6979', async () => { for (const vector of ecdsa.invalid.sign) { expect(() => { - return secp.sign(vector.m, vector.d, { der: false }); + return secp.sign(vector.m, vector.d); }).rejects.toThrowError(); } }); @@ -263,51 +274,52 @@ describe('secp256k1', () => { expect(async () => await secp.sign('')).rejects.toThrowError(); }); - // it('should create correct DER encoding against libsecp256k1', async () => { - // const CASES = [ - // [ - // 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', - // '304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b', - // ], - // [ - // '5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82', - // '3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c', - // ], - // [ - // '0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808', - // '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', - // ], - // ]; - // const privKey = hexToBytes( - // '0101010101010101010101010101010101010101010101010101010101010101' - // ); - // for (let [msg, exp] of CASES) { - // const res = await secp.sign(msg, privKey, { extraEntropy: undefined }); - // expect(hex(res)).toBe(exp); - // const rs = secp.Signature.fromDER(res).toCompactHex(); - // expect(secp.Signature.fromCompact(rs).toDERHex()).toBe(exp); - // } - // }); - // it('sign ecdsa extraData', async () => { - // const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; - // const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; - // const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; - // const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; - // const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - - // for (const e of ecdsa.extraEntropy) { - // const sign = async (extraEntropy?: string) => { - // const s = await secp.sign(e.m, e.d, { der: false, extraEntropy }); - // return s.toCompactHex(); - // }; - // expect(await sign()).toBe(e.signature); - // expect(await sign(ent1)).toBe(e.extraEntropy0); - // expect(await sign(ent2)).toBe(e.extraEntropy1); - // expect(await sign(ent3)).toBe(e.extraEntropyRand); - // expect(await sign(ent4)).toBe(e.extraEntropyN); - // expect(await sign(ent5)).toBe(e.extraEntropyMax); - // } - // }); + it('should create correct DER encoding against libsecp256k1', async () => { + const CASES = [ + [ + 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', + '304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b', + ], + [ + '5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82', + '3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c', + ], + [ + '0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808', + '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', + ], + ]; + const privKey = hexToBytes( + '0101010101010101010101010101010101010101010101010101010101010101' + ); + for (let [msg, exp] of CASES) { + const res = await secp.sign(msg, privKey, { extraEntropy: undefined }); + const derRes = DER.hexFromSig(res); + expect(derRes).toBe(exp); + const derRes2 = DER.toSig(derRes); + expect(DER.hexFromSig(derRes2)).toBe(exp); + } + }); + it('sign ecdsa extraData', async () => { + const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; + const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; + const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; + const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; + const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; + + for (const e of ecdsa.extraEntropy) { + const sign = async (extraEntropy?: string) => { + const s = await secp.sign(e.m, e.d, { extraEntropy }); + return s.toCompactHex(); + }; + expect(await sign()).toBe(e.signature); + expect(await sign(ent1)).toBe(e.extraEntropy0); + expect(await sign(ent2)).toBe(e.extraEntropy1); + expect(await sign(ent3)).toBe(e.extraEntropyRand); + expect(await sign(ent4)).toBe(e.extraEntropyN); + expect(await sign(ent5)).toBe(e.extraEntropyMax); + } + }); }); describe('.verify()', () => { @@ -324,7 +336,7 @@ describe('secp256k1', () => { const PRIV_KEY = secp.utils.numToField(0x2n); const WRONG_PRIV_KEY = secp.utils.numToField(0x22n); const signature = await secp.sign(MSG, PRIV_KEY); - const publicKey = secp.Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); + const publicKey = Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); expect(publicKey.length).toBe(130); expect(secp.verify(signature, MSG, publicKey)).toBe(false); }); @@ -361,7 +373,7 @@ describe('secp256k1', () => { const r = 1n; const s = 115792089237316195423570985008687907852837564279074904382605163141518162728904n; - const pub = new secp.Point(x, y); + const pub = new Point(x, y); const signature = new secp.Signature(2n, 2n); // @ts-ignore signature.r = r; @@ -378,7 +390,7 @@ describe('secp256k1', () => { const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; const r = 104546003225722045112039007203142344920046999340768276760147352389092131869133n; const s = 96900796730960181123786672629079577025401317267213807243199432755332205217369n; - const pub = new secp.Point(x, y).toRawBytes(); + const pub = new Point(x, y).toRawBytes(); const sig = new secp.Signature(r, s); expect(secp.verify(sig, msg, pub)).toBeFalsy(); }); @@ -388,7 +400,7 @@ describe('secp256k1', () => { const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n; const r = 432420386565659656852420866390673177323n; const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n; - const pub = new secp.Point(x, y).toRawBytes(); + const pub = new Point(x, y).toRawBytes(); const sig = new secp.Signature(r, s); expect(secp.verify(sig, msg, pub, { lowS: false })).toBeTruthy(); }); @@ -436,7 +448,7 @@ describe('secp256k1', () => { it('should recover public key from recovery bit', async () => { const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; const privateKey = secp.utils.numToField(123456789n); - const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); + const publicKey = Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); const sig = await secp.sign(message, privateKey); const recoveredPubkey = sig.recoverPublicKey(message); expect(recoveredPubkey).not.toBe(null); @@ -534,16 +546,16 @@ describe('secp256k1', () => { }, pointAddScalar: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { - const P = secp.Point.fromHex(p); + const P = Point.fromHex(p); const t = normal(tweak); - const Q = P.add(secp.Point.G.mul(t)); - // const Q = secp.Point.BASE.multiplyAndAddUnsafe(P, t, 1n); - if (!Q || Q.eql(secp.Point.I)) throw new Error('Tweaked point at infinity'); + const Q = P.add(Point.G.mul(t)); + // const Q = Point.G.multiplyAndAddUnsafe(P, t, 1n); + if (!Q || Q.eql(Point.I)) throw new Error('Tweaked point at infinity'); return Q.toRawBytes(isCompressed); }, pointMultiply: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { - const P = secp.Point.fromHex(p); + const P = Point.fromHex(p); const h = typeof tweak === 'string' ? tweak : secp.utils.bytesToHex(tweak); const t = BigInt(`0x${h}`); return P.mul(t).toRawBytes(isCompressed); @@ -592,20 +604,18 @@ describe('secp256k1', () => { }); describe('wychenproof vectors', () => { - const sha256 = (m: Uint8Array) => Uint8Array.from(createHash('sha256').update(m).digest()) + const sha256 = (m: Uint8Array) => Uint8Array.from(createHash('sha256').update(m).digest()); it('should pass all tests', async () => { for (let group of wp.testGroups) { - const pubKey = secp.Point.fromHex(group.key.uncompressed); + const pubKey = Point.fromHex(group.key.uncompressed); for (let test of group.tests) { const m = sha256(hexToBytes(test.msg)); if (test.result === 'valid' || test.result === 'acceptable') { const parsed = DER.toSig(test.sig); const verified = secp.verify(parsed, m, group.key.uncompressed); - if (parsed.s > (secp.CURVE.n >> 1n)) { + if (parsed.s > secp.CURVE.n >> 1n) { expect(verified).toBeFalsy(); } else { - console.log('verified', test); - expect(verified).toBeTruthy(); } } else if (test.result === 'invalid') { @@ -627,8 +637,8 @@ describe('secp256k1', () => { }); // describe('JacobianPoint', () => { -// const JZERO = secp.utils._JacobianPoint.ZERO; -// const AZERO = secp.utils._JacobianPoint.fromAffine(secp.Point.ZERO); +// const JZERO = Point.I; +// const AZERO = { x: 0n, y: 0n }; // expect(AZERO.equals(JZERO)).toBeTruthy(); // expect(AZERO.toAffine().equals(JZERO.toAffine())).toBeTruthy(); // }); From 5f9abe6dab9eee353b82acf647948c8ab9c1ccce Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 01:47:01 +0000 Subject: [PATCH 020/145] Make default points compressed. Ban DER. Iteration 9: 8111, 424LOC --- index.ts | 157 +++++++++++++++++++++++----------------------- package.json | 6 +- test/benchmark.js | 2 +- test/index.ts | 10 +-- 4 files changed, 87 insertions(+), 88 deletions(-) diff --git a/index.ts b/index.ts index b42d521..b3ae421 100644 --- a/index.ts +++ b/index.ts @@ -1,6 +1,6 @@ /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve -const P = B256 - 2n ** 32n - 977n; // curve's field +const P = B256 - 0x1000003d1n; // curve's field const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order const a = 0n; // a equation's param const b = 7n; // b equation's param @@ -10,22 +10,22 @@ const CURVE = { P, n: N, a, b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; // accepted inputs: bytes/hex const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula -const errs = {'':'', l: 'legacy', h: 'no sync hmac', i: 'no inv', c: 'no CSPRNG/hmac', t: 'type'}; +const errs = {'':'', l: 'legacy', h: 'no sync hmac', i: 'no inv', c: 'no CSPRNG/hmac', d: 'no DER'}; const err = (m: keyof typeof errs = '', sfx = ''): never => { throw new Error(errs[m]+sfx); }; const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: any): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const u8a = (content?: any) => new Uint8Array(content); // creates Uint8Array -const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut -const isU8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) +const u8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err() : a; -const toU8 = (a: any, len?: number) => isU8(str(a) ? h2b(a) : a, len); // (hex or ui8a) to ui8a -const toPriv = (p: Hex | bigint): bigint => { // normalize private key +const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array +const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut +const toU8 = (a: any, len?: number) => u8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a +const toPriv = (p: Hex | bigint): bigint => { // normalize private key to bigint if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err(); // check if bigint is in range }; -let Gpows: Point[] | undefined = undefined; // Precomputes for base point G +let Gpows: Point[] | undefined = undefined; // precomputes for base point G interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords const isPoint = (p: any) => (p instanceof Point ? p : err()); // is 3d point class Point { // Point in 3d xyz projective coords @@ -85,11 +85,9 @@ class Point { // Point in 3d xyz proje return { x: mod(x * iz), y: mod(y * iz) }; // x = x*z^-1; y = y*z^-1 } ok(): Point { // checks if the point is valid and on-curve - const { x, y } = this.aff(); // convert to 2d xy affine point + const { x, y } = this.aff(); // convert to 2d xy affine point. if (!fe(x) || !fe(y)) err(); // x and y must be in range 0 < n < P - const l = mod(y * y); // y² - const r = crv(x); // x³ + ax + b - return mod(l - r) === 0n ? this : err(); // y² = x³ + ax + b, must be equal + return mod(y * y) === crv(x) ? this : err(); // y² = x³ + ax + b, must be equal } static fromHex(hex: Hex): Point { // convert Uint8Array or hex string to Point hex = toU8(hex); // converts hex string to Uint8Array @@ -107,12 +105,12 @@ class Point { // Point in 3d xyz proje if (len === 65 && head === 0x04) p = new Point(x, slcNum(tail, fLen, 2 * fLen)); return p ? p.ok() : err(); // Check if the result is valid / on-curve } - toHex(isCompressed = false) { // Converts point to hex string + toHex(isCompressed = true) { // Converts point to hex string const { x, y } = this.aff(); // Convert to 2d xy affine point const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; // 0x02, 0x03, 0x04 prefix return `${head}${n2h(x)}${isCompressed ? '' : n2h(y)}`; // prefix||x and ||y } - toRawBytes(isCompressed = false) { // Converts point to Uint8Array + toRawBytes(isCompressed = true) { // Converts point to Uint8Array return h2b(this.toHex(isCompressed)); // Re-use toHex(), convert hex to bytes } static fromPrivateKey(n: bigint | Hex) { // Create point from a private key. Multiply @@ -129,7 +127,7 @@ const inv = (num: bigint, md = P): bigint => { // modular inversion const m = x - u * q, n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } - return b === 1n ? mod(x, md) : err('i'); // b is gcd at this point + return b === 1n ? mod(x, md) : err('i'); // b is gcd at this point }; const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiation num^e if (md <= 0n || e < 0n) err(); // exponentiation by squaring @@ -151,7 +149,7 @@ const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); / const h2b = (hex: string): Bytes => { // hex to bytes const l = hex.length; // error if not string, if (!str(hex) || l % 2) err(); // or has odd length like 3, 5. - const arr = u8a(l / 2); // create result array + const arr = u8n(l / 2); // create result array for (let i = 0; i < arr.length; i++) { const j = i * 2; const h = hex.slice(j, j + 2); // hexByte. slice is faster than substr @@ -167,11 +165,11 @@ const n2b = (num: bigint): Bytes => { // number to bytes. must return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err(); }; const n2h = (num: bigint): string => b2h(n2b(num)); // number to hex -const concatB = (...list: Bytes[]) => { // concatenate Uint8Array-s - let pad = 0; - const res = u8a(list.reduce((sum, arr) => sum + arr.length, 0)); - list.forEach(arr => { res.set(isU8(arr), pad); pad += arr.length; }); - return res; +const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Array-s + const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length + let pad = 0; // walk through each array, ensure + arrs.forEach(a => { r.set(u8(a), pad); pad += a.length }); // they have proper type + return r; }; const b2n_2 = (bytes: Bytes) => { // bytes to bigint @@ -185,18 +183,18 @@ const truncH = (hash: Bytes): bigint => { // truncate hash }; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 -const getPublicKey = (privKey: Hex | bigint, isCompressed = false) => { // calculate public +const getPublicKey = (privKey: Hex | bigint, isCompressed = true) => { // calculate public return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; class Signature { // calculates signature - constructor(readonly r: bigint, readonly s: bigint, readonly rec?: number) { this.ok(); } + constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { this.ok(); } ok(): Signature { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n static fromCompact(hex: Hex) { // create signature from 64b compact repr hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery - const { r, s, rec } = this; // section 4.1.6 of secg.org/sec1-v2.pdf + const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 if (rec == null || ![0, 1, 2, 3].includes(rec)) err(); // also can just grind through all values const h = truncH(toU8(msgh)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n @@ -212,7 +210,7 @@ class Signature { // calculates signature toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr } const b2i = (b: Bytes): bigint => { // RFC6979 bytes to int - isU8(b); + u8(b); const sl = b.length > fLen ? b.slice(0, fLen) : b; // slice return b2n(sl); // call our own method }; @@ -227,18 +225,6 @@ const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependen node: typeof require === 'function' && require('crypto'), // node.js require('crypto') web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, // browser-only var }; -const hmac = async (key: Bytes, ...msgs: Bytes[]): Promise => { - const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! - if (cr.web) { // browser built-in version - const s = cr.web.subtle; - const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); - return u8a(await s.sign('HMAC', k, m)); - } else if (cr.node) { // node.js built-in version - return u8fr(cr.node.createHmac('sha256', key).update(m).digest()); - } else { - return err('c'); - } -}; type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it const stdo: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() @@ -253,7 +239,7 @@ const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC const seed = [i2o(d), b2o(h1)]; // Step D of RFC6979 3.2 let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - if (ent === true) ent = utils.randomBytes(fLen); // if true, use CSPRNG to generate data + if (ent === true) ent = ut.randomBytes(fLen); // if true, use CSPRNG to generate data const e = toU8(ent); // convert Hex|Bytes to Bytes if (e.length !== fLen) err(); // Expected 32 bytes of extra data seed.push(e); @@ -262,28 +248,28 @@ const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC return [concatB(...seed), m, d, low]; }; const kmd2sig = (kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined => { - const k = b2n_2(kBytes); // Utility method for RFC6979 k generation - if (!ge(k)) return; // Check 0 < k < CURVE.n - const ik = inv(k, N); // k^-1 mod n, NOT mod P - const q = G.mul(k).aff(); // q = Gk - const r = mod(q.x, N); // r = q.x mod n - if (r === 0n) return; // invalid - const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1 * m + dr mod n - if (s === 0n) return; // invalid - let normS = s; // normalized s - let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit - if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always - normS = mod(-s, N); // in the bottom half of CURVE.n + const k = b2n_2(kBytes); // Utility method for RFC6979 k generation + if (!ge(k)) return; // Check 0 < k < CURVE.n + const ik = inv(k, N); // k^-1 mod n, NOT mod P + const q = G.mul(k).aff(); // q = Gk + const r = mod(q.x, N); // r = q.x mod n + if (r === 0n) return; // r=0 invalid + const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1(m + rd) mod n + if (s === 0n) return; // s=0 invalid + let normS = s; + let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit + if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always + normS = mod(-s, N); // in the bottom half of CURVE.n rec ^= 1; } - return new Signature(r, normS, rec); + return new Signature(r, normS, rec); // use normS, not s }; const hmacDrbgA = async (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMAC-DRBG async - let v = u8a(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8a(fLen).fill(0); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same + let v = u8n(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(fLen).fill(0); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same let i = 0; // Iterations counter, will throw when over 1000 - const h = (...b: Bytes[]) => hmac(k, v, ...b); // hmac(k)(v, ...values) - const reseed = async (seed = u8a()) => { // HMAC-DRBG reseed() function. Steps D-G + const h = (...b: Bytes[]) => ut.hmacSha256(k, v, ...b); // hmac(k)(v, ...values) + const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) v = await h(); // v = hmac(K || V) if (seed.length === 0) return; @@ -292,7 +278,7 @@ const hmacDrbgA = async (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { }; const gen = async () => { // HMAC-DRBG generate() function if (i++ >= 1000) err(); - v = await hmac(k, v); // v = hmac(K || V) + v = await h(); // v = hmac(K || V) return v; }; await reseed(seed); // Steps D-G @@ -301,12 +287,12 @@ const hmacDrbgA = async (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { return sig; }; const hmacDrbgS = (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMAC-DRBG sync - let v = u8a(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8a(fLen).fill(0); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let v = u8n(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(fLen).fill(0); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same let i = 0; // Iterations counter, will throw when over 1000 if (!_hmacSync) err('h'); const h = (...b: Bytes[]) => _hmacSync!(k, v, ...b); // hmac(k)(v, ...values) - const reseed = (seed = u8a()) => { // HMAC-DRBG reseed() function. Steps D-G + const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) v = h(); // v = hmac(k || v) if (seed.length === 0) return; @@ -324,18 +310,21 @@ const hmacDrbgS = (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMA return sig; }; const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { - return hmacDrbgA(...prepSig(msgh, priv, opts)); + return hmacDrbgA(...prepSig(msgh, priv, opts)); // ECDSA sig generation secg.org/sec1-v2.pdf 4.1.2 }; -const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { // Synchronous version of sign - return hmacDrbgS(...prepSig(msgh, priv, opts)); +const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { + return hmacDrbgS(...prepSig(msgh, priv, opts)); // Synchronous version of sign() }; +const isInst = (sig: any): sig is Signature => sig instanceof Signature const verify = (sig: Hex | Signature, msgh: Hex, pub: Hex, opts = vstdo): boolean => { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true if ('strict' in opts) err('l'); // legacy param - let sig_: Signature, h: bigint, P: Point; // section 4.1.4 from secg.org/sec1-v2.pdf + let sig_: Signature, h: bigint, P: Point; // secg.org/sec1-v2.pdf 4.1.4 + const inst = isInst(sig); // Previous ver supported DER sigs. We throw + if (!inst && (toU8(sig).length !== 2 * fLen)) err('d'); // error when DER is suspected now. try { - sig_ = sig instanceof Signature ? sig.ok() : Signature.fromCompact(sig); + sig_ = inst ? sig.ok() : Signature.fromCompact(sig); h = truncH(toU8(msgh, fLen)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { return false; } // Check sig for validity in both cases @@ -353,7 +342,7 @@ const verify = (sig: Hex | Signature, msgh: Hex, pub: Hex, opts = vstdo): boolea const v = mod(R.x, N); return v === r; // mod(R.x, n) == r } -const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed?: boolean) => { +const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true) => { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); }; const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation @@ -367,16 +356,28 @@ const ut = { // utilities mod, invert: inv, // math utilities concatBytes: concatB, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) - return cr.web ? cr.web.getRandomValues(u8a(len)) : + return cr.web ? cr.web.getRandomValues(u8n(len)) : cr.node ? u8fr(cr.node.randomBytes(len)) : err('c'); // throw when unavailable }, hashToPrivateKey, + hmacSha256: async (key: Bytes, ...msgs: Bytes[]): Promise => { + const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! + if (cr.web) { // browser built-in version + const s = cr.web.subtle; + const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); + return u8n(await s.sign('HMAC', k, m)); + } else if (cr.node) { // node.js built-in version + return u8fr(cr.node.createHmac('sha256', key).update(m).digest()); + } else { + return err('c'); + } + }, hmacSha256Sync: _hmacSync, // undefined by default randomPrivateKey: (): Bytes => hashToPrivateKey(ut.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, }; -Object.defineProperties(ut, { - hmacSha256Sync: { +Object.defineProperties(ut, { // Allow setting the function only once. + hmacSha256Sync: { // Next tries will silently fail. configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, }, }); @@ -384,18 +385,19 @@ const W = 8; // Precomputes-related c const precompute = () => { // They give 12x faster getPublicKey(), const points: Point[] = []; // 10x sign(), 2x verify(). To achieve this, const windows = 256 / W + 1; // app needs to spend 40ms+ to calculate - let p = G, b = p; // 65536 points related to base point G + let p = G, b = p; // 65536 points related to base point G. for (let w = 0; w < windows; w++) { // Points are stored in array and used b = p; // any time Gx multiplication is done. points.push(b); // They consume 16-32 MiB of RAM. for (let i = 1; i < 2 ** (W - 1); i++) { b = b.add(p); points.push(b); } - p = b.dbl(); // Precomputes do not speed-up getSharedKey, + p = b.dbl(); // Precomputes don't speed-up getSharedKey, } // which multiplies user point by scalar, return points; // when precomputes are using base point } const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method if (256 % W) err(); // Compared to other point mult methods, const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction + const neg = (cnd: boolean, p: Point) => { let n = p.neg(); return cnd ? n : p; } // negate let p = I, f = G; // f must be G, or could become I in the end const windows = 1 + 256 / W; // W=8 17 windows const wsize = 2 ** (W - 1); // W=8 128 window size @@ -406,18 +408,17 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo const off = w * wsize; let wbits = Number(n & mask); // extract W bits. n >>= shiftBy; // shift number by W bits. - if (wbits > wsize) { wbits -= maxNum; n += 1n; } // split if bits>max: +224 => 256-32 - const off1 = off, off2 = off + Math.abs(wbits) - 1; // offsets - const cond1 = w % 2 !== 0, cond2 = wbits < 0; // conditions - const neg = (bool: boolean, item: Point) => bool ? item.neg() : item; // negate + if (wbits > wsize) { wbits -= maxNum; n += 1n; } // split if bits > max: +224 => 256-32 + const off1 = off, off2 = off + Math.abs(wbits) - 1; // offsets, evaluate both + const cnd1 = w % 2 !== 0, cnd2 = wbits < 0; // conditions, evaluate both if (wbits === 0) { - f = f.add(neg(cond1, comp[off1])); // bit is 0: add garbage to fake point - } else { - p = p.add(neg(cond2, comp[off2])); // bit is 1: add to result point + f = f.add(neg(cnd1, comp[off1])); // bits are 0: add garbage to fake point + } else { // ^ can't add off2, off2 = I + p = p.add(neg(cnd2, comp[off2])); // bits are 1: add to result point } } return { p, f } // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() -export const JPoint = Point; +export const PPoint = Point; export const utils = ut; export { getPublicKey, sign, signSync, verify, getSharedSecret, CURVE, Signature }; diff --git a/package.json b/package.json index 675cc35..6640c2b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", - "version": "1.7.1", - "description": "Fastest JS implementation of secp256k1. Independently audited, high-security, 0-dependency ECDSA & Schnorr signatures", + "version": "2.0.0-pre", + "description": "Fastest JS implementation of secp256k1. Independently audited, high-security, 0-dependency ECDSA signatures", "files": [ "lib" ], @@ -54,12 +54,10 @@ "signature", "ecc", "rfc6979", - "schnorr", "sig", "bip0340", "bip340", "ecdsa", - "endomorphism", "cryptography", "security", "noble" diff --git a/test/benchmark.js b/test/benchmark.js index fb14de0..3e84679 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -23,5 +23,5 @@ run(async () => { await mark('recoverPublicKey', 500, () => signature.recoverPublicKey(msg)); let i = 0; let len = points.length; - await mark('Point.fromHex (decompression)', 10000, () => secp.Point.fromHex(points[i++ % len])); + await mark('Point.fromHex (decompression)', 10000, () => secp.PPoint.fromHex(points[i++ % len])); }); diff --git a/test/index.ts b/test/index.ts index 39fab64..e5a9f84 100644 --- a/test/index.ts +++ b/test/index.ts @@ -24,7 +24,7 @@ const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyz const toBEHex = (n: number | bigint) => n.toString(16).padStart(64, '0'); const hex = secp.utils.bytesToHex; const hexToBytes = secp.utils.hexToBytes; -const Point = secp.JPoint; +const Point = secp.PPoint; // const { Signature } = secp; const { bytesToNumber: b2n, hexToBytes: h2b } = secp.utils; @@ -328,7 +328,7 @@ describe('secp256k1', () => { const PRIV_KEY = secp.utils.numToField(0x2n); const signature = await secp.sign(MSG, PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY); - expect(publicKey.length).toBe(65); + expect(publicKey.length).toBe(33); expect(secp.verify(signature, MSG, publicKey)).toBe(true); }); it('should not verify signature with wrong public key', async () => { @@ -337,7 +337,7 @@ describe('secp256k1', () => { const WRONG_PRIV_KEY = secp.utils.numToField(0x22n); const signature = await secp.sign(MSG, PRIV_KEY); const publicKey = Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); - expect(publicKey.length).toBe(130); + expect(publicKey.length).toBe(66); expect(secp.verify(signature, MSG, publicKey)).toBe(false); }); it('should not verify signature with wrong hash', async () => { @@ -346,7 +346,7 @@ describe('secp256k1', () => { const WRONG_MSG = '11'.repeat(32); const signature = await secp.sign(MSG, PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY); - expect(publicKey.length).toBe(65); + expect(publicKey.length).toBe(33); expect(secp.verify(signature, WRONG_MSG, publicKey)).toBe(false); }); it('should verify random signatures', async () => @@ -452,7 +452,7 @@ describe('secp256k1', () => { const sig = await secp.sign(message, privateKey); const recoveredPubkey = sig.recoverPublicKey(message); expect(recoveredPubkey).not.toBe(null); - expect(recoveredPubkey.toHex()).toBe(publicKey); + expect(recoveredPubkey.toHex(false)).toBe(publicKey); expect(secp.verify(sig, message, publicKey)).toBe(true); }); it('should not recover zero points', () => { From bf159a90b2710228b018c687943f41fbbde64d51 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 19:28:27 +0000 Subject: [PATCH 021/145] Update README --- README.md | 191 +++++++++++++++++------------------------------------- 1 file changed, 60 insertions(+), 131 deletions(-) diff --git a/README.md b/README.md index aea7aba..67424bd 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,15 @@ [Fastest](#speed) JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, -ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979 and **Schnorr** signatures from [BIP0340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). +ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. -[**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/) +[**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). + +**2023 update:** version 2 has been released. It features 4x less code and improved security. +Some features have been removed. Use [**noble-curves**](https://github.com/paulmillr/noble-curves) +if you need big, audited & optimized library. Use **noble-secp256k1** if you need +stable, frozen, minimal feature set and smaller attack surface. +Check out [Upgrading](#upgrading) section. ### This library belongs to _noble_ crypto @@ -15,9 +21,9 @@ ECDH key agreement protocol and signature schemes. Supports deterministic **ECDS - Supported in all major browsers and stable node.js versions - All releases are signed with PGP keys - Check out [homepage](https://paulmillr.com/noble/) & all libraries: - [secp256k1](https://github.com/paulmillr/noble-secp256k1), + [curves](https://github.com/paulmillr/noble-curves) ([secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519), - [bls12-381](https://github.com/paulmillr/noble-bls12-381), + [bls12-381](https://github.com/paulmillr/noble-bls12-381)) and [hashes](https://github.com/paulmillr/noble-hashes) ## Usage @@ -38,14 +44,10 @@ import * as secp from '@noble/secp256k1'; // Uint8Array.from([0xde, 0xad, 0xbe, 0xef]) === 'deadbeef' const privKey = secp.utils.randomPrivateKey(); const pubKey = secp.getPublicKey(privKey); - const msgHash = await secp.utils.sha256('hello world'); + // sha256 of 'hello world' + const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; const signature = await secp.sign(msgHash, privKey); const isValid = secp.verify(signature, msgHash, pubKey); - - // Schnorr signatures - const rpub = secp.schnorr.getPublicKey(privKey); - const rsignature = await secp.schnorr.sign(message, privKey); - const risValid = await secp.schnorr.verify(rsignature, message, rpub); })(); ``` @@ -62,24 +64,18 @@ you will need [import map](https://deno.land/manual/linking_to_external_code/imp - [`sign(msgHash, privateKey)`](#signmsghash-privatekey) - [`verify(signature, msgHash, publicKey)`](#verifysignature-msghash-publickey) - [`getSharedSecret(privateKeyA, publicKeyB)`](#getsharedsecretprivatekeya-publickeyb) -- [`recoverPublicKey(hash, signature, recovery)`](#recoverpublickeyhash-signature-recovery) -- [`schnorr.getPublicKey(privateKey)`](#schnorrgetpublickeyprivatekey) -- [`schnorr.sign(message, privateKey)`](#schnorrsignmessage-privatekey) -- [`schnorr.verify(signature, message, publicKey)`](#schnorrverifysignature-message-publickey) +- [`signature.recoverPublicKey(msgHash)`](#recoverpublickeyhash-signature-recovery) - [Utilities](#utilities) ##### `getPublicKey(privateKey)` ```typescript -function getPublicKey(privateKey: Uint8Array | string | bigint, isCompressed = false): Uint8Array; +function getPublicKey(privateKey: Uint8Array | string | bigint, isCompressed = true): Uint8Array; ``` -Creates public key for the corresponding private key. The default is full 65-byte key. - -- `isCompressed = false` determines whether to return compact (33-byte), or full (65-byte) key. - -Internally, it does `Point.BASE.multiply(privateKey)`. If you need actual `Point` instead of -`Uint8Array`, use `Point.fromPrivateKey(privateKey)`. +Creates public key for the corresponding private key. The default is full 33-byte key. +Set second argument to `false` if you need full (65-byte) key. Use `PPoint.fromPrivateKey(privateKey)` +if you need `PPoint` instead of `Uint8Array` ##### `sign(msgHash, privateKey)` @@ -87,13 +83,8 @@ Internally, it does `Point.BASE.multiply(privateKey)`. If you need actual `Point function sign( msgHash: Uint8Array | string, privateKey: Uint8Array | string, - opts?: Options -): Promise; -function sign( - msgHash: Uint8Array | string, - privateKey: Uint8Array | string, - opts?: Options -): Promise<[Uint8Array, number]>; + opts?: { lowS: boolean, extraEntropy: boolean | Hex } +): Promise; ``` Generates low-s deterministic ECDSA signature as per RFC6979. @@ -101,13 +92,10 @@ Generates low-s deterministic ECDSA signature as per RFC6979. - `msgHash: Uint8Array | string` - 32-byte message hash which would be signed - `privateKey: Uint8Array | string | bigint` - private key which will sign the hash - `options?: Options` - _optional_ object related to signature value and format with following keys: - - `recovered: boolean = false` - whether the recovered bit should be included in the result. In this case, the result would be an array of two items. - - `canonical: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. + - `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. `true` (default) makes signatures compatible with libsecp256k1, `false` makes signatures compatible with openssl - - `der: boolean = true` - whether the returned signature should be in DER format. If `false`, it would be in Compact format (32-byte r + 32-byte s) - `extraEntropy: Uint8Array | string | true` - additional entropy `k'` for deterministic signature, follows section 3.6 of RFC6979. When `true`, it would automatically be filled with 32 bytes of cryptographically secure entropy. **Strongly recommended** to pass `true` to improve security: - - Schnorr signatures are doing it every time - It would help a lot in case there is an error somewhere in `k` generation. Exposing `k` could leak private keys - If the entropy generator is broken, signatures would be the same as they are without the option - Signatures with extra entropy would have different `r` / `s`, which means they @@ -120,7 +108,7 @@ The function is asynchronous because we're utilizing built-in HMAC API to not re // Signatures with improved security const signatureE = await secp.sign(msgHash, privKey, { extraEntropy: true }); // Malleable signatures, but compatible with openssl - const signatureM = await secp.sign(msgHash, privKey, { canonical: false }); + const signatureM = await secp.sign(msgHash, privKey, { lowS: false }); })(); ``` @@ -128,8 +116,8 @@ The function is asynchronous because we're utilizing built-in HMAC API to not re function signSync( msgHash: Uint8Array | string, privateKey: Uint8Array | string, - opts?: Options -): Uint8Array | [Uint8Array, number]; + opts?: { lowS: boolean, extraEntropy: boolean | Hex } +): Signature; ``` `signSync` counterpart could also be used, you need to set `utils.hmacSha256Sync` to a function with signature `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array`. Example with `noble-hashes` package: @@ -137,29 +125,26 @@ function signSync( ```ts import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; -secp256k1.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) -secp256k1.utils.sha256Sync = (...msgs) => sha256(secp256k1.utils.concatBytes(...msgs)) -// Can be used now -secp256k1.signSync(msgHash, privateKey); -schnorr.signSync(message, privateKey) +secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) +secp.signSync(msgHash, privateKey); // Can be used now ``` ##### `verify(signature, msgHash, publicKey)` ```typescript function verify( - signature: Uint8Array | string, + signature: Uint8Array | string | Signature, msgHash: Uint8Array | string, - publicKey: Uint8Array | string + publicKey: Uint8Array | string | Point, + opts?: { lowS: boolean } ): boolean; -function verify(signature: Signature, msgHash: Uint8Array | string, publicKey: Point): boolean; ``` - `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function - `msgHash: Uint8Array | string` - message hash that needs to be verified - `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey` - `options?: Options` - _optional_ object related to signature value and format - - `strict: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. + - `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. `true` (default) makes signatures compatible with libsecp256k1, `false` makes signatures compatible with openssl - Returns `boolean`: `true` if `signature == hash`; otherwise `false` @@ -170,87 +155,29 @@ function verify(signature: Signature, msgHash: Uint8Array | string, publicKey: P function getSharedSecret( privateKeyA: Uint8Array | string | bigint, publicKeyB: Uint8Array | string | Point, - isCompressed = false + isCompressed = true ): Uint8Array; ``` Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between a private key and a different public key. - To get Point instance, use `Point.fromHex(publicKeyB).multiply(privateKeyA)` -- `isCompressed = false` determines whether to return compact (33-byte), or full (65-byte) key -- If you have one public key you'll be creating lots of secrets against, - consider massive speed-up by using precomputations: +- `isCompressed = true` determines whether to return compact (33-byte), or full (65-byte) key - ```js - const pub = secp.utils.precompute(8, publicKeyB); - // Use pub everywhere instead of publicKeyB - getSharedSecret(privKey, pub); // Now 12x faster - ``` - -##### `recoverPublicKey(hash, signature, recovery)` +##### `Signature.recoverPublicKey(hash)` ```typescript -function recoverPublicKey( - msgHash: Uint8Array | string, - signature: Uint8Array | string, - recovery: number, - isCompressed = false -): Uint8Array | undefined; +signature.recoverPublicKey(msgHash: Uint8Array | string): Uint8Array | undefined; ``` -Recovers public key from message hash, signature & recovery bit. The default is full 65-byte key. +`Signature` instance method, recovers public key from message hash. - `msgHash: Uint8Array | string` - message hash which would be signed -- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function -- `recovery: number` - recovery bit returned by `sign` with `recovered` option - `isCompressed = false` determines whether to return compact (33-byte), or full (65-byte) key Public key is generated by doing scalar multiplication of a base Point(x, y) by a fixed integer. The result is another `Point(x, y)` which we will by default encode to hex Uint8Array. If signature is invalid - function will return `undefined` as result. -To get Point instance, use `Point.fromSignature(hash, signature, recovery)`. - -##### `schnorr.getPublicKey(privateKey)` - -```typescript -function schnorrGetPublicKey(privateKey: Uint8Array | string): Uint8Array; -``` - -Calculates 32-byte public key from a private key. - -_Warning:_ it is incompatible with non-schnorr pubkey. Specifically, its _y_ coordinate may be flipped. See [BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) for clarification. - -##### `schnorr.sign(message, privateKey)` - -```typescript -function schnorrSign( - message: Uint8Array | string, - privateKey: Uint8Array | string, - auxilaryRandom?: Uint8Array -): Promise; -``` - -Generates Schnorr signature as per BIP0340. Asynchronous, so use `await`. - -- `message: Uint8Array | string` - message (not hash) which would be signed -- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash -- `auxilaryRandom?: Uint8Array` — optional 32 random bytes. By default, the method gathers cryptogarphically secure entropy -- Returns Schnorr signature in Hex format. - -##### `schnorr.verify(signature, message, publicKey)` - -```typescript -function schnorrVerify( - signature: Uint8Array | string, - message: Uint8Array | string, - publicKey: Uint8Array | string -): boolean; -``` - -- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function -- `message: Uint8Array | string` - message (not hash) that needs to be verified -- `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey` -- Returns `boolean`: `true` if `signature == hash`; otherwise `false` #### Utilities @@ -263,10 +190,6 @@ console.log(secp.utils.bytesToHex(pubKey)); ```typescript const utils: { - // Can take 40 or more bytes of uniform input e.g. from CSPRNG or KDF - // and convert them into private key, with the modulo bias being neglible. - // As per FIPS 186 B.1.1. - hashToPrivateKey: (hash: Hex) => Uint8Array; // Returns `Uint8Array` of 32 cryptographically secure random bytes that can be used as private key randomPrivateKey: () => Uint8Array; // Checks private key for validity @@ -283,34 +206,22 @@ const utils: { // Modular inversion invert(number: bigint, modulo?: bigint): bigint; - sha256: (message: Uint8Array) => Promise; hmacSha256: (key: Uint8Array, ...messages: Uint8Array[]) => Promise; - // You can set up your synchronous methods for `signSync`/`signSchnorrSync` to work. + // You can set up your synchronous methods for `signSync` to work. // The argument order is identical to async methods from above - sha256Sync: undefined; hmacSha256Sync: undefined; - - // BIP0340-style tagged hashes - taggedHash: (tag: string, ...messages: Uint8Array[]) => Promise; - taggedHashSync: (tag: string, ...messages: Uint8Array[]) => Uint8Array; - - // 1. Returns cached point which you can use to pass to `getSharedSecret` or to `#multiply` by it. - // 2. Precomputes point multiplication table. Is done by default on first `getPublicKey()` call. - // If you want your first getPublicKey to take 0.16ms instead of 20ms, make sure to call - // utils.precompute() somewhere without arguments first. - precompute(windowSize?: number, point?: Point): Point; }; secp256k1.CURVE.P // Field, 2 ** 256 - 2 ** 32 - 977 secp256k1.CURVE.n // Order, 2 ** 256 - 432420386565659656852420866394968145599 -secp256k1.Point.BASE // new secp256k1.Point(Gx, Gy) where +secp256k1.PPoint.G // new secp256k1.Point(Gx, Gy) where // Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240n // Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; // Elliptic curve point in Affine (x, y) coordinates. -secp256k1.Point { - constructor(x: bigint, y: bigint); +secp256k1.PPoint { + constructor(x: bigint, y: bigint, z?: bigint); // Supports compressed and non-compressed hex static fromHex(hex: Uint8Array | string); static fromPrivateKey(privateKey: Uint8Array | string | number | bigint); @@ -330,12 +241,9 @@ secp256k1.Point { } secp256k1.Signature { constructor(r: bigint, s: bigint); - // DER encoded ECDSA signature - static fromDER(hex: Uint8Array | string); // R, S 32-byte each static fromCompact(hex: Uint8Array | string); - assertValidity(): void; - hasHighS(): boolean; // high-S sigs cannot be produced using { canonical: true } + ok(): void; toDERRawBytes(): Uint8Array; toDERHex(): string; toCompactRawBytes(): Uint8Array; @@ -400,6 +308,27 @@ Check out a blog post about this library: [Learning fast elliptic-curve cryptogr Special thanks to [Roman Koblov](https://github.com/romankoblov), who have helped to improve scalar multiplication speed. +## Upgrading + +noble-secp256k1 v2.0 has been reduced 4x to just over 400 lines. It features improved security and smaller attack surface. + +Some functionality present in v1, such as schnorr and DER, was removed: use [**noble-curves**](https://github.com/paulmillr/noble-curves) if you still need it. + +- `getPublicKey()` and `getSharedSecret()` now produce compressed 33-byte signatures by default. If you + need the old 65-byte behavior, set `isCompressed` option as `false`: `getPublicKey(priv, false)`, `getSharedSecret(a, b, false)` +- `sign()`: now returns `Signature` instance with `{ r, s, rec }` properties. It could still be passed to `verify` as-is. + - `canonical` has been renamed to `lowS`. The default value is the same as before: `lowS: true` + - `recovered` has been removed. Recovery bit is always returned in the `Signature` instance + - `der` has been removed. DER encoding is no longer supported. Use compact format (32-byte r + 32-byte s), `Signature` instance methods `toCompactRawBytes` / `toCompactHex()`: `(await sign(msgHash, priv)).toCompactRawBytes()` +- `verify()`: `strict` option has been renamed to `lowS`, default value is still the same +- `recoverPublicKey(msgHash, sig, recovery)` has been changed to `sig.recoverPublicKey(msgHash)` +- `Point` has been changed to `PPoint`; which now works in 3d xyz projective coordinates instead of + 2d xy affine. Its methods have been renamed: `multiply` to `mul`, `subtract` to `sub` etc. +- Schnorr signature scheme has been removed +- asn.1 DER encoding has been removed +- Errors are sometimes thrown with empty messages and longer stack traces +- Support for environments that can't parse bigint literals has been removed + ## License MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file. From a5f8d3a6a250da3815d48222d00e74b7fe56f637 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 19:49:30 +0000 Subject: [PATCH 022/145] README --- README.md | 78 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 67424bd..b33b67d 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,15 @@ you will need [import map](https://deno.land/manual/linking_to_external_code/imp function getPublicKey(privateKey: Uint8Array | string | bigint, isCompressed = true): Uint8Array; ``` -Creates public key for the corresponding private key. The default is full 33-byte key. -Set second argument to `false` if you need full (65-byte) key. Use `PPoint.fromPrivateKey(privateKey)` -if you need `PPoint` instead of `Uint8Array` +```js +const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; +getPublicKey(privKey); +getPublicKey(privKey, false); +``` + +Creates 33-byte compact public key for the corresponding private key. Set optional `isCompressed` to `false` +if you need full 65-byte key. Use `PPoint.fromPrivateKey(privateKey)` +if you need `PPoint` instead of `Uint8Array`: ##### `sign(msgHash, privateKey)` @@ -89,7 +95,17 @@ function sign( Generates low-s deterministic ECDSA signature as per RFC6979. -- `msgHash: Uint8Array | string` - 32-byte message hash which would be signed +```js +const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; +const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; +const sig = await sign(msgHash, privKey); +// Signatures with improved security +const sigE = await sign(msgHash, privKey, { extraEntropy: true }); +// Malleable signatures, but compatible with openssl +const sigM = await sign(msgHash, privKey, { lowS: false }); +``` + +- `msgHash: Uint8Array | string` - 32-byte message hash (not the message itself) which would be signed - `privateKey: Uint8Array | string | bigint` - private key which will sign the hash - `options?: Options` - _optional_ object related to signature value and format with following keys: - `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. @@ -103,15 +119,6 @@ Generates low-s deterministic ECDSA signature as per RFC6979. The function is asynchronous because we're utilizing built-in HMAC API to not rely on dependencies. -```ts -(async () => { - // Signatures with improved security - const signatureE = await secp.sign(msgHash, privKey, { extraEntropy: true }); - // Malleable signatures, but compatible with openssl - const signatureM = await secp.sign(msgHash, privKey, { lowS: false }); -})(); -``` - ```typescript function signSync( msgHash: Uint8Array | string, @@ -126,7 +133,7 @@ function signSync( import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) -secp.signSync(msgHash, privateKey); // Can be used now +secp.signSync(msgHash, privKey); // Can be used now ``` ##### `verify(signature, msgHash, publicKey)` @@ -140,6 +147,14 @@ function verify( ): boolean; ``` +```js +const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; +const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; +const pub = getPublicKey(privKey); +const sig = await sign(msgHash, privKey); +const isValid = verify(sig, msgHash, pub); +``` + - `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function - `msgHash: Uint8Array | string` - message hash that needs to be verified - `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey` @@ -147,18 +162,22 @@ function verify( - `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. `true` (default) makes signatures compatible with libsecp256k1, `false` makes signatures compatible with openssl -- Returns `boolean`: `true` if `signature == hash`; otherwise `false` +- Returns `boolean`: `true` if `signature` is valid for `hash` and `publicKey`; otherwise `false` ##### `getSharedSecret(privateKeyA, publicKeyB)` ```typescript function getSharedSecret( - privateKeyA: Uint8Array | string | bigint, - publicKeyB: Uint8Array | string | Point, - isCompressed = true + privateKeyA: Uint8Array | string, publicKeyB: Uint8Array | string, isCompressed = true ): Uint8Array; ``` +```js +const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; +const alicesPubkey = getPublicKey(utils.randomPrivateKey()); +getSharedSecret(privKey, alicesPubkey); +``` + Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between a private key and a different public key. - To get Point instance, use `Point.fromHex(publicKeyB).multiply(privateKeyA)` @@ -170,6 +189,13 @@ Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between a private ke signature.recoverPublicKey(msgHash: Uint8Array | string): Uint8Array | undefined; ``` +```js +const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; +const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; +const sig = await sign(msgHash, privKey); +sig.recoverPublicKey(msgHash); +``` + `Signature` instance method, recovers public key from message hash. - `msgHash: Uint8Array | string` - message hash which would be signed @@ -232,8 +258,8 @@ secp256k1.PPoint { ): Point | undefined { toRawBytes(isCompressed = false): Uint8Array; toHex(isCompressed = false): string; - equals(other: Point): boolean; - negate(): Point; + eql(other: Point): boolean; + neg(): Point; add(other: Point): Point; subtract(other: Point): Point; // Constant-time scalar multiplication. @@ -244,8 +270,6 @@ secp256k1.Signature { // R, S 32-byte each static fromCompact(hex: Uint8Array | string); ok(): void; - toDERRawBytes(): Uint8Array; - toDERHex(): string; toCompactRawBytes(): Uint8Array; toCompactHex(): string; } @@ -319,14 +343,14 @@ Some functionality present in v1, such as schnorr and DER, was removed: use [**n - `sign()`: now returns `Signature` instance with `{ r, s, rec }` properties. It could still be passed to `verify` as-is. - `canonical` has been renamed to `lowS`. The default value is the same as before: `lowS: true` - `recovered` has been removed. Recovery bit is always returned in the `Signature` instance - - `der` has been removed. DER encoding is no longer supported. Use compact format (32-byte r + 32-byte s), `Signature` instance methods `toCompactRawBytes` / `toCompactHex()`: `(await sign(msgHash, priv)).toCompactRawBytes()` + - `der` has been removed. DER encoding is no longer supported. Use compact format (32-byte r + 32-byte s), `Signature` instance methods `toCompactRawBytes` / `toCompactHex()`: `(await sign(msgHash, priv)).toCompactRawBytes()`. Use curves if you still need der - `verify()`: `strict` option has been renamed to `lowS`, default value is still the same - `recoverPublicKey(msgHash, sig, recovery)` has been changed to `sig.recoverPublicKey(msgHash)` - `Point` has been changed to `PPoint`; which now works in 3d xyz projective coordinates instead of - 2d xy affine. Its methods have been renamed: `multiply` to `mul`, `subtract` to `sub` etc. -- Schnorr signature scheme has been removed -- asn.1 DER encoding has been removed -- Errors are sometimes thrown with empty messages and longer stack traces + 2d xy affine. Its methods have been renamed: `multiply` to `mul`, `subtract` to `sub` etc. Use curves if you still need affine point +- Schnorr signature scheme has been removed. Use curves if you need it +- asn.1 DER encoding has been removed. Use curves if you need it +- Errors are sometimes thrown with empty messages and longer stack traces. Use curves if you need formatted errors - Support for environments that can't parse bigint literals has been removed ## License From 4e5facf34fe8c8b58140f600cdfef324af246a9d Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 20:01:49 +0000 Subject: [PATCH 023/145] README --- README.md | 111 +++++++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index b33b67d..d0a6089 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. -[**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). +Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). **2023 update:** version 2 has been released. It features 4x less code and improved security. Some features have been removed. Use [**noble-curves**](https://github.com/paulmillr/noble-curves) @@ -87,13 +87,18 @@ if you need `PPoint` instead of `Uint8Array`: ```typescript function sign( - msgHash: Uint8Array | string, - privateKey: Uint8Array | string, - opts?: { lowS: boolean, extraEntropy: boolean | Hex } + msgHash: Uint8Array | string, // 32-byte message hash (not the message itself) + privateKey: Uint8Array | string, // private key that will sign it + opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional object with params ): Promise; +function signSync( + msgHash: Uint8Array | string, // 32-byte message hash (not the message itself) + privateKey: Uint8Array | string, // private key that will sign it + opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional object with params +): Signature; ``` -Generates low-s deterministic ECDSA signature as per RFC6979. +Generates low-s deterministic-k ECDSA signature as per RFC6979. ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; @@ -105,27 +110,18 @@ const sigE = await sign(msgHash, privKey, { extraEntropy: true }); const sigM = await sign(msgHash, privKey, { lowS: false }); ``` -- `msgHash: Uint8Array | string` - 32-byte message hash (not the message itself) which would be signed -- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash -- `options?: Options` - _optional_ object related to signature value and format with following keys: - - `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. - `true` (default) makes signatures compatible with libsecp256k1, - `false` makes signatures compatible with openssl - - `extraEntropy: Uint8Array | string | true` - additional entropy `k'` for deterministic signature, follows section 3.6 of RFC6979. When `true`, it would automatically be filled with 32 bytes of cryptographically secure entropy. **Strongly recommended** to pass `true` to improve security: - - It would help a lot in case there is an error somewhere in `k` generation. Exposing `k` could leak private keys - - If the entropy generator is broken, signatures would be the same as they are without the option - - Signatures with extra entropy would have different `r` / `s`, which means they - would still be valid, but may break some test vectors if you're cross-testing against other libs +Options: -The function is asynchronous because we're utilizing built-in HMAC API to not rely on dependencies. +- `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. + `true` (default) makes signatures compatible with libsecp256k1, + `false` makes signatures compatible with openssl +- `extraEntropy: Uint8Array | string | boolean = false` - additional entropy `k'` for deterministic signature, follows section 3.6 of RFC6979. When `true`, it would automatically be filled with 32 bytes of cryptographically secure entropy. **Strongly recommended** to pass `true` to improve security: + - It would help a lot in case there is an error somewhere in `k` generation. Exposing `k` could leak private keys + - If the entropy generator is broken, signatures would be the same as they are without the option + - Signatures with extra entropy would have different `r` / `s`, which means they + would still be valid, but may break some test vectors if you're cross-testing against other libs -```typescript -function signSync( - msgHash: Uint8Array | string, - privateKey: Uint8Array | string, - opts?: { lowS: boolean, extraEntropy: boolean | Hex } -): Signature; -``` +The function is asynchronous because we're utilizing built-in HMAC API to not rely on dependencies. `signSync` counterpart could also be used, you need to set `utils.hmacSha256Sync` to a function with signature `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array`. Example with `noble-hashes` package: @@ -140,11 +136,12 @@ secp.signSync(msgHash, privKey); // Can be used now ```typescript function verify( - signature: Uint8Array | string | Signature, - msgHash: Uint8Array | string, - publicKey: Uint8Array | string | Point, - opts?: { lowS: boolean } -): boolean; + signature: Uint8Array | string | Signature, // Signature is returned by sign() + msgHash: Uint8Array | string, // message hash (not the message) that must be verified + publicKey: Uint8Array | string | Point, // public (not private) key + opts?: { lowS: boolean } // if a signature.s must be in the lower-half of CURVE.n. Used in BTC, ETH + // lowS: false should only be used if you need openSSL-compatible signatures +): boolean; // `true` if `signature` is valid for `hash` and `publicKey`; otherwise `false` ``` ```js @@ -155,21 +152,14 @@ const sig = await sign(msgHash, privKey); const isValid = verify(sig, msgHash, pub); ``` -- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function -- `msgHash: Uint8Array | string` - message hash that needs to be verified -- `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey` -- `options?: Options` - _optional_ object related to signature value and format - - `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. - `true` (default) makes signatures compatible with libsecp256k1, - `false` makes signatures compatible with openssl -- Returns `boolean`: `true` if `signature` is valid for `hash` and `publicKey`; otherwise `false` - ##### `getSharedSecret(privateKeyA, publicKeyB)` ```typescript -function getSharedSecret( - privateKeyA: Uint8Array | string, publicKeyB: Uint8Array | string, isCompressed = true -): Uint8Array; +function getSharedSecret( // Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between + privateKeyA: Uint8Array | string, // Alices's private key + publicKeyB: Uint8Array | string, // Bob's public key + isCompressed = true // optional arg; `true` default returns 33 byte keys, `false` can return 65-byte +): Uint8Array; // Use Point.fromHex(publicKeyB).mul(privateKeyA) if you need Point instance ``` ```js @@ -178,11 +168,6 @@ const alicesPubkey = getPublicKey(utils.randomPrivateKey()); getSharedSecret(privKey, alicesPubkey); ``` -Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between a private key and a different public key. - -- To get Point instance, use `Point.fromHex(publicKeyB).multiply(privateKeyA)` -- `isCompressed = true` determines whether to return compact (33-byte), or full (65-byte) key - ##### `Signature.recoverPublicKey(hash)` ```typescript @@ -245,25 +230,18 @@ secp256k1.PPoint.G // new secp256k1.Point(Gx, Gy) where // Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240n // Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; -// Elliptic curve point in Affine (x, y) coordinates. +// Elliptic curve point in Projective (x, y, z) coordinates. secp256k1.PPoint { constructor(x: bigint, y: bigint, z?: bigint); // Supports compressed and non-compressed hex static fromHex(hex: Uint8Array | string); static fromPrivateKey(privateKey: Uint8Array | string | number | bigint); - static fromSignature( - msgHash: Hex, - signature: Signature, - recovery: number | bigint - ): Point | undefined { toRawBytes(isCompressed = false): Uint8Array; toHex(isCompressed = false): string; eql(other: Point): boolean; neg(): Point; add(other: Point): Point; - subtract(other: Point): Point; - // Constant-time scalar multiplication. - multiply(scalar: bigint | Uint8Array): Point; + mul(scalar: bigint): Point; // Constant-time scalar multiplication. } secp256k1.Signature { constructor(r: bigint, s: bigint); @@ -279,7 +257,7 @@ secp256k1.Signature { Noble is production-ready. -1. The library has been audited by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf). See [changes since audit](https://github.com/paulmillr/noble-secp256k1/compare/1.2.0..main). +1. The library, as per version 1.2.0, has been audited by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf). See [changes since audit](https://github.com/paulmillr/noble-secp256k1/compare/1.2.0..main). - The audit has been [crowdfunded](https://gitcoin.co/grants/2451/audit-of-noble-secp256k1-cryptographic-library) by community with help of [Umbra.cash](https://umbra.cash). 2. The library has also been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). You can run the fuzzer by yourself to check it. @@ -289,18 +267,14 @@ We however consider infrastructure attacks like rogue NPM modules very important ## Speed -Benchmarks measured with Apple M2 on MacOS 12 with node.js 18.8. +Benchmarks measured with Apple M2 on MacOS 12 with node.js 18.10. - getPublicKey(utils.randomPrivateKey()) x 7,093 ops/sec @ 140μs/op - sign x 5,615 ops/sec @ 178μs/op - signSync (@noble/hashes) x 5,209 ops/sec @ 191μs/op - verify x 1,114 ops/sec @ 896μs/op - recoverPublicKey x 1,018 ops/sec @ 982μs/op - getSharedSecret aka ecdh x 665 ops/sec @ 1ms/op - getSharedSecret (precomputed) x 7,426 ops/sec @ 134μs/op - Point.fromHex (decompression) x 14,582 ops/sec @ 68μs/op - schnorr.sign x 805 ops/sec @ 1ms/op - schnorr.verify x 1,129 ops/sec @ 885μs/op + getPublicKey(utils.randomPrivateKey()) x 5,030 ops/sec @ 198μs/op + sign x 4,046 ops/sec @ 247μs/op + verify x 479 ops/sec @ 2ms/op + getSharedSecret x 405 ops/sec @ 2ms/op + recoverPublicKey x 487 ops/sec @ 2ms/op + Point.fromHex (decompression) x 7,642 ops/sec @ 130μs/op Compare to other libraries on M1 (`openssl` uses native bindings, not JS): @@ -348,8 +322,7 @@ Some functionality present in v1, such as schnorr and DER, was removed: use [**n - `recoverPublicKey(msgHash, sig, recovery)` has been changed to `sig.recoverPublicKey(msgHash)` - `Point` has been changed to `PPoint`; which now works in 3d xyz projective coordinates instead of 2d xy affine. Its methods have been renamed: `multiply` to `mul`, `subtract` to `sub` etc. Use curves if you still need affine point -- Schnorr signature scheme has been removed. Use curves if you need it -- asn.1 DER encoding has been removed. Use curves if you need it +- schnorr signatures, asn.1 DER, custom precomputes have been removed. Use noble-curves if you need them - Errors are sometimes thrown with empty messages and longer stack traces. Use curves if you need formatted errors - Support for environments that can't parse bigint literals has been removed From 0045f1dd4f0bf45a3dca4ff6fbcbcd89cd872e96 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 20:08:43 +0000 Subject: [PATCH 024/145] Docs --- README.md | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index d0a6089..f6ce088 100644 --- a/README.md +++ b/README.md @@ -70,19 +70,19 @@ you will need [import map](https://deno.land/manual/linking_to_external_code/imp ##### `getPublicKey(privateKey)` ```typescript -function getPublicKey(privateKey: Uint8Array | string | bigint, isCompressed = true): Uint8Array; +function getPublicKey( // Creates 33-byte compact public key for the private key. + privateKey: Uint8Array | string | bigint, + isCompressed = true // Optional argument: default `true` produces 33-byte compressed +): Uint8Array; ``` ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; getPublicKey(privKey); getPublicKey(privKey, false); +// Use `PPoint.fromPrivateKey(privateKey)` if you need `PPoint` instead of `Uint8Array` ``` -Creates 33-byte compact public key for the corresponding private key. Set optional `isCompressed` to `false` -if you need full 65-byte key. Use `PPoint.fromPrivateKey(privateKey)` -if you need `PPoint` instead of `Uint8Array`: - ##### `sign(msgHash, privateKey)` ```typescript @@ -104,30 +104,24 @@ Generates low-s deterministic-k ECDSA signature as per RFC6979. const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; const sig = await sign(msgHash, privKey); -// Signatures with improved security -const sigE = await sign(msgHash, privKey, { extraEntropy: true }); -// Malleable signatures, but compatible with openssl +// Malleable signatures, incompatible with BTC/ETH, but compatible with openssl +// `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) because of malleability const sigM = await sign(msgHash, privKey, { lowS: false }); -``` - -Options: -- `lowS: boolean = true` - whether a signature `s` should be no more than 1/2 prime order. - `true` (default) makes signatures compatible with libsecp256k1, - `false` makes signatures compatible with openssl -- `extraEntropy: Uint8Array | string | boolean = false` - additional entropy `k'` for deterministic signature, follows section 3.6 of RFC6979. When `true`, it would automatically be filled with 32 bytes of cryptographically secure entropy. **Strongly recommended** to pass `true` to improve security: - - It would help a lot in case there is an error somewhere in `k` generation. Exposing `k` could leak private keys - - If the entropy generator is broken, signatures would be the same as they are without the option - - Signatures with extra entropy would have different `r` / `s`, which means they - would still be valid, but may break some test vectors if you're cross-testing against other libs - -The function is asynchronous because we're utilizing built-in HMAC API to not rely on dependencies. - -`signSync` counterpart could also be used, you need to set `utils.hmacSha256Sync` to a function with signature `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array`. Example with `noble-hashes` package: +// Signatures with improved security: adds additional entropy `k` for deterministic signature, +// follows section 3.6 of RFC6979. When `true`, it would be filled with 32b from CSPRNG. +// **Strongly recommended** to pass `true` to improve security: +// - No disadvantage: if an entropy generator is broken, sigs would be the same as they are without the option +// - It would help a lot in case there is an error somewhere in `k` gen. Exposing `k` could leak private keys +// - Sigs with extra entropy would have different `r` / `s`, which means they +// would still be valid, but may break some test vectors if you're cross-testing against other libs +const sigE = await sign(msgHash, privKey, { extraEntropy: true }); -```ts +// ^ The function is async because we're utilizing built-in HMAC API to not rely on dependencies. +// signSync is disabled by default. To enable it, pass a hmac calculator function import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; +// should be `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array` secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) secp.signSync(msgHash, privKey); // Can be used now ``` From fc66eb38e5c89046fc4b6dbfc60a2c291362e59f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 20:10:51 +0000 Subject: [PATCH 025/145] README --- README.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f6ce088..a709f79 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,14 @@ you will need [import map](https://deno.land/manual/linking_to_external_code/imp ##### `getPublicKey(privateKey)` ```typescript -function getPublicKey( // Creates 33-byte compact public key for the private key. +function getPublicKey( privateKey: Uint8Array | string | bigint, isCompressed = true // Optional argument: default `true` produces 33-byte compressed ): Uint8Array; ``` +Creates 33-byte compact public key for the private key. + ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; getPublicKey(privKey); @@ -104,6 +106,15 @@ Generates low-s deterministic-k ECDSA signature as per RFC6979. const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; const sig = await sign(msgHash, privKey); + +// ^ The function is async because we're utilizing built-in HMAC API to not rely on dependencies. +// signSync is disabled by default. To enable it, pass a hmac calculator function +import { hmac } from '@noble/hashes/hmac'; +import { sha256 } from '@noble/hashes/sha256'; +// should be `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array` +secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) +secp.signSync(msgHash, privKey); // Can be used now + // Malleable signatures, incompatible with BTC/ETH, but compatible with openssl // `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) because of malleability const sigM = await sign(msgHash, privKey, { lowS: false }); @@ -116,14 +127,6 @@ const sigM = await sign(msgHash, privKey, { lowS: false }); // - Sigs with extra entropy would have different `r` / `s`, which means they // would still be valid, but may break some test vectors if you're cross-testing against other libs const sigE = await sign(msgHash, privKey, { extraEntropy: true }); - -// ^ The function is async because we're utilizing built-in HMAC API to not rely on dependencies. -// signSync is disabled by default. To enable it, pass a hmac calculator function -import { hmac } from '@noble/hashes/hmac'; -import { sha256 } from '@noble/hashes/sha256'; -// should be `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array` -secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) -secp.signSync(msgHash, privKey); // Can be used now ``` ##### `verify(signature, msgHash, publicKey)` @@ -138,6 +141,8 @@ function verify( ): boolean; // `true` if `signature` is valid for `hash` and `publicKey`; otherwise `false` ``` +Verifies signatures against message and public key. + ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; @@ -149,13 +154,15 @@ const isValid = verify(sig, msgHash, pub); ##### `getSharedSecret(privateKeyA, publicKeyB)` ```typescript -function getSharedSecret( // Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between +function getSharedSecret( privateKeyA: Uint8Array | string, // Alices's private key publicKeyB: Uint8Array | string, // Bob's public key isCompressed = true // optional arg; `true` default returns 33 byte keys, `false` can return 65-byte ): Uint8Array; // Use Point.fromHex(publicKeyB).mul(privateKeyA) if you need Point instance ``` +Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between key A and different key B. + ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const alicesPubkey = getPublicKey(utils.randomPrivateKey()); From c5400543a918ac53d4c6b85f00dd6641979d9642 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 20:23:15 +0000 Subject: [PATCH 026/145] Docs --- README.md | 83 +++++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index a709f79..4800bae 100644 --- a/README.md +++ b/README.md @@ -172,9 +172,13 @@ getSharedSecret(privKey, alicesPubkey); ##### `Signature.recoverPublicKey(hash)` ```typescript -signature.recoverPublicKey(msgHash: Uint8Array | string): Uint8Array | undefined; +signature.recoverPublicKey( + msgHash: Uint8Array | string +): Uint8Array | undefined; ``` +`Signature` instance method, recovers public key from message hash. Returns 33-byte compact key. + ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; @@ -182,75 +186,40 @@ const sig = await sign(msgHash, privKey); sig.recoverPublicKey(msgHash); ``` -`Signature` instance method, recovers public key from message hash. - -- `msgHash: Uint8Array | string` - message hash which would be signed -- `isCompressed = false` determines whether to return compact (33-byte), or full (65-byte) key - -Public key is generated by doing scalar multiplication of a base Point(x, y) by a fixed -integer. The result is another `Point(x, y)` which we will by default encode to hex Uint8Array. -If signature is invalid - function will return `undefined` as result. - #### Utilities secp256k1 exposes a few internal utilities for improved developer experience. -```js -// Default output is Uint8Array. If you need hex string as an output: -console.log(secp.utils.bytesToHex(pubKey)); -``` - ```typescript -const utils: { - // Returns `Uint8Array` of 32 cryptographically secure random bytes that can be used as private key - randomPrivateKey: () => Uint8Array; - // Checks private key for validity +secp.utils { + randomPrivateKey: () => Uint8Array; // Returns secure key from CSPRNG + randomBytes: (bytesLength?: number) => Uint8Array; // Returns secure bytes from CSPRNG isValidPrivateKey(privateKey: PrivKey): boolean; - - // Returns `Uint8Array` of x cryptographically secure random bytes. - randomBytes: (bytesLength?: number) => Uint8Array; - // Converts Uint8Array to hex string - bytesToHex(uint8a: Uint8Array): string; - hexToBytes(hex: string): Uint8Array; - concatBytes(...arrays: Uint8Array[]): Uint8Array; - // Modular division over curve prime - mod: (number: number | bigint, modulo = CURVE.P): bigint; - // Modular inversion - invert(number: bigint, modulo?: bigint): bigint; - - hmacSha256: (key: Uint8Array, ...messages: Uint8Array[]) => Promise; - - // You can set up your synchronous methods for `signSync` to work. - // The argument order is identical to async methods from above - hmacSha256Sync: undefined; + mod(number: number | bigint, modulo = CURVE.P): bigint; // Modular division + invert(number: bigint, modulo?: bigint): bigint; // Modular inversion + hmacSha256(key: Uint8Array, ...messages: Uint8Array[]) => Promise; + hmacSha256Sync: undefined; // Must be specified if you need `signSync` to work, args are same + bytesToHex(bytes: Uint8Array): string; // If you need hex string as an output }; - -secp256k1.CURVE.P // Field, 2 ** 256 - 2 ** 32 - 977 -secp256k1.CURVE.n // Order, 2 ** 256 - 432420386565659656852420866394968145599 -secp256k1.PPoint.G // new secp256k1.Point(Gx, Gy) where -// Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240n -// Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; - -// Elliptic curve point in Projective (x, y, z) coordinates. -secp256k1.PPoint { +secp.CURVE { P, n, a, b, Gx, Gy }; // CURVE prime; order; equation params; generator coordinates +secp.PPoint { // Elliptic curve point in Projective (x, y, z) coordinates. constructor(x: bigint, y: bigint, z?: bigint); - // Supports compressed and non-compressed hex static fromHex(hex: Uint8Array | string); static fromPrivateKey(privateKey: Uint8Array | string | number | bigint); + ok(): PPoint; // checks Point validity toRawBytes(isCompressed = false): Uint8Array; toHex(isCompressed = false): string; - eql(other: Point): boolean; - neg(): Point; - add(other: Point): Point; - mul(scalar: bigint): Point; // Constant-time scalar multiplication. + eql(other: Point): boolean; // a.equals(b) + neg(): Point; // negate + add(other: Point): Point; // addition + mul(scalar: bigint): Point; // constant-time scalar multiplication } -secp256k1.Signature { - constructor(r: bigint, s: bigint); - // R, S 32-byte each - static fromCompact(hex: Uint8Array | string); - ok(): void; - toCompactRawBytes(): Uint8Array; - toCompactHex(): string; +secp.Signature { + constructor(r: bigint, s: bigint, recovery?: number); + static fromCompact(hex: Uint8Array | string); // R, S 32-byte each + ok(): Signature; // checks Signature validity + toCompactRawBytes(): Uint8Array; // R, S 32-byte each + toCompactHex(): string; // same, in hex string } ``` From b33c1640f7d1e683490be1c40951fb01a022b8ab Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 18 Jan 2023 20:25:18 +0000 Subject: [PATCH 027/145] Docs --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4800bae..bc0584d 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,10 @@ you will need [import map](https://deno.land/manual/linking_to_external_code/imp - [`sign(msgHash, privateKey)`](#signmsghash-privatekey) - [`verify(signature, msgHash, publicKey)`](#verifysignature-msghash-publickey) - [`getSharedSecret(privateKeyA, publicKeyB)`](#getsharedsecretprivatekeya-publickeyb) -- [`signature.recoverPublicKey(msgHash)`](#recoverpublickeyhash-signature-recovery) +- [`signature.recoverPublicKey(msgHash)`](#signaturerecoverpublickeyhash) - [Utilities](#utilities) -##### `getPublicKey(privateKey)` +#### `getPublicKey(privateKey)` ```typescript function getPublicKey( @@ -85,7 +85,7 @@ getPublicKey(privKey, false); // Use `PPoint.fromPrivateKey(privateKey)` if you need `PPoint` instead of `Uint8Array` ``` -##### `sign(msgHash, privateKey)` +#### `sign(msgHash, privateKey)` ```typescript function sign( @@ -112,7 +112,7 @@ const sig = await sign(msgHash, privKey); import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; // should be `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array` -secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) +secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp.utils.concatBytes(...msgs)) secp.signSync(msgHash, privKey); // Can be used now // Malleable signatures, incompatible with BTC/ETH, but compatible with openssl @@ -129,7 +129,7 @@ const sigM = await sign(msgHash, privKey, { lowS: false }); const sigE = await sign(msgHash, privKey, { extraEntropy: true }); ``` -##### `verify(signature, msgHash, publicKey)` +#### `verify(signature, msgHash, publicKey)` ```typescript function verify( @@ -151,7 +151,7 @@ const sig = await sign(msgHash, privKey); const isValid = verify(sig, msgHash, pub); ``` -##### `getSharedSecret(privateKeyA, publicKeyB)` +#### `getSharedSecret(privateKeyA, publicKeyB)` ```typescript function getSharedSecret( @@ -169,7 +169,7 @@ const alicesPubkey = getPublicKey(utils.randomPrivateKey()); getSharedSecret(privKey, alicesPubkey); ``` -##### `Signature.recoverPublicKey(hash)` +#### `Signature.recoverPublicKey(hash)` ```typescript signature.recoverPublicKey( @@ -188,7 +188,7 @@ sig.recoverPublicKey(msgHash); #### Utilities -secp256k1 exposes a few internal utilities for improved developer experience. +The package exposes a few internal utilities for improved developer experience. ```typescript secp.utils { From f9a140d88496fed6e0fa6501281091e71132de55 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 23 Jan 2023 23:14:22 +0000 Subject: [PATCH 028/145] Add error messages. bits2int, truncateHash match curves. 8454, 419LOC. --- README.md | 11 ++-- index.ts | 149 ++++++++++++++++++++++++++---------------------------- 2 files changed, 77 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index bc0584d..300cf7a 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ ECDH key agreement protocol and signature schemes. Supports deterministic **ECDS Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). -**2023 update:** version 2 has been released. It features 4x less code and improved security. -Some features have been removed. Use [**noble-curves**](https://github.com/paulmillr/noble-curves) -if you need big, audited & optimized library. Use **noble-secp256k1** if you need -stable, frozen, minimal feature set and smaller attack surface. -Check out [Upgrading](#upgrading) section. +**2023 update:** version 2 has been released, check out [Upgrading](#upgrading) section. +It features 4x less code and improved security. Some features have been removed. +Use [**noble-curves**](https://github.com/paulmillr/noble-curves) +now if you need big, audited & optimized library with additional features. +Use **noble-secp256k1** if you need stable, frozen, minimal feature set and smaller attack surface. ### This library belongs to _noble_ crypto @@ -293,7 +293,6 @@ Some functionality present in v1, such as schnorr and DER, was removed: use [**n - `Point` has been changed to `PPoint`; which now works in 3d xyz projective coordinates instead of 2d xy affine. Its methods have been renamed: `multiply` to `mul`, `subtract` to `sub` etc. Use curves if you still need affine point - schnorr signatures, asn.1 DER, custom precomputes have been removed. Use noble-curves if you need them -- Errors are sometimes thrown with empty messages and longer stack traces. Use curves if you need formatted errors - Support for environments that can't parse bigint literals has been removed ## License diff --git a/index.ts b/index.ts index b3ae421..f64331e 100644 --- a/index.ts +++ b/index.ts @@ -2,32 +2,32 @@ const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve const P = B256 - 0x1000003d1n; // curve's field const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order -const a = 0n; // a equation's param -const b = 7n; // b equation's param +const _a = 0n; // a equation's param +const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -const CURVE = { P, n: N, a, b, Gx, Gy }; // exported variables +const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; // accepted inputs: bytes/hex -const crv = (x: bigint) => mod(mod(x * mod(x * x)) + a * x + b); // x³ + ax + b weierstrass formula -const errs = {'':'', l: 'legacy', h: 'no sync hmac', i: 'no inv', c: 'no CSPRNG/hmac', d: 'no DER'}; -const err = (m: keyof typeof errs = '', sfx = ''): never => { throw new Error(errs[m]+sfx); }; +const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _a * x + _b); // x³ + ax + b weierstrass formula +const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: any): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const u8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) - !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err() : a; +const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) + !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? + err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut -const toU8 = (a: any, len?: number) => u8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a +const toU8 = (a: any, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a const toPriv = (p: Hex | bigint): bigint => { // normalize private key to bigint if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes - return ge(p) ? p : err(); // check if bigint is in range + return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; let Gpows: Point[] | undefined = undefined; // precomputes for base point G interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords -const isPoint = (p: any) => (p instanceof Point ? p : err()); // is 3d point +const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { // Point in 3d xyz projective coords static readonly G = new Point(Gx, Gy, 1n); // generator / base point. static readonly I = new Point(0n, 1n, 0n); // identity / zero point @@ -42,6 +42,7 @@ class Point { // Point in 3d xyz proje add(other: Point) { // point addition: complete, exception-free const { x: X1, y: Y1, z: Z1 } = this; // formula from Renes-Costello-Batina const { x: X2, y: Y2, z: Z2 } = isPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 + const { a, b } = CURVE; let X3 = 0n, Y3 = 0n, Z3 = 0n; // Cost: 12M + 0S + 3*a + 3*b3 + 23add const b3 = mod(b * 3n); let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); // step 1 @@ -62,9 +63,9 @@ class Point { // Point in 3d xyz proje Z3 = mod(Z3 + t0); // step 40 return new Point(X3, Y3, Z3); } - mul(n: bigint, safe = true) { // multiply point by scalar n - if (!safe && n === 0n) return I; // In unsafe mode, allow zero - if (!ge(n)) err(); // must be 0 < n < CURVE.n + mul(n: bigint, safe = true) { // Multiply point by scalar n; + if (!safe && n === 0n) return I; // in unsafe mode, allow zero + if (!ge(n)) err('invalid scalar'); // must be 0 < n < CURVE.n if (this.eql(G)) return wNAF(n).p; // Use precomputes for base point let p = I, f = G; // init result point & fake point for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder @@ -76,26 +77,27 @@ class Point { // Point in 3d xyz proje mulAddQUns(R: Point, u1: bigint, u2: bigint) { // Q = u1⋅G + u2⋅R: double scalar mult. return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related } // to private keys. Doesn't use Shamir trick - aff(): AffinePoint { // converts point to 2d xy affine point - const { x, y, z } = this; + aff(): AffinePoint { // Converts point to 2d xy affine point + const { x, y, z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) if (this.eql(I)) return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is const iz = inv(z); // z^-1: invert z - if (mod(z * iz) !== 1n) err(); // (z * z^-1) must be 1, otherwise bad math + if (mod(z * iz) !== 1n) err('invalid inverse'); // (z * z^-1) must be 1, otherwise bad math return { x: mod(x * iz), y: mod(y * iz) }; // x = x*z^-1; y = y*z^-1 } - ok(): Point { // checks if the point is valid and on-curve + ok(): Point { // Checks if the point is valid and on-curve const { x, y } = this.aff(); // convert to 2d xy affine point. - if (!fe(x) || !fe(y)) err(); // x and y must be in range 0 < n < P - return mod(y * y) === crv(x) ? this : err(); // y² = x³ + ax + b, must be equal + if (!fe(x) || !fe(y)) err('Point invalid: x or y'); // x and y must be in range 0 < n < P + return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal + this : err('Point invalid: not on curve'); } - static fromHex(hex: Hex): Point { // convert Uint8Array or hex string to Point + static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate - if (len === 33 && [0x02, 0x03].includes(head)) { // Compressed points: 33b, start - if (!fe(x)) err(); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num: bigint, md = P): bigint => { // modular inversion - if (num === 0n || md <= 0n) err('i', ` n=${num} mod=${md}`); // negative exponent not supported + if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // negative exponent not supported let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { // uses euclidean gcd algorithm const q = b / a, r = b % a; // not constant-time const m = x - u * q, n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } - return b === 1n ? mod(x, md) : err('i'); // b is gcd at this point + return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point }; const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiation num^e - if (md <= 0n || e < 0n) err(); // exponentiation by squaring + if (md <= 0n || e < 0n) err('pow invalid'); // exponentiation by squaring if (md === 1n) return 0n; // the ladder can leak exponent bits let res = 1n; // and is vulnerable to timing attacks for (; e > 0n; e >>= 1n) { @@ -141,20 +143,20 @@ const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiat }; const sqrt = (n: bigint) => { // √(n) = n^((p+1)/4) for fields P = 3 mod 4 const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square - return mod(r * r) === n ? r : err(); // Roots from 1;24,51,10 to Dan Shanks" + return mod(r * r) === n ? r : err('sqrt invalid'); // Roots from 1;24,51,10 to Dan Shanks" }; const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0') const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); // hex to number const h2b = (hex: string): Bytes => { // hex to bytes const l = hex.length; // error if not string, - if (!str(hex) || l % 2) err(); // or has odd length like 3, 5. + if (!str(hex) || l % 2) err('hex invalid'); // or has odd length like 3, 5. const arr = u8n(l / 2); // create result array for (let i = 0; i < arr.length; i++) { const j = i * 2; const h = hex.slice(j, j + 2); // hexByte. slice is faster than substr const b = Number.parseInt(h, 16); // byte, created from string part - if (Number.isNaN(b) || b < 0) err(); // byte must be valid 0 <= byte < 256 + if (Number.isNaN(b) || b < 0) err('hex invalid'); // byte must be valid 0 <= byte < 256 arr[i] = b; } return arr; @@ -162,27 +164,16 @@ const h2b = (hex: string): Bytes => { // hex to bytes const b2n = (b: Bytes): bigint => h2n(b2h(b)); // bytes to number const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num: bigint): Bytes => { // number to bytes. must be 0 <= num < B256 - return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err(); + return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; const n2h = (num: bigint): string => b2h(n2b(num)); // number to hex const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Array-s const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length let pad = 0; // walk through each array, ensure - arrs.forEach(a => { r.set(u8(a), pad); pad += a.length }); // they have proper type + arrs.forEach(a => { r.set(au8(a), pad); pad += a.length }); // they have proper type return r; }; - -const b2n_2 = (bytes: Bytes) => { // bytes to bigint - const delta = bytes.length * 8 - 256; // truncates bits - const num = b2n(bytes); - return delta > 0 ? num >> BigInt(delta) : num; -}; -const truncH = (hash: Bytes): bigint => { // truncate hash - const h = b2n_2(hash); - return h >= N ? h - N : h; -}; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 - const getPublicKey = (privKey: Hex | bigint, isCompressed = true) => { // calculate public return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; @@ -194,11 +185,12 @@ class Signature { // calculates signature return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery - const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 - if (rec == null || ![0, 1, 2, 3].includes(rec)) err(); // also can just grind through all values - const h = truncH(toU8(msgh)); // Truncate hash + const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 + if (rec == null || ![0, 1, 2, 3].includes(rec)) // It is also possible to just grind through + err('recovery id invalid'); // all 4 recovery ids and deduce correct one + const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n - if (radj >= P) err(); // ensure q.x is still a field element + if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element const prefix = (rec! & 1) === 0 ? '02' : '03'; // prefix is 0x02 or 0x03 const R = Point.fromHex(`${prefix}${n2h(radj)}`); // concat prefix + hex repr of r const ir = inv(radj, N); // r^-1 @@ -209,15 +201,17 @@ class Signature { // calculates signature toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr } -const b2i = (b: Bytes): bigint => { // RFC6979 bytes to int - u8(b); - const sl = b.length > fLen ? b.slice(0, fLen) : b; // slice - return b2n(sl); // call our own method +// RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. +// FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. +// bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. +// int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors +const bits2int = (bytes: Uint8Array): bigint => { + const delta = bytes.length * 8 - 256; // truncate to nBitLength leftmost bits + const num = b2n(bytes); // check for == u8 done here + return delta > 0 ? num >> BigInt(delta) : num; }; -const b2o = (bytes: Bytes): Bytes => { // RFC6979 bits to octets - const z1 = b2i(bytes); - const z2 = mod(z1, N); - return i2o(z2 < 0n ? z1 : z2); +const bits2int_modN = (bytes: Uint8Array): bigint => { + return mod(bits2int(bytes), N); // can't use bytesToNumberBE here }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets declare const self: Record | undefined; // Typescript global symbol available in @@ -231,12 +225,14 @@ const stdo: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; const vstdo = { lowS: true }; // standard opts for verify() type PSA = [Bytes, bigint, bigint, boolean]; // return type of prepSig() const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC6979 sig generation - if (['der', 'recovered', 'canonical'].some(k => k in opts)) err('l'); // Ban legacy options + if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options + err('sign() legacy options not supported'); let low = opts?.lowS; // generates low-s sigs by default if (low == null) low = true; // RFC6979 3.2: we skip step A, because - const h1 = n2b(truncH(toU8(msgh))); // the message hash is already provided + const h1i = bits2int_modN(toU8(msgh)); + const h1o = i2o(h1i); const d = toPriv(priv); // validate private key, convert to bigint - const seed = [i2o(d), b2o(h1)]; // Step D of RFC6979 3.2 + const seed = [i2o(d), h1o]; // Step D of RFC6979 3.2 let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') if (ent === true) ent = ut.randomBytes(fLen); // if true, use CSPRNG to generate data @@ -244,11 +240,11 @@ const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC if (e.length !== fLen) err(); // Expected 32 bytes of extra data seed.push(e); } - const m = b2i(h1); // convert msg to bigint + const m = h1i; // convert msg to bigint return [concatB(...seed), m, d, low]; }; const kmd2sig = (kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined => { - const k = b2n_2(kBytes); // Utility method for RFC6979 k generation + const k = bits2int(kBytes); // Utility method for RFC6979 k generation if (!ge(k)) return; // Check 0 < k < CURVE.n const ik = inv(k, N); // k^-1 mod n, NOT mod P const q = G.mul(k).aff(); // q = Gk @@ -290,7 +286,7 @@ const hmacDrbgS = (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMA let v = u8n(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. let k = u8n(fLen).fill(0); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same let i = 0; // Iterations counter, will throw when over 1000 - if (!_hmacSync) err('h'); + if (!_hmacSync) err('utils.hmacSha256 not set'); const h = (...b: Bytes[]) => _hmacSync!(k, v, ...b); // hmac(k)(v, ...values) const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) @@ -309,7 +305,7 @@ const hmacDrbgS = (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMA while (!(sig = kmd2sig(gen(), m, d, lowS))) reseed(); // Step H: grind until k is in [1..n-1] return sig; }; -const sign = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { +const signAsync = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { return hmacDrbgA(...prepSig(msgh, priv, opts)); // ECDSA sig generation secg.org/sec1-v2.pdf 4.1.2 }; const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { @@ -319,13 +315,14 @@ const isInst = (sig: any): sig is Signature => sig instanceof Signature const verify = (sig: Hex | Signature, msgh: Hex, pub: Hex, opts = vstdo): boolean => { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true - if ('strict' in opts) err('l'); // legacy param + if ('strict' in opts) err('verify() legacy options not supported'); // legacy param let sig_: Signature, h: bigint, P: Point; // secg.org/sec1-v2.pdf 4.1.4 const inst = isInst(sig); // Previous ver supported DER sigs. We throw - if (!inst && (toU8(sig).length !== 2 * fLen)) err('d'); // error when DER is suspected now. + if (!inst && (toU8(sig).length !== 2 * fLen)) // error when DER is suspected now. + err('signature must be 64 bytes'); try { sig_ = inst ? sig.ok() : Signature.fromCompact(sig); - h = truncH(toU8(msgh, fLen)); // Truncate hash + h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { return false; } // Check sig for validity in both cases if (!sig_) return false; @@ -348,7 +345,7 @@ const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true) => { const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation hash = toU8(hash); // produces private keys with modulo bias const minLen = fLen + 8; // being neglible. - if (hash.length < minLen || hash.length > 1024) err(); + if (hash.length < minLen || hash.length > 1024) err('expected proper params'); const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); }; @@ -357,7 +354,7 @@ const ut = { // utilities concatBytes: concatB, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) return cr.web ? cr.web.getRandomValues(u8n(len)) : - cr.node ? u8fr(cr.node.randomBytes(len)) : err('c'); // throw when unavailable + cr.node ? u8fr(cr.node.randomBytes(len)) : err('CSPRNG not present'); }, hashToPrivateKey, hmacSha256: async (key: Bytes, ...msgs: Bytes[]): Promise => { @@ -369,18 +366,16 @@ const ut = { // utilities } else if (cr.node) { // node.js built-in version return u8fr(cr.node.createHmac('sha256', key).update(m).digest()); } else { - return err('c'); + return err('utils.hmacSha256 not set'); } }, - hmacSha256Sync: _hmacSync, // undefined by default + hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below randomPrivateKey: (): Bytes => hashToPrivateKey(ut.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, }; -Object.defineProperties(ut, { // Allow setting the function only once. - hmacSha256Sync: { // Next tries will silently fail. - configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, - }, -}); +Object.defineProperties(ut, { hmacSha256Sync: { // Allow setting it once. Next sets will be ignored + configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, +} }); const W = 8; // Precomputes-related code. W = window size const precompute = () => { // They give 12x faster getPublicKey(), const points: Point[] = []; // 10x sign(), 2x verify(). To achieve this, @@ -394,8 +389,8 @@ const precompute = () => { // They give 12x faster } // which multiplies user point by scalar, return points; // when precomputes are using base point } -const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method - if (256 % W) err(); // Compared to other point mult methods, +const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method. + // Compared to other point mult methods, const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction const neg = (cnd: boolean, p: Point) => { let n = p.neg(); return cnd ? n : p; } // negate let p = I, f = G; // f must be G, or could become I in the end @@ -421,4 +416,4 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() export const PPoint = Point; export const utils = ut; -export { getPublicKey, sign, signSync, verify, getSharedSecret, CURVE, Signature }; +export { getPublicKey, signAsync as sign, signSync, verify, getSharedSecret, CURVE, Signature }; From ff5f0817efdc652f9f318ca0ccc054a295e1cf0e Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 24 Jan 2023 01:47:32 +0000 Subject: [PATCH 029/145] Improve hmac-drbg logic and k generation --- index.ts | 151 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/index.ts b/index.ts index f64331e..cb56686 100644 --- a/index.ts +++ b/index.ts @@ -223,12 +223,12 @@ type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it const stdo: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() const vstdo = { lowS: true }; // standard opts for verify() -type PSA = [Bytes, bigint, bigint, boolean]; // return type of prepSig() -const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC6979 sig generation +type BC = { seed: Bytes, k2sig : (kb: Bytes) => Signature | undefined }; +const prepSig = (msgh: Hex, priv: Hex, opts = stdo): BC => { // prepare for RFC6979 sig generation if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); - let low = opts?.lowS; // generates low-s sigs by default - if (low == null) low = true; // RFC6979 3.2: we skip step A, because + let { lowS } = opts; // generates low-s sigs by default + if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because const h1i = bits2int_modN(toU8(msgh)); const h1o = i2o(h1i); const d = toPriv(priv); // validate private key, convert to bigint @@ -241,75 +241,94 @@ const prepSig = (msgh: Hex, priv: Hex, opts = stdo): PSA => { // prepare for RFC seed.push(e); } const m = h1i; // convert msg to bigint - return [concatB(...seed), m, d, low]; -}; -const kmd2sig = (kBytes: Bytes, m: bigint, d: bigint, lowS?: boolean): Signature | undefined => { - const k = bits2int(kBytes); // Utility method for RFC6979 k generation - if (!ge(k)) return; // Check 0 < k < CURVE.n - const ik = inv(k, N); // k^-1 mod n, NOT mod P - const q = G.mul(k).aff(); // q = Gk - const r = mod(q.x, N); // r = q.x mod n - if (r === 0n) return; // r=0 invalid - const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1(m + rd) mod n - if (s === 0n) return; // s=0 invalid - let normS = s; - let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit - if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always - normS = mod(-s, N); // in the bottom half of CURVE.n - rec ^= 1; - } - return new Signature(r, normS, rec); // use normS, not s -}; -const hmacDrbgA = async (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMAC-DRBG async - let v = u8n(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8n(fLen).fill(0); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same - let i = 0; // Iterations counter, will throw when over 1000 - const h = (...b: Bytes[]) => ut.hmacSha256(k, v, ...b); // hmac(k)(v, ...values) - const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G - k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) - v = await h(); // v = hmac(K || V) - if (seed.length === 0) return; - k = await h(u8fr([0x01]), seed); // k = hmac(K || V || 0x01 || seed) - v = await h(); // v = hmac(K || V) - }; - const gen = async () => { // HMAC-DRBG generate() function - if (i++ >= 1000) err(); - v = await h(); // v = hmac(K || V) - return v; + const k2sig = (kBytes: Bytes): Signature | undefined => { + const k = bits2int(kBytes); // Transforms k into Signature + if (!ge(k)) return; // Check 0 < k < CURVE.n + const ik = inv(k, N); // k^-1 mod n, NOT mod P + const q = G.mul(k).aff(); // q = Gk + const r = mod(q.x, N); // r = q.x mod n + if (r === 0n) return; // r=0 invalid + const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1(m + rd) mod n + if (s === 0n) return; // s=0 invalid + let normS = s; + let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit + if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always + normS = mod(-s, N); // in the bottom half of CURVE.n + rec ^= 1; + } + return new Signature(r, normS, rec); // use normS, not s }; - await reseed(seed); // Steps D-G - let sig: Signature | undefined = undefined; // Step H: grind until k is in [1..n-1] - while (!(sig = kmd2sig(await gen(), m, d, lowS))) await reseed(); - return sig; + return { seed: concatB(...seed), k2sig } }; -const hmacDrbgS = (seed: Bytes, m: bigint, d: bigint, lowS: boolean) => { // HMAC-DRBG sync - let v = u8n(fLen).fill(1); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8n(fLen).fill(0); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same +type Pred = (v: Uint8Array) => T | undefined; +function hmacDrbg(asynchronous: true): (seed: Bytes, predicate: Pred) => Promise; +function hmacDrbg(asynchronous: false): (seed: Bytes, predicate: Pred) => T; +function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async + let v = u8n(fLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(fLen); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same let i = 0; // Iterations counter, will throw when over 1000 - if (!_hmacSync) err('utils.hmacSha256 not set'); - const h = (...b: Bytes[]) => _hmacSync!(k, v, ...b); // hmac(k)(v, ...values) - const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G - k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) - v = h(); // v = hmac(k || v) - if (seed.length === 0) return; - k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) - v = h(); // v = hmac(k || v) - }; - const gen = () => { // HMAC-DRBG generate() function - if (i++ >= 1000) err(); - v = h(); // v = hmac(k || v) - return v; - }; - reseed(seed); - let sig: Signature | undefined = undefined; // Steps D-G - while (!(sig = kmd2sig(gen(), m, d, lowS))) reseed(); // Step H: grind until k is in [1..n-1] - return sig; + const reset = () => { v.fill(1); k.fill(0); i = 0; }; + const _e = 'drbg: tried 1000 values'; + if (asynchronous) { // asynchronous=true + const h = (...b: Bytes[]) => ut.hmacSha256(k, v, ...b); // hmac(k)(v, ...values) + const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G + k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) + v = await h(); // v = hmac(K || V) + if (seed.length === 0) return; + k = await h(u8fr([0x01]), seed); // k = hmac(K || V || 0x01 || seed) + v = await h(); // v = hmac(K || V) + }; + const gen = async () => { // HMAC-DRBG generate() function + if (i++ >= 1000) err(_e); + v = await h(); // v = hmac(K || V) + return v; + }; + return async (seed: Bytes, pred: Pred): Promise => { // Even though it feels safe to reuse + reset(); // the returned fn, don't, it's: 1. slower (JIT). 2. unsafe (async race conditions) + await reseed(seed); // Steps D-G + let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] + while (!(res = pred(await gen()))) await reseed(); + reset(); + return res!; + }; + } else { + const h = (...b: Bytes[]) => { // Same, but synchronous + const f = _hmacSync; + if (!f) err('utils.hmacSha256 not set'); + return f!(k, v, ...b); // hmac(k)(v, ...values) + }; + const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) + v = h(); // v = hmac(k || v) + if (seed.length === 0) return; + k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) + v = h(); // v = hmac(k || v) + }; + const gen = () => { // HMAC-DRBG generate() function + if (i++ >= 1000) err(_e); + v = h(); // v = hmac(k || v) + return v; + }; + return (seed: Bytes, pred: Pred): T => { + reset(); + reseed(seed); // Steps D-G + let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed(); + reset(); + return res!; + }; + } }; +// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2. hmacDrbg() const signAsync = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { - return hmacDrbgA(...prepSig(msgh, priv, opts)); // ECDSA sig generation secg.org/sec1-v2.pdf 4.1.2 + const { seed, k2sig } = prepSig(msgh, priv, opts); + const genUntil = hmacDrbg(true); + return genUntil(seed, k2sig); }; const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { - return hmacDrbgS(...prepSig(msgh, priv, opts)); // Synchronous version of sign() + const { seed, k2sig } = prepSig(msgh, priv, opts); + const genUntil = hmacDrbg(false); + return genUntil(seed, k2sig); }; const isInst = (sig: any): sig is Signature => sig instanceof Signature const verify = (sig: Hex | Signature, msgh: Hex, pub: Hex, opts = vstdo): boolean => { From 99b57327e17461c68670d4bc2ff6016380f3583f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 24 Jan 2023 01:55:25 +0000 Subject: [PATCH 030/145] Rename sign => signAsync, signSync => sign for compat with curves. 8554, 438LOC --- README.md | 18 +++++++++--------- index.ts | 2 +- test/index.ts | 27 +++++++++++++-------------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 300cf7a..c6fe979 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ import * as secp from '@noble/secp256k1'; const pubKey = secp.getPublicKey(privKey); // sha256 of 'hello world' const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; - const signature = await secp.sign(msgHash, privKey); + const signature = await secp.signAsync(msgHash, privKey); const isValid = secp.verify(signature, msgHash, pubKey); })(); ``` @@ -88,24 +88,24 @@ getPublicKey(privKey, false); #### `sign(msgHash, privateKey)` ```typescript -function sign( +function signAsync( // Available by default msgHash: Uint8Array | string, // 32-byte message hash (not the message itself) privateKey: Uint8Array | string, // private key that will sign it opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional object with params ): Promise; -function signSync( +function sign( // Not available by default: need to set utils.hmacSha256 first msgHash: Uint8Array | string, // 32-byte message hash (not the message itself) privateKey: Uint8Array | string, // private key that will sign it opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional object with params ): Signature; ``` -Generates low-s deterministic-k ECDSA signature as per RFC6979. +Generates low-s deterministic-k RFC6979 ECDSA signature. Use with `extraEntropy: true` to improve security. ```js const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; -const sig = await sign(msgHash, privKey); +const sig = await signAsync(msgHash, privKey); // ^ The function is async because we're utilizing built-in HMAC API to not rely on dependencies. // signSync is disabled by default. To enable it, pass a hmac calculator function @@ -113,11 +113,11 @@ import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; // should be `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array` secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp.utils.concatBytes(...msgs)) -secp.signSync(msgHash, privKey); // Can be used now +secp.sign(msgHash, privKey); // Can be used now // Malleable signatures, incompatible with BTC/ETH, but compatible with openssl // `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) because of malleability -const sigM = await sign(msgHash, privKey, { lowS: false }); +const sigM = sign(msgHash, privKey, { lowS: false }); // Signatures with improved security: adds additional entropy `k` for deterministic signature, // follows section 3.6 of RFC6979. When `true`, it would be filled with 32b from CSPRNG. @@ -126,7 +126,7 @@ const sigM = await sign(msgHash, privKey, { lowS: false }); // - It would help a lot in case there is an error somewhere in `k` gen. Exposing `k` could leak private keys // - Sigs with extra entropy would have different `r` / `s`, which means they // would still be valid, but may break some test vectors if you're cross-testing against other libs -const sigE = await sign(msgHash, privKey, { extraEntropy: true }); +const sigE = sign(msgHash, privKey, { extraEntropy: true }); ``` #### `verify(signature, msgHash, publicKey)` @@ -147,7 +147,7 @@ Verifies signatures against message and public key. const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; const pub = getPublicKey(privKey); -const sig = await sign(msgHash, privKey); +const sig = await signAsync(msgHash, privKey); const isValid = verify(sig, msgHash, pub); ``` diff --git a/index.ts b/index.ts index cb56686..9876ae7 100644 --- a/index.ts +++ b/index.ts @@ -435,4 +435,4 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() export const PPoint = Point; export const utils = ut; -export { getPublicKey, signAsync as sign, signSync, verify, getSharedSecret, CURVE, Signature }; +export { getPublicKey, signAsync, signSync as sign, verify, getSharedSecret, CURVE, Signature }; diff --git a/test/index.ts b/test/index.ts index e5a9f84..db5107e 100644 --- a/test/index.ts +++ b/test/index.ts @@ -26,7 +26,6 @@ const hex = secp.utils.bytesToHex; const hexToBytes = secp.utils.hexToBytes; const Point = secp.PPoint; -// const { Signature } = secp; const { bytesToNumber: b2n, hexToBytes: h2b } = secp.utils; const DER = { // asn.1 DER encoding utils @@ -251,7 +250,7 @@ describe('secp256k1', () => { describe('.sign()', () => { it('should create deterministic signatures with RFC 6979', async () => { for (const vector of ecdsa.valid) { - let usig = await secp.sign(vector.m, vector.d); + let usig = await secp.signAsync(vector.m, vector.d); let sig = usig.toCompactHex(); const vsig = vector.signature; expect(sig.slice(0, 64)).toBe(vsig.slice(0, 64)); @@ -262,16 +261,16 @@ describe('secp256k1', () => { it('should not create invalid deterministic signatures with RFC 6979', async () => { for (const vector of ecdsa.invalid.sign) { expect(() => { - return secp.sign(vector.m, vector.d); + return secp.signAsync(vector.m, vector.d); }).rejects.toThrowError(); } }); it('edge cases', () => { // @ts-ignore - expect(async () => await secp.sign()).rejects.toThrowError(); + expect(async () => await secp.signAsync()).rejects.toThrowError(); // @ts-ignore - expect(async () => await secp.sign('')).rejects.toThrowError(); + expect(async () => await secp.signAsync('')).rejects.toThrowError(); }); it('should create correct DER encoding against libsecp256k1', async () => { @@ -293,7 +292,7 @@ describe('secp256k1', () => { '0101010101010101010101010101010101010101010101010101010101010101' ); for (let [msg, exp] of CASES) { - const res = await secp.sign(msg, privKey, { extraEntropy: undefined }); + const res = await secp.signAsync(msg, privKey, { extraEntropy: undefined }); const derRes = DER.hexFromSig(res); expect(derRes).toBe(exp); const derRes2 = DER.toSig(derRes); @@ -309,7 +308,7 @@ describe('secp256k1', () => { for (const e of ecdsa.extraEntropy) { const sign = async (extraEntropy?: string) => { - const s = await secp.sign(e.m, e.d, { extraEntropy }); + const s = await secp.signAsync(e.m, e.d, { extraEntropy }); return s.toCompactHex(); }; expect(await sign()).toBe(e.signature); @@ -326,7 +325,7 @@ describe('secp256k1', () => { it('should verify signature', async () => { const MSG = '01'.repeat(32); const PRIV_KEY = secp.utils.numToField(0x2n); - const signature = await secp.sign(MSG, PRIV_KEY); + const signature = await secp.signAsync(MSG, PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY); expect(publicKey.length).toBe(33); expect(secp.verify(signature, MSG, publicKey)).toBe(true); @@ -335,7 +334,7 @@ describe('secp256k1', () => { const MSG = '01'.repeat(32); const PRIV_KEY = secp.utils.numToField(0x2n); const WRONG_PRIV_KEY = secp.utils.numToField(0x22n); - const signature = await secp.sign(MSG, PRIV_KEY); + const signature = await secp.signAsync(MSG, PRIV_KEY); const publicKey = Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); expect(publicKey.length).toBe(66); expect(secp.verify(signature, MSG, publicKey)).toBe(false); @@ -344,7 +343,7 @@ describe('secp256k1', () => { const MSG = '01'.repeat(32); const PRIV_KEY = secp.utils.numToField(0x2n); const WRONG_MSG = '11'.repeat(32); - const signature = await secp.sign(MSG, PRIV_KEY); + const signature = await secp.signAsync(MSG, PRIV_KEY); const publicKey = secp.getPublicKey(PRIV_KEY); expect(publicKey.length).toBe(33); expect(secp.verify(signature, WRONG_MSG, publicKey)).toBe(false); @@ -357,7 +356,7 @@ describe('secp256k1', () => { async (privKey, msg) => { const pk = secp.utils.numToField(privKey); const pub = secp.getPublicKey(pk); - const sig = await secp.sign(msg, pk); + const sig = await secp.signAsync(msg, pk); expect(secp.verify(sig, msg, pub)).toBeTruthy(); } ) @@ -449,7 +448,7 @@ describe('secp256k1', () => { const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; const privateKey = secp.utils.numToField(123456789n); const publicKey = Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); - const sig = await secp.sign(message, privateKey); + const sig = await secp.signAsync(message, privateKey); const recoveredPubkey = sig.recoverPublicKey(message); expect(recoveredPubkey).not.toBe(null); expect(recoveredPubkey.toHex(false)).toBe(publicKey); @@ -468,14 +467,14 @@ describe('secp256k1', () => { const privKey = secp.utils.randomPrivateKey(); const pub = secp.getPublicKey(privKey); const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; - const sig = await secp.sign(zeros, privKey); + const sig = await secp.signAsync(zeros, privKey); const recoveredKey = sig.recoverPublicKey(zeros); expect(recoveredKey.toRawBytes()).toEqual(pub); }); it('should handle RFC 6979 vectors', async () => { for (const vector of ecdsa.valid) { if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue; - let sig = await secp.sign(vector.m, vector.d); + let sig = await secp.signAsync(vector.m, vector.d); // let sig = hex(usig); const vpub = secp.getPublicKey(vector.d); const recovered = sig.recoverPublicKey(vector.m)!; From d1283ab37509940fe441cbafe1a9693f5303baa9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 31 Jan 2023 04:33:54 +0000 Subject: [PATCH 031/145] Compat with curves. 8768, 439LOC --- index.ts | 69 ++++++++++++++++++++++++++------------------------- test/index.ts | 40 ++++++++++++++--------------- 2 files changed, 54 insertions(+), 55 deletions(-) diff --git a/index.ts b/index.ts index 9876ae7..a8f6d1d 100644 --- a/index.ts +++ b/index.ts @@ -13,9 +13,9 @@ const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _a * x + _b); // x³ + ax + b const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: any): s is string => typeof s === 'string'; // is string -const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element +const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) +const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array @@ -29,19 +29,19 @@ let Gpows: Point[] | undefined = undefined; // precomputes for base interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { // Point in 3d xyz projective coords - static readonly G = new Point(Gx, Gy, 1n); // generator / base point. - static readonly I = new Point(0n, 1n, 0n); // identity / zero point - constructor(readonly x: bigint, readonly y: bigint, readonly z = 1n) {} // z is optional - eql(other: Point): boolean { // equality check - const { x: X1, y: Y1, z: Z1 } = this; - const { x: X2, y: Y2, z: Z2 } = isPoint(other); // isPoint() checks class equality + static readonly BASE = new Point(Gx, Gy, 1n); // generator / base point. + static readonly ZERO = new Point(0n, 1n, 0n); // identity / zero point + constructor(readonly px: bigint, readonly py: bigint, readonly pz = 1n) {} // z is optional + equals(other: Point): boolean { // equality check + const { px: X1, py: Y1, pz: Z1 } = this; + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // isPoint() checks class equality return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); } - neg() { return new Point(this.x, mod(-this.y), this.z); } // negate, flips point over y coord + neg() { return new Point(this.px, mod(-this.py), this.pz); } // negate, flips point over y coord dbl() { return this.add(this); } // point doubling add(other: Point) { // point addition: complete, exception-free - const { x: X1, y: Y1, z: Z1 } = this; // formula from Renes-Costello-Batina - const { x: X2, y: Y2, z: Z2 } = isPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 + const { px: X1, py: Y1, pz: Z1 } = this; // formula from Renes-Costello-Batina + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 const { a, b } = CURVE; let X3 = 0n, Y3 = 0n, Z3 = 0n; // Cost: 12M + 0S + 3*a + 3*b3 + 23add const b3 = mod(b * 3n); @@ -66,7 +66,7 @@ class Point { // Point in 3d xyz proje mul(n: bigint, safe = true) { // Multiply point by scalar n; if (!safe && n === 0n) return I; // in unsafe mode, allow zero if (!ge(n)) err('invalid scalar'); // must be 0 < n < CURVE.n - if (this.eql(G)) return wNAF(n).p; // Use precomputes for base point + if (this.equals(G)) return wNAF(n).p; // Use precomputes for base point let p = I, f = G; // init result point & fake point for (let d: Point = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder if (n & 1n) p = p.add(d); // if bit is present, add to point @@ -78,8 +78,8 @@ class Point { // Point in 3d xyz proje return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related } // to private keys. Doesn't use Shamir trick aff(): AffinePoint { // Converts point to 2d xy affine point - const { x, y, z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) - if (this.eql(I)) return { x: 0n, y: 0n }; // fast-path for zero point + const { px: x, py: y, pz: z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) + if (this.equals(I)) return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is const iz = inv(z); // z^-1: invert z if (mod(z * iz) !== 1n) err('invalid inverse'); // (z * z^-1) must be 1, otherwise bad math @@ -91,6 +91,11 @@ class Point { // Point in 3d xyz proje return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal this : err('Point invalid: not on curve'); } + multiply(n: bigint) { return this.mul(n); } // Aliases for compatibilty + toAffine() { return this.aff(); } + assertValidity() { return this.ok(); } + get x() { return this.aff().x; } + get y() { return this.aff().y; } static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; @@ -119,7 +124,7 @@ class Point { // Point in 3d xyz proje return G.mul(toPriv(n)); // base point by bigint(n) } } -const { G, I } = Point; // Generator, identity points +const { BASE: G, ZERO: I } = Point; // Generator, identity points const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num: bigint, md = P): bigint => { // modular inversion if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // negative exponent not supported @@ -141,7 +146,7 @@ const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiat } return res; }; -const sqrt = (n: bigint) => { // √(n) = n^((p+1)/4) for fields P = 3 mod 4 +const sqrt = (n: bigint) => { // √n = n^((p+1)/4) for fields p = 3 mod 4 const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square return mod(r * r) === n ? r : err('sqrt invalid'); // Roots from 1;24,51,10 to Dan Shanks" }; @@ -186,8 +191,8 @@ class Signature { // calculates signature } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 - if (rec == null || ![0, 1, 2, 3].includes(rec)) // It is also possible to just grind through - err('recovery id invalid'); // all 4 recovery ids and deduce correct one + if (rec == null || ![0, 1, 2, 3].includes(rec)) // + err('recovery id invalid'); // const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element @@ -201,17 +206,13 @@ class Signature { // calculates signature toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr } -// RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. -// FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. -// bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. -// int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors -const bits2int = (bytes: Uint8Array): bigint => { - const delta = bytes.length * 8 - 256; // truncate to nBitLength leftmost bits - const num = b2n(bytes); // check for == u8 done here - return delta > 0 ? num >> BigInt(delta) : num; +const bits2int = (bytes: Uint8Array): bigint => { // RFC6979: ensure ECDSA msg is X bytes. + const delta = bytes.length * 8 - 256; // RFC suggests optional truncating via bits2octets + const num = b2n(bytes); // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which + return delta > 0 ? num >> BigInt(delta) : num; // matches bits2int. bits2int can produce res>N. }; -const bits2int_modN = (bytes: Uint8Array): bigint => { - return mod(bits2int(bytes), N); // can't use bytesToNumberBE here +const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be used; pads small msgs + return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets declare const self: Record | undefined; // Typescript global symbol available in @@ -330,17 +331,17 @@ const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { const genUntil = hmacDrbg(false); return genUntil(seed, k2sig); }; -const isInst = (sig: any): sig is Signature => sig instanceof Signature -const verify = (sig: Hex | Signature, msgh: Hex, pub: Hex, opts = vstdo): boolean => { +type SigLike = { r: bigint, s: bigint }; +const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): boolean => { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true if ('strict' in opts) err('verify() legacy options not supported'); // legacy param let sig_: Signature, h: bigint, P: Point; // secg.org/sec1-v2.pdf 4.1.4 - const inst = isInst(sig); // Previous ver supported DER sigs. We throw - if (!inst && (toU8(sig).length !== 2 * fLen)) // error when DER is suspected now. + const rs = sig && typeof sig === 'object' && 'r' in sig; // Previous ver supported DER sigs. We + if (!rs && (toU8(sig).length !== 2 * fLen)) // throw error when DER is suspected now. err('signature must be 64 bytes'); try { - sig_ = inst ? sig.ok() : Signature.fromCompact(sig); + sig_ = rs ? new Signature(sig.r, sig.s).ok() : Signature.fromCompact(sig); h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { return false; } // Check sig for validity in both cases @@ -433,6 +434,6 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo } return { p, f } // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() -export const PPoint = Point; +export const ProjectivePoint = Point; export const utils = ut; export { getPublicKey, signAsync, signSync as sign, verify, getSharedSecret, CURVE, Signature }; diff --git a/test/index.ts b/test/index.ts index db5107e..fdaffa8 100644 --- a/test/index.ts +++ b/test/index.ts @@ -24,7 +24,7 @@ const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyz const toBEHex = (n: number | bigint) => n.toString(16).padStart(64, '0'); const hex = secp.utils.bytesToHex; const hexToBytes = secp.utils.hexToBytes; -const Point = secp.PPoint; +const Point = secp.ProjectivePoint; const { bytesToNumber: b2n, hexToBytes: h2b } = secp.utils; const DER = { @@ -45,33 +45,31 @@ const DER = { // ^ Weird condition: not about length, but about first bytes of number. return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left }, - toSig(hex: string) { + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { // parse DER signature const { Err: E } = DER; - const data = typeof hex === 'string' ? secp.utils.hexToBytes(hex) : hex; + const data = typeof hex === 'string' ? h2b(hex) : hex; + if (!(data instanceof Uint8Array)) throw new Error('ui8a expected'); let l = data.length; if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); const { d: r, l: sBytes } = DER._parseInt(data.subarray(2)); const { d: s, l: rBytesLeft } = DER._parseInt(sBytes); if (rBytesLeft.length) throw new E('Invalid signature: left bytes after parsing'); - return new secp.Signature(r, s); + return { r, s }; }, - fromSig(sig: secp.Signature): Uint8Array { - return h2b(DER.hexFromSig(sig)); - }, - hexFromSig(sig: secp.Signature): string { + hexFromSig(sig: { r: bigint; s: bigint }): string { const slice = (s: string): string => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER const h = (num: number | bigint) => { const hex = num.toString(16); return hex.length & 1 ? `0${hex}` : hex; }; - const s = slice(h(sig.s)), - r = slice(h(sig.r)); - const shl = s.length / 2, - rhl = r.length / 2; - const sl = h(shl), - rl = h(rhl); + const s = slice(h(sig.s)); + const r = slice(h(sig.r)); + const shl = s.length / 2; + const rhl = r.length / 2; + const sl = h(shl); + const rl = h(rhl); return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; }, }; @@ -177,8 +175,8 @@ describe('secp256k1', () => { if (expected) { expect(p.add(q).toHex(true)).toBe(expected); } else { - if (p.eql(q.neg())) { - expect(p.add(q).toHex(true)).toBe(Point.I.toHex(true)); + if (p.equals(q.neg())) { + expect(p.add(q).toHex(true)).toBe(Point.ZERO.toHex(true)); } else { expect(() => p.add(q).toHex(true)).toThrowError(); } @@ -210,7 +208,7 @@ describe('secp256k1', () => { } for (const num of [0n, 0, -1n, -1, 1.1]) { // @ts-ignore - expect(() => Point.G.multiply(num)).toThrowError(); + expect(() => Point.BASE.multiply(num)).toThrowError(); } }); @@ -547,9 +545,9 @@ describe('secp256k1', () => { pointAddScalar: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { const P = Point.fromHex(p); const t = normal(tweak); - const Q = P.add(Point.G.mul(t)); - // const Q = Point.G.multiplyAndAddUnsafe(P, t, 1n); - if (!Q || Q.eql(Point.I)) throw new Error('Tweaked point at infinity'); + const Q = P.add(Point.BASE.mul(t)); + // const Q = Point.BASE.multiplyAndAddUnsafe(P, t, 1n); + if (!Q || Q.equals(Point.ZERO)) throw new Error('Tweaked point at infinity'); return Q.toRawBytes(isCompressed); }, @@ -636,7 +634,7 @@ describe('secp256k1', () => { }); // describe('JacobianPoint', () => { -// const JZERO = Point.I; +// const JZERO = Point.ZERO; // const AZERO = { x: 0n, y: 0n }; // expect(AZERO.equals(JZERO)).toBeTruthy(); // expect(AZERO.toAffine().equals(JZERO.toAffine())).toBeTruthy(); From d0ed59f7816217081bf0dc790e82ccf356e492c9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 31 Jan 2023 04:36:12 +0000 Subject: [PATCH 032/145] Fix hexToNum bug --- index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.ts b/index.ts index a8f6d1d..b50ad6d 100644 --- a/index.ts +++ b/index.ts @@ -152,7 +152,7 @@ const sqrt = (n: bigint) => { // √n = n^((p+1)/4) fo }; const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0') const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex -const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex}`) : err()); // hex to number +const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex||'0'}`) : err()); // hex to number const h2b = (hex: string): Bytes => { // hex to bytes const l = hex.length; // error if not string, if (!str(hex) || l % 2) err('hex invalid'); // or has odd length like 3, 5. From 6c0d92e613015b6091985ce07d12ad9bd13e86c2 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 31 Jan 2023 04:47:18 +0000 Subject: [PATCH 033/145] Fix deno --- index.ts | 7 +++---- mod.ts | 16 ++++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/index.ts b/index.ts index b50ad6d..7a47134 100644 --- a/index.ts +++ b/index.ts @@ -124,7 +124,7 @@ class Point { // Point in 3d xyz proje return G.mul(toPriv(n)); // base point by bigint(n) } } -const { BASE: G, ZERO: I } = Point; // Generator, identity points +const { BASE: G, ZERO: I } = Point; // Generator, identity points const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num: bigint, md = P): bigint => { // modular inversion if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // negative exponent not supported @@ -150,7 +150,7 @@ const sqrt = (n: bigint) => { // √n = n^((p+1)/4) fo const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square return mod(r * r) === n ? r : err('sqrt invalid'); // Roots from 1;24,51,10 to Dan Shanks" }; -const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0') +const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0'); const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex||'0'}`) : err()); // hex to number const h2b = (hex: string): Bytes => { // hex to bytes @@ -191,8 +191,7 @@ class Signature { // calculates signature } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 - if (rec == null || ![0, 1, 2, 3].includes(rec)) // - err('recovery id invalid'); // + if (![0, 1, 2, 3].includes(rec!)) err('recovery id invalid'); // check recovery id const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element diff --git a/mod.ts b/mod.ts index b21f1a5..8ab3b16 100644 --- a/mod.ts +++ b/mod.ts @@ -1,11 +1,11 @@ // prettier-ignore import { - CURVE, Point, Signature, - getPublicKey, sign, signSync, verify, recoverPublicKey, getSharedSecret, - schnorr, utils, + CURVE, ProjectivePoint, Signature, + getPublicKey, sign, signAsync, verify, getSharedSecret, + utils, } from './index.ts'; -import { HmacSha256 } from 'https://deno.land/std@0.153.0/hash/sha256.ts'; -import { crypto } from 'https://deno.land/std@0.153.0/crypto/mod.ts'; +import { HmacSha256 } from 'https://deno.land/std@0.175.0/hash/sha256.ts'; +import { crypto } from 'https://deno.land/std@0.175.0/crypto/mod.ts'; utils.sha256 = async (...msgs: Uint8Array[]): Promise => { return new Uint8Array(await crypto.subtle.digest('SHA-256', utils.concatBytes(...msgs))); @@ -26,7 +26,7 @@ utils.hmacSha256Sync = (key: Uint8Array, ...messages: Uint8Array[]) => hmac(key, // prettier-ignore export { - CURVE, Point, Signature, - getPublicKey, sign, signSync, verify, recoverPublicKey, getSharedSecret, - schnorr, utils, + CURVE, ProjectivePoint, Signature, + getPublicKey, sign, signAsync, verify, getSharedSecret, + utils, }; From 1a137054c039ab045216d0466146a7980cb455ba Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 4 Feb 2023 08:39:03 +0000 Subject: [PATCH 034/145] Link to noble-curves --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index aea7aba..e465b4c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # noble-secp256k1 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [Fastest](#speed) JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), -an elliptic curve that could be used for asymmetric encryption, -ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979 and **Schnorr** signatures from [BIP0340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). +an elliptic curve that could be used for ECDSA/Schnorr signature schemes and ECDH key agreement protocol. -[**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/) +Conforms to [RFC6979](https://datatracker.ietf.org/doc/rfc6979/) for deterministic ECDSA and to [BIP0340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). + +[**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). ### This library belongs to _noble_ crypto @@ -15,9 +16,9 @@ ECDH key agreement protocol and signature schemes. Supports deterministic **ECDS - Supported in all major browsers and stable node.js versions - All releases are signed with PGP keys - Check out [homepage](https://paulmillr.com/noble/) & all libraries: - [secp256k1](https://github.com/paulmillr/noble-secp256k1), - [ed25519](https://github.com/paulmillr/noble-ed25519), - [bls12-381](https://github.com/paulmillr/noble-bls12-381), + [curves](https://github.com/paulmillr/noble-curves) + ([secp256k1](https://github.com/paulmillr/noble-secp256k1), + [ed25519](https://github.com/paulmillr/noble-ed25519)), [hashes](https://github.com/paulmillr/noble-hashes) ## Usage From dddf55b9ac93e441874f183a3fbb31e5d5e97424 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 4 Feb 2023 08:55:46 +0000 Subject: [PATCH 035/145] README --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index e465b4c..470b305 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,7 @@ [Fastest](#speed) JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for ECDSA/Schnorr signature schemes and ECDH key agreement protocol. -Conforms to [RFC6979](https://datatracker.ietf.org/doc/rfc6979/) for deterministic ECDSA and to [BIP0340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). - -[**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). +Conforms to [RFC6979](https://datatracker.ietf.org/doc/rfc6979/) for deterministic ECDSA and to [BIP0340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). [**Audited**](#security) by an independent security firm. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). ### This library belongs to _noble_ crypto From 0dee9b091d24278c017e3982531e4d59e85110cd Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 4 Feb 2023 08:35:00 +0000 Subject: [PATCH 036/145] Updates --- README.md | 13 ++++++------- index.ts | 16 ++++++++-------- package.json | 2 +- test/benchmark.js | 6 +++--- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index ad1ac11..07138f9 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning **2023 update:** version 2 has been released, check out [Upgrading](#upgrading) section. It features 4x less code and improved security. Some features have been removed. -Use [**noble-curves**](https://github.com/paulmillr/noble-curves) -now if you need big, audited & optimized library with additional features. -Use **noble-secp256k1** if you need stable, frozen, minimal feature set and smaller attack surface. + +1. Use [**noble-curves**](https://github.com/paulmillr/noble-curves) now if you need audited & optimized library with features like Schnorr & DER. +2. Use **noble-secp256k1** if you need a tiny 9KB stable library with minimal feature set and smaller attack surface. ### This library belongs to _noble_ crypto @@ -284,15 +284,14 @@ Some functionality present in v1, such as schnorr and DER, was removed: use [**n - `getPublicKey()` and `getSharedSecret()` now produce compressed 33-byte signatures by default. If you need the old 65-byte behavior, set `isCompressed` option as `false`: `getPublicKey(priv, false)`, `getSharedSecret(a, b, false)` -- `sign()`: now returns `Signature` instance with `{ r, s, rec }` properties. It could still be passed to `verify` as-is. +- `sign()`: now returns `Signature` instance with `{ r, s, recovery }` properties. It could still be passed to `verify` as-is. - `canonical` has been renamed to `lowS`. The default value is the same as before: `lowS: true` - `recovered` has been removed. Recovery bit is always returned in the `Signature` instance - `der` has been removed. DER encoding is no longer supported. Use compact format (32-byte r + 32-byte s), `Signature` instance methods `toCompactRawBytes` / `toCompactHex()`: `(await sign(msgHash, priv)).toCompactRawBytes()`. Use curves if you still need der - `verify()`: `strict` option has been renamed to `lowS`, default value is still the same - `recoverPublicKey(msgHash, sig, recovery)` has been changed to `sig.recoverPublicKey(msgHash)` -- `Point` has been changed to `PPoint`; which now works in 3d xyz projective coordinates instead of - 2d xy affine. Its methods have been renamed: `multiply` to `mul`, `subtract` to `sub` etc. Use curves if you still need affine point -- schnorr signatures, asn.1 DER, custom precomputes have been removed. Use noble-curves if you need them +- `Point` is now `ProjectivePoint`, working in 3d xyz projective coordinates instead of 2d xy affine +- Removed schnorr signatures, asn.1 DER, custom precomputes. Use noble-curves if you need them - Support for environments that can't parse bigint literals has been removed ## License diff --git a/index.ts b/index.ts index 7a47134..413eabe 100644 --- a/index.ts +++ b/index.ts @@ -29,12 +29,12 @@ let Gpows: Point[] | undefined = undefined; // precomputes for base interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { // Point in 3d xyz projective coords - static readonly BASE = new Point(Gx, Gy, 1n); // generator / base point. - static readonly ZERO = new Point(0n, 1n, 0n); // identity / zero point + static readonly BASE = new Point(Gx, Gy, 1n); // generator / base point. + static readonly ZERO = new Point(0n, 1n, 0n); // identity / zero point constructor(readonly px: bigint, readonly py: bigint, readonly pz = 1n) {} // z is optional - equals(other: Point): boolean { // equality check + equals(other: Point): boolean { // equality check const { px: X1, py: Y1, pz: Z1 } = this; - const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // isPoint() checks class equality + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // isPoint() checks class equality return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); } neg() { return new Point(this.px, mod(-this.py), this.pz); } // negate, flips point over y coord @@ -94,8 +94,8 @@ class Point { // Point in 3d xyz proje multiply(n: bigint) { return this.mul(n); } // Aliases for compatibilty toAffine() { return this.aff(); } assertValidity() { return this.ok(); } - get x() { return this.aff().x; } - get y() { return this.aff().y; } + get x() { return this.aff().x; } // .x, .y will call expensive toAffine. + get y() { return this.aff().y; } // Should be used with care. static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; @@ -270,7 +270,7 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async const reset = () => { v.fill(1); k.fill(0); i = 0; }; const _e = 'drbg: tried 1000 values'; if (asynchronous) { // asynchronous=true - const h = (...b: Bytes[]) => ut.hmacSha256(k, v, ...b); // hmac(k)(v, ...values) + const h = (...b: Bytes[]) => ut.hmacSha256Async(k, v, ...b); // hmac(k)(v, ...values) const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) v = await h(); // v = hmac(K || V) @@ -376,7 +376,7 @@ const ut = { // utilities cr.node ? u8fr(cr.node.randomBytes(len)) : err('CSPRNG not present'); }, hashToPrivateKey, - hmacSha256: async (key: Bytes, ...msgs: Bytes[]): Promise => { + hmacSha256Async: async (key: Bytes, ...msgs: Bytes[]): Promise => { const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! if (cr.web) { // browser built-in version const s = cr.web.subtle; diff --git a/package.json b/package.json index 6640c2b..787cdae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", "version": "2.0.0-pre", - "description": "Fastest JS implementation of secp256k1. Independently audited, high-security, 0-dependency ECDSA signatures", + "description": "Fastest JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures", "files": [ "lib" ], diff --git a/test/benchmark.js b/test/benchmark.js index 3e84679..8813cea 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -16,12 +16,12 @@ run(async () => { const priv2 = '2e63f49054e1e44ccc2e6ef6ce387936efb16158f89cc302a2426e0b7fd66f66'; const pub2 = secp.getPublicKey(priv2, true); const msg = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef'; - const signature = await secp.sign(msg, priv); - await mark('sign', 4000, async () => secp.sign(msg, priv)); + const signature = await secp.signAsync(msg, priv); + await mark('sign', 4000, async () => secp.signAsync(msg, priv)); await mark('verify', 500, () => secp.verify(signature, msg, pub)); await mark('getSharedSecret', 500, () => secp.getSharedSecret(priv, pub2)); await mark('recoverPublicKey', 500, () => signature.recoverPublicKey(msg)); let i = 0; let len = points.length; - await mark('Point.fromHex (decompression)', 10000, () => secp.PPoint.fromHex(points[i++ % len])); + await mark('Point.fromHex (decompression)', 10000, () => secp.ProjectivePoint.fromHex(points[i++ % len])); }); From 021893ab8ef28637e2adbdb4bea312acf4df0372 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 7 Feb 2023 13:23:20 +0000 Subject: [PATCH 037/145] Adjustments --- index.ts | 14 +++++++------- test/index.ts | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/index.ts b/index.ts index 413eabe..8d7b24c 100644 --- a/index.ts +++ b/index.ts @@ -29,9 +29,11 @@ let Gpows: Point[] | undefined = undefined; // precomputes for base interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { // Point in 3d xyz projective coords + constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} // z is optional static readonly BASE = new Point(Gx, Gy, 1n); // generator / base point. static readonly ZERO = new Point(0n, 1n, 0n); // identity / zero point - constructor(readonly px: bigint, readonly py: bigint, readonly pz = 1n) {} // z is optional + get x() { return this.aff().x; } // .x, .y will call expensive toAffine. + get y() { return this.aff().y; } // Should be used with care. equals(other: Point): boolean { // equality check const { px: X1, py: Y1, pz: Z1 } = this; const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // isPoint() checks class equality @@ -94,8 +96,6 @@ class Point { // Point in 3d xyz proje multiply(n: bigint) { return this.mul(n); } // Aliases for compatibilty toAffine() { return this.aff(); } assertValidity() { return this.ok(); } - get x() { return this.aff().x; } // .x, .y will call expensive toAffine. - get y() { return this.aff().y; } // Should be used with care. static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // converts hex string to Uint8Array let p: Point | undefined = undefined; @@ -107,17 +107,17 @@ class Point { // Point in 3d xyz proje const isYOdd = (y & 1n) === 1n; // y² is equivalent left-side. Calculate y²: const headOdd = (head & 1) === 1; // y = √y²; there are two solutions: y, -y if (headOdd !== isYOdd) y = mod(-y); // determine proper solution - p = new Point(x, y); // create 3d point + p = new Point(x, y, 1n); // create point } // Uncompressed points: 65b, start with 0x04 - if (len === 65 && head === 0x04) p = new Point(x, slcNum(tail, fLen, 2 * fLen)); + if (len === 65 && head === 0x04) p = new Point(x, slcNum(tail, fLen, 2 * fLen), 1n); return p ? p.ok() : err('Point is not on curve'); // Verify the result } - toHex(isCompressed = true) { // Converts point to hex string + toHex(isCompressed = true) { // Encodes point to hex string const { x, y } = this.aff(); // Convert to 2d xy affine point const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; // 0x02, 0x03, 0x04 prefix return `${head}${n2h(x)}${isCompressed ? '' : n2h(y)}`; // prefix||x and ||y } - toRawBytes(isCompressed = true) { // Converts point to Uint8Array + toRawBytes(isCompressed = true) { // Encodes point to Uint8Array return h2b(this.toHex(isCompressed)); // Re-use toHex(), convert hex to bytes } static fromPrivateKey(n: bigint | Hex) { // Create point from a private key. Multiply diff --git a/test/index.ts b/test/index.ts index fdaffa8..fc6735c 100644 --- a/test/index.ts +++ b/test/index.ts @@ -370,7 +370,7 @@ describe('secp256k1', () => { const r = 1n; const s = 115792089237316195423570985008687907852837564279074904382605163141518162728904n; - const pub = new Point(x, y); + const pub = new Point(x, y, 1n); const signature = new secp.Signature(2n, 2n); // @ts-ignore signature.r = r; @@ -387,7 +387,7 @@ describe('secp256k1', () => { const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; const r = 104546003225722045112039007203142344920046999340768276760147352389092131869133n; const s = 96900796730960181123786672629079577025401317267213807243199432755332205217369n; - const pub = new Point(x, y).toRawBytes(); + const pub = new Point(x, y, 1n).toRawBytes(); const sig = new secp.Signature(r, s); expect(secp.verify(sig, msg, pub)).toBeFalsy(); }); @@ -397,7 +397,7 @@ describe('secp256k1', () => { const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n; const r = 432420386565659656852420866390673177323n; const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n; - const pub = new Point(x, y).toRawBytes(); + const pub = new Point(x, y, 1n).toRawBytes(); const sig = new secp.Signature(r, s); expect(secp.verify(sig, msg, pub, { lowS: false })).toBeTruthy(); }); From 91192ad8be030beab43e1b4692f5bd017a64b2ff Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 14:03:15 +0000 Subject: [PATCH 038/145] Remove rollup, terser --- package.json | 12 +++--------- rollup.config.js | 13 ------------- 2 files changed, 3 insertions(+), 22 deletions(-) delete mode 100644 rollup.config.js diff --git a/package.json b/package.json index 787cdae..b3939c2 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,6 @@ "scripts": { "build": "tsc && tsc -p tsconfig.esm.json", "build:release": "rollup -c rollup.config.js", - "lint": "prettier --print-width 100 --single-quote --check test/index.ts", - "format": "prettier --print-width 100 --single-quote --write test/index.ts", "test": "jest", "coverage": "jest --coverage", "bench": "node test/benchmark.js", @@ -30,17 +28,13 @@ "crypto": false }, "devDependencies": { - "@noble/hashes": "1.1.2", - "@rollup/plugin-commonjs": "22.0.0", - "@rollup/plugin-node-resolve": "13.3.0", + "@noble/hashes": "1.2.0", "@types/jest": "28.1.1", "@types/node": "17.0.18", "fast-check": "3.0.0", "jest": "28.1.0", - "micro-bmark": "0.2.0", - "prettier": "2.6.2", - "rollup": "2.75.5", - "terser": "^5.16.1", + "micro-bmark": "0.3.0", + "terser": "5.16.1", "ts-jest": "28.0.4", "typescript": "4.7.3" }, diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index a8119a5..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,13 +0,0 @@ -import resolve from '@rollup/plugin-node-resolve'; - -export default { - input: 'lib/esm/index.js', - output: { - file: 'build/noble-secp256k1.js', - format: 'umd', - name: 'nobleSecp256k1', - exports: 'named', - preferConst: true, - }, - plugins: [resolve({ browser: true })], -}; From d4804363aeeb9efd9b10219f70d9370aa9c2f88e Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 14:03:21 +0000 Subject: [PATCH 039/145] Improve exports --- index.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/index.ts b/index.ts index 8d7b24c..a4d7ab7 100644 --- a/index.ts +++ b/index.ts @@ -1,12 +1,12 @@ /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve -const P = B256 - 0x1000003d1n; // curve's field +const P = B256 - 0x1000003d1n; // curve's field prime const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order const _a = 0n; // a equation's param const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables +export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; // accepted inputs: bytes/hex const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _a * x + _b); // x³ + ax + b weierstrass formula @@ -179,10 +179,10 @@ const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Arra return r; }; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 -const getPublicKey = (privKey: Hex | bigint, isCompressed = true) => { // calculate public +export const getPublicKey = (privKey: Hex | bigint, isCompressed = true) => { // calculate public return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; -class Signature { // calculates signature +export class Signature { // calculates signature constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { this.ok(); } ok(): Signature { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n static fromCompact(hex: Hex) { // create signature from 64b compact repr @@ -320,18 +320,18 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async } }; // ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2. hmacDrbg() -const signAsync = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { +export const signAsync = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { const { seed, k2sig } = prepSig(msgh, priv, opts); const genUntil = hmacDrbg(true); return genUntil(seed, k2sig); }; -const signSync = (msgh: Hex, priv: Hex, opts = stdo): Signature => { +export const sign = (msgh: Hex, priv: Hex, opts = stdo): Signature => { const { seed, k2sig } = prepSig(msgh, priv, opts); const genUntil = hmacDrbg(false); return genUntil(seed, k2sig); }; type SigLike = { r: bigint, s: bigint }; -const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): boolean => { +export const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): boolean => { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true if ('strict' in opts) err('verify() legacy options not supported'); // legacy param @@ -358,7 +358,7 @@ const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): boolean const v = mod(R.x, N); return v === r; // mod(R.x, n) == r } -const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true) => { +export const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true) => { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); }; const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation @@ -435,4 +435,3 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() export const ProjectivePoint = Point; export const utils = ut; -export { getPublicKey, signAsync, signSync as sign, verify, getSharedSecret, CURVE, Signature }; From 9011dbab9d012f747cb7e9fb13e6b545f5d8fa30 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 14:03:26 +0000 Subject: [PATCH 040/145] README updates --- README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 07138f9..64af7d0 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ # noble-secp256k1 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) -[Fastest](#speed) JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), +[Fastest](#speed) 9KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). -**2023 update:** version 2 has been released, check out [Upgrading](#upgrading) section. -It features 4x less code and improved security. Some features have been removed. +The library does not use dependencies and is as minimal as possible. [noble-curves](https://github.com/paulmillr/noble-curves) is even faster drop-in replacement for noble-secp256k1 with more features such as Schnorr signatures, DER encoding, support for different hash functions. -1. Use [**noble-curves**](https://github.com/paulmillr/noble-curves) now if you need audited & optimized library with features like Schnorr & DER. -2. Use **noble-secp256k1** if you need a tiny 9KB stable library with minimal feature set and smaller attack surface. +Check out [Upgrading](#upgrading) section for v1 to v2 transition instructions. ### This library belongs to _noble_ crypto @@ -237,14 +235,14 @@ We however consider infrastructure attacks like rogue NPM modules very important ## Speed -Benchmarks measured with Apple M2 on MacOS 12 with node.js 18.10. +Benchmarks measured with Apple M2 on MacOS 13 with node.js 19. - getPublicKey(utils.randomPrivateKey()) x 5,030 ops/sec @ 198μs/op - sign x 4,046 ops/sec @ 247μs/op - verify x 479 ops/sec @ 2ms/op - getSharedSecret x 405 ops/sec @ 2ms/op - recoverPublicKey x 487 ops/sec @ 2ms/op - Point.fromHex (decompression) x 7,642 ops/sec @ 130μs/op + getPublicKey(utils.randomPrivateKey()) x 5,695 ops/sec @ 175μs/op + sign x 4,737 ops/sec @ 211μs/op + verify x 523 ops/sec @ 1ms/op + getSharedSecret x 441 ops/sec @ 2ms/op + recoverPublicKey x 534 ops/sec @ 1ms/op + Point.fromHex (decompression) x 8,538 ops/sec @ 117μs/op Compare to other libraries on M1 (`openssl` uses native bindings, not JS): From e68ba4ba026e097389411cc5950f1256fee24fed Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 15:49:39 +0000 Subject: [PATCH 041/145] Comments --- index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/index.ts b/index.ts index a4d7ab7..82c2619 100644 --- a/index.ts +++ b/index.ts @@ -34,10 +34,12 @@ class Point { // Point in 3d xyz proje static readonly ZERO = new Point(0n, 1n, 0n); // identity / zero point get x() { return this.aff().x; } // .x, .y will call expensive toAffine. get y() { return this.aff().y; } // Should be used with care. - equals(other: Point): boolean { // equality check + equals(other: Point): boolean { // equality check: compare points const { px: X1, py: Y1, pz: Z1 } = this; const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // isPoint() checks class equality - return mod(X1 * Z2) === mod(X2 * Z1) && mod(Y1 * Z2) === mod(Y2 * Z1); + const X1Z2 = mod(X1 * Z2), X2Z1 = mod(X2 * Z1); + const Y1Z2 = mod(Y1 * Z2), Y2Z1 = mod(Y2 * Z1); + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1; } neg() { return new Point(this.px, mod(-this.py), this.pz); } // negate, flips point over y coord dbl() { return this.add(this); } // point doubling @@ -399,7 +401,7 @@ const W = 8; // Precomputes-related c const precompute = () => { // They give 12x faster getPublicKey(), const points: Point[] = []; // 10x sign(), 2x verify(). To achieve this, const windows = 256 / W + 1; // app needs to spend 40ms+ to calculate - let p = G, b = p; // 65536 points related to base point G. + let p = G, b = p; // a lot of points related to base point G. for (let w = 0; w < windows; w++) { // Points are stored in array and used b = p; // any time Gx multiplication is done. points.push(b); // They consume 16-32 MiB of RAM. From 86e4d02a65b55a294681dc3db3a8edeb005ce276 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 19:20:50 +0000 Subject: [PATCH 042/145] Drop jest. Reuse tests from curves --- index.ts | 24 +- package.json | 12 +- test/index.ts | 641 ------------------------------------- test/secp256k1.helpers.mjs | 70 ++++ test/secp256k1.helpers.mts | 66 ++++ test/secp256k1.test.mjs | 536 +++++++++++++++++++++++++++++++ test/tsconfig.json | 6 +- 7 files changed, 692 insertions(+), 663 deletions(-) delete mode 100644 test/index.ts create mode 100644 test/secp256k1.helpers.mjs create mode 100644 test/secp256k1.helpers.mts create mode 100644 test/secp256k1.test.mjs diff --git a/index.ts b/index.ts index 82c2619..7d86b1d 100644 --- a/index.ts +++ b/index.ts @@ -8,7 +8,7 @@ const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length -type Bytes = Uint8Array; type Hex = Bytes | string; // accepted inputs: bytes/hex +type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _a * x + _b); // x³ + ax + b weierstrass formula const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer @@ -21,7 +21,7 @@ const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of spe const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut const toU8 = (a: any, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a -const toPriv = (p: Hex | bigint): bigint => { // normalize private key to bigint +const toPriv = (p: PrivKey): bigint => { // normalize private key to bigint if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; @@ -96,6 +96,7 @@ class Point { // Point in 3d xyz proje this : err('Point invalid: not on curve'); } multiply(n: bigint) { return this.mul(n); } // Aliases for compatibilty + negate() { return this.neg(); } toAffine() { return this.aff(); } assertValidity() { return this.ok(); } static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point @@ -122,7 +123,7 @@ class Point { // Point in 3d xyz proje toRawBytes(isCompressed = true) { // Encodes point to Uint8Array return h2b(this.toHex(isCompressed)); // Re-use toHex(), convert hex to bytes } - static fromPrivateKey(n: bigint | Hex) { // Create point from a private key. Multiply + static fromPrivateKey(n: PrivKey) { // Create point from a private key. Multiply return G.mul(toPriv(n)); // base point by bigint(n) } } @@ -181,7 +182,7 @@ const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Arra return r; }; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 -export const getPublicKey = (privKey: Hex | bigint, isCompressed = true) => { // calculate public +export const getPublicKey = (privKey: PrivKey, isCompressed = true) => { // calculate public return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; export class Signature { // calculates signature @@ -191,6 +192,7 @@ export class Signature { // calculates sig hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } + hasHighS() { return moreThanHalfN(this.s); } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 if (![0, 1, 2, 3].includes(rec!)) err('recovery id invalid'); // check recovery id @@ -216,10 +218,10 @@ const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be us return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets -declare const self: Record | undefined; // Typescript global symbol available in +declare const globalThis: Record | undefined; // Typescript global symbol available in const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependence on @types/dom node: typeof require === 'function' && require('crypto'), // node.js require('crypto') - web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, // browser-only var + web: typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined, // browser-only var }; type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it @@ -296,7 +298,7 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async } else { const h = (...b: Bytes[]) => { // Same, but synchronous const f = _hmacSync; - if (!f) err('utils.hmacSha256 not set'); + if (!f) err('utils.hmacSha256Sync not set'); return f!(k, v, ...b); // hmac(k)(v, ...values) }; const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G @@ -372,7 +374,10 @@ const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compli }; const ut = { // utilities mod, invert: inv, // math utilities - concatBytes: concatB, hexToBytes: h2b, bytesToHex: b2h, bytesToNumber: b2n, numToField: n2b, + concatBytes: concatB, + hexToBytes: h2b, bytesToHex: b2h, + bytesToNumberBE: b2n, numberToBytesBE: n2b, + normPrivateKeyToScalar: toPriv, randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) return cr.web ? cr.web.getRandomValues(u8n(len)) : cr.node ? u8fr(cr.node.randomBytes(len)) : err('CSPRNG not present'); @@ -393,8 +398,9 @@ const ut = { // utilities hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below randomPrivateKey: (): Bytes => hashToPrivateKey(ut.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, + precompute(p: Point) {return p;} }; -Object.defineProperties(ut, { hmacSha256Sync: { // Allow setting it once. Next sets will be ignored +Object.defineProperties(ut, { hmacSha256Sync: { // Allow setting it once, ignore then configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, } }); const W = 8; // Precomputes-related code. W = window size diff --git a/package.json b/package.json index b3939c2..6cfb48d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "tsc && tsc -p tsconfig.esm.json", "build:release": "rollup -c rollup.config.js", - "test": "jest", + "test": "node test/secp256k1.test.mjs", "coverage": "jest --coverage", "bench": "node test/benchmark.js", "min": "terser --ecma 2020 -m -c < lib/esm/index.js", @@ -29,13 +29,11 @@ }, "devDependencies": { "@noble/hashes": "1.2.0", - "@types/jest": "28.1.1", "@types/node": "17.0.18", "fast-check": "3.0.0", - "jest": "28.1.0", "micro-bmark": "0.3.0", + "micro-should": "0.4.0", "terser": "5.16.1", - "ts-jest": "28.0.4", "typescript": "4.7.3" }, "keywords": [ @@ -63,12 +61,6 @@ "default": "./lib/index.js" } }, - "jest": { - "testRegex": "/test/.*?\\.ts", - "transform": { - "^.+\\.ts$": "ts-jest" - } - }, "funding": [ { "type": "individual", diff --git a/test/index.ts b/test/index.ts deleted file mode 100644 index fc6735c..0000000 --- a/test/index.ts +++ /dev/null @@ -1,641 +0,0 @@ -import * as fc from 'fast-check'; -import * as secp from '..'; -import { readFileSync } from 'fs'; -import { createHash } from 'crypto'; -// import { createHash } from 'crypto'; -import * as sysPath from 'path'; -import * as ecdsa from './vectors/ecdsa.json'; -import * as ecdh from './vectors/ecdh.json'; -import * as privates from './vectors/privates.json'; -import * as points from './vectors/points.json'; -import * as wp from './vectors/wychenproof.json'; -const privatesTxt = readFileSync(sysPath.join(__dirname, 'vectors', 'privates-2.txt'), 'utf-8'); -const schCsv = readFileSync(sysPath.join(__dirname, 'vectors', 'schnorr.csv'), 'utf-8'); - -const FC_BIGINT = fc.bigInt(1n + 1n, secp.CURVE.n - 1n); -// prettier-ignore -const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxy', secp.CURVE.n + 2n]; - -// secp.utils.sha256Sync = (...msgs) => -// createHash('sha256') -// .update(secp.utils.concatBytes(...msgs)) -// .digest(); - -const toBEHex = (n: number | bigint) => n.toString(16).padStart(64, '0'); -const hex = secp.utils.bytesToHex; -const hexToBytes = secp.utils.hexToBytes; -const Point = secp.ProjectivePoint; - -const { bytesToNumber: b2n, hexToBytes: h2b } = secp.utils; -const DER = { - // asn.1 DER encoding utils - Err: class DERErr extends Error { - constructor(m = '') { - super(m); - } - }, - _parseInt(data: Uint8Array): { d: bigint; l: Uint8Array } { - const { Err: E } = DER; - if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag'); - const len = data[1]; - const res = data.subarray(2, len + 2); - if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length'); - if (res[0] === 0x00 && res[1] <= 0x7f) - throw new E('Invalid signature integer: trailing length'); - // ^ Weird condition: not about length, but about first bytes of number. - return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left - }, - toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { - // parse DER signature - const { Err: E } = DER; - const data = typeof hex === 'string' ? h2b(hex) : hex; - if (!(data instanceof Uint8Array)) throw new Error('ui8a expected'); - let l = data.length; - if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); - if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); - const { d: r, l: sBytes } = DER._parseInt(data.subarray(2)); - const { d: s, l: rBytesLeft } = DER._parseInt(sBytes); - if (rBytesLeft.length) throw new E('Invalid signature: left bytes after parsing'); - return { r, s }; - }, - hexFromSig(sig: { r: bigint; s: bigint }): string { - const slice = (s: string): string => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER - const h = (num: number | bigint) => { - const hex = num.toString(16); - return hex.length & 1 ? `0${hex}` : hex; - }; - const s = slice(h(sig.s)); - const r = slice(h(sig.r)); - const shl = s.length / 2; - const rhl = r.length / 2; - const sl = h(shl); - const rl = h(rhl); - return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; - }, -}; - -function hexToNumber(hex: string): bigint { - if (typeof hex !== 'string') { - throw new TypeError('hexToNumber: expected string, got ' + typeof hex); - } - // Big Endian - return BigInt(`0x${hex}`); -} - -describe('secp256k1', () => { - it('.getPublicKey()', () => { - const data = privatesTxt - .split('\n') - .filter((line) => line) - .map((line) => line.split(':')); - for (let [priv, x, y] of data) { - const { x: x1, y: y1 } = Point.fromPrivateKey(BigInt(priv)).aff(); - expect(toBEHex(x1)).toBe(x); - expect(toBEHex(y1)).toBe(y); - - const { x: x2, y: y2 } = Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))).aff(); - expect(toBEHex(x2)).toBe(x); - expect(toBEHex(y2)).toBe(y); - - const { x: x3, y: y3 } = Point.fromHex( - secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv)))) - ).aff(); - expect(toBEHex(x3)).toBe(x); - expect(toBEHex(y3)).toBe(y); - } - }); - it('.getPublicKey() rejects invalid keys', () => { - for (const item of INVALID_ITEMS) { - expect(() => secp.getPublicKey(item as any)).toThrowError(); - } - }); - // it('precompute', () => { - // // secp.utils.precompute(4); - // const data = privatesTxt - // .split('\n') - // .filter((line) => line) - // .map((line) => line.split(':')); - // for (let [priv, x, y] of data) { - // const point = secp.Point.fromPrivateKey(BigInt(priv)); - // expect(toBEHex(point.x)).toBe(x); - // expect(toBEHex(point.y)).toBe(y); - - // const point2 = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))); - // expect(toBEHex(point2.x)).toBe(x); - // expect(toBEHex(point2.y)).toBe(y); - - // const point3 = secp.Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv))))); - // expect(toBEHex(point3.x)).toBe(x); - // expect(toBEHex(point3.y)).toBe(y); - // } - // }); - describe('Point', () => { - it('.isValidPoint()', () => { - for (const vector of points.valid.isPoint) { - const { P, expected } = vector; - if (expected) { - Point.fromHex(P); - } else { - expect(() => Point.fromHex(P)).toThrowError(); - } - } - }); - - it('.fromPrivateKey()', () => { - for (const vector of points.valid.pointFromScalar) { - const { d, expected } = vector; - let p = Point.fromPrivateKey(d); - expect(p.toHex(true)).toBe(expected); - } - }); - - it('#toHex(compressed)', () => { - for (const vector of points.valid.pointCompress) { - const { P, compress, expected } = vector; - let p = Point.fromHex(P); - expect(p.toHex(compress)).toBe(expected); - } - }); - - it('#toHex() roundtrip', () => { - fc.assert( - fc.property(FC_BIGINT, (x) => { - const point1 = Point.fromPrivateKey(x); - const hex = point1.toHex(true); - expect(Point.fromHex(hex).toHex(true)).toBe(hex); - }) - ); - }); - - it('#add(other)', () => { - for (const vector of points.valid.pointAdd) { - const { P, Q, expected } = vector; - let p = Point.fromHex(P); - let q = Point.fromHex(Q); - if (expected) { - expect(p.add(q).toHex(true)).toBe(expected); - } else { - if (p.equals(q.neg())) { - expect(p.add(q).toHex(true)).toBe(Point.ZERO.toHex(true)); - } else { - expect(() => p.add(q).toHex(true)).toThrowError(); - } - } - } - }); - - it('#multiply(privateKey)', () => { - for (const vector of points.valid.pointMultiply) { - const { P, d, expected } = vector; - const p = Point.fromHex(P); - if (expected) { - expect(p.mul(hexToNumber(d)).toHex(true)).toBe(expected); - } else { - expect(() => { - p.mul(hexToNumber(d)).toHex(true); - }).toThrowError(); - } - } - - for (const vector of points.invalid.pointMultiply) { - const { P, d } = vector; - if (hexToNumber(d) < secp.CURVE.n) { - expect(() => { - const p = Point.fromHex(P); - p.mul(hexToNumber(d)).toHex(true); - }).toThrowError(); - } - } - for (const num of [0n, 0, -1n, -1, 1.1]) { - // @ts-ignore - expect(() => Point.BASE.multiply(num)).toThrowError(); - } - }); - - // multiply() should equal multiplyUnsafe() - // it('JacobianPoint#multiplyUnsafe', () => { - // const p0 = new secp.JacobianPoint( - // 55066263022277343669578718895168534326250603453777594175500187360389116729240n, - // 32670510020758816978083085130507043184471273380659243275938904335757337482424n, - // 1n - // ); - // const z = 106011723082030650010038151861333186846790370053628296836951575624442507889495n; - // console.log(p0.multiply(z)); - // console.log(secp.JacobianPoint.normalizeZ([p0.multiplyUnsafe(z)])[0]) - // }); - }); - - describe('Signature', () => { - it('.fromCompactHex() roundtrip', () => { - fc.assert( - fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { - const sig = new secp.Signature(r, s); - expect(secp.Signature.fromCompact(sig.toCompactHex())).toEqual(sig); - }) - ); - }); - - it('.fromDERHex() roundtrip', () => { - fc.assert( - fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { - const sig = new secp.Signature(r, s); - expect(DER.toSig(DER.hexFromSig(sig))).toEqual(sig); - }) - ); - }); - }); - - describe('.sign()', () => { - it('should create deterministic signatures with RFC 6979', async () => { - for (const vector of ecdsa.valid) { - let usig = await secp.signAsync(vector.m, vector.d); - let sig = usig.toCompactHex(); - const vsig = vector.signature; - expect(sig.slice(0, 64)).toBe(vsig.slice(0, 64)); - expect(sig.slice(64, 128)).toBe(vsig.slice(64, 128)); - } - }); - - it('should not create invalid deterministic signatures with RFC 6979', async () => { - for (const vector of ecdsa.invalid.sign) { - expect(() => { - return secp.signAsync(vector.m, vector.d); - }).rejects.toThrowError(); - } - }); - - it('edge cases', () => { - // @ts-ignore - expect(async () => await secp.signAsync()).rejects.toThrowError(); - // @ts-ignore - expect(async () => await secp.signAsync('')).rejects.toThrowError(); - }); - - it('should create correct DER encoding against libsecp256k1', async () => { - const CASES = [ - [ - 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', - '304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b', - ], - [ - '5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82', - '3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c', - ], - [ - '0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808', - '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', - ], - ]; - const privKey = hexToBytes( - '0101010101010101010101010101010101010101010101010101010101010101' - ); - for (let [msg, exp] of CASES) { - const res = await secp.signAsync(msg, privKey, { extraEntropy: undefined }); - const derRes = DER.hexFromSig(res); - expect(derRes).toBe(exp); - const derRes2 = DER.toSig(derRes); - expect(DER.hexFromSig(derRes2)).toBe(exp); - } - }); - it('sign ecdsa extraData', async () => { - const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; - const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; - const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; - const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; - const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - - for (const e of ecdsa.extraEntropy) { - const sign = async (extraEntropy?: string) => { - const s = await secp.signAsync(e.m, e.d, { extraEntropy }); - return s.toCompactHex(); - }; - expect(await sign()).toBe(e.signature); - expect(await sign(ent1)).toBe(e.extraEntropy0); - expect(await sign(ent2)).toBe(e.extraEntropy1); - expect(await sign(ent3)).toBe(e.extraEntropyRand); - expect(await sign(ent4)).toBe(e.extraEntropyN); - expect(await sign(ent5)).toBe(e.extraEntropyMax); - } - }); - }); - - describe('.verify()', () => { - it('should verify signature', async () => { - const MSG = '01'.repeat(32); - const PRIV_KEY = secp.utils.numToField(0x2n); - const signature = await secp.signAsync(MSG, PRIV_KEY); - const publicKey = secp.getPublicKey(PRIV_KEY); - expect(publicKey.length).toBe(33); - expect(secp.verify(signature, MSG, publicKey)).toBe(true); - }); - it('should not verify signature with wrong public key', async () => { - const MSG = '01'.repeat(32); - const PRIV_KEY = secp.utils.numToField(0x2n); - const WRONG_PRIV_KEY = secp.utils.numToField(0x22n); - const signature = await secp.signAsync(MSG, PRIV_KEY); - const publicKey = Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); - expect(publicKey.length).toBe(66); - expect(secp.verify(signature, MSG, publicKey)).toBe(false); - }); - it('should not verify signature with wrong hash', async () => { - const MSG = '01'.repeat(32); - const PRIV_KEY = secp.utils.numToField(0x2n); - const WRONG_MSG = '11'.repeat(32); - const signature = await secp.signAsync(MSG, PRIV_KEY); - const publicKey = secp.getPublicKey(PRIV_KEY); - expect(publicKey.length).toBe(33); - expect(secp.verify(signature, WRONG_MSG, publicKey)).toBe(false); - }); - it('should verify random signatures', async () => - fc.assert( - fc.asyncProperty( - FC_BIGINT, - fc.hexaString({ minLength: 64, maxLength: 64 }), - async (privKey, msg) => { - const pk = secp.utils.numToField(privKey); - const pub = secp.getPublicKey(pk); - const sig = await secp.signAsync(msg, pk); - expect(secp.verify(sig, msg, pub)).toBeTruthy(); - } - ) - )); - it('should not verify signature with invalid r/s', () => { - const msg = new Uint8Array([ - 0xbb, 0x5a, 0x52, 0xf4, 0x2f, 0x9c, 0x92, 0x61, 0xed, 0x43, 0x61, 0xf5, 0x94, 0x22, 0xa1, - 0xe3, 0x00, 0x36, 0xe7, 0xc3, 0x2b, 0x27, 0x0c, 0x88, 0x07, 0xa4, 0x19, 0xfe, 0xca, 0x60, - 0x50, 0x23, - ]); - const x = 100260381870027870612475458630405506840396644859280795015145920502443964769584n; - const y = 41096923727651821103518389640356553930186852801619204169823347832429067794568n; - const r = 1n; - const s = 115792089237316195423570985008687907852837564279074904382605163141518162728904n; - - const pub = new Point(x, y, 1n); - const signature = new secp.Signature(2n, 2n); - // @ts-ignore - signature.r = r; - // @ts-ignore - signature.s = s; - - const verified = secp.verify(signature, msg, pub.toRawBytes()); - // Verifies, but it shouldn't, because signature S > curve order - expect(verified).toBeFalsy(); - }); - it('should not verify msg = curve order', async () => { - const msg = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; - const x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n; - const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; - const r = 104546003225722045112039007203142344920046999340768276760147352389092131869133n; - const s = 96900796730960181123786672629079577025401317267213807243199432755332205217369n; - const pub = new Point(x, y, 1n).toRawBytes(); - const sig = new secp.Signature(r, s); - expect(secp.verify(sig, msg, pub)).toBeFalsy(); - }); - it('should verify non-strict msg bb5a...', async () => { - const msg = 'bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023'; - const x = 3252872872578928810725465493269682203671229454553002637820453004368632726370n; - const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n; - const r = 432420386565659656852420866390673177323n; - const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n; - const pub = new Point(x, y, 1n).toRawBytes(); - const sig = new secp.Signature(r, s); - expect(secp.verify(sig, msg, pub, { lowS: false })).toBeTruthy(); - }); - it('should not verify invalid deterministic signatures with RFC 6979', () => { - for (const vector of ecdsa.invalid.verify) { - const res = secp.verify(vector.signature, vector.m, vector.Q); - expect(res).toBeFalsy(); - } - }); - }); - - // describe('schnorr', () => { - // // index,secret key,public key,aux_rand,message,signature,verification result,comment - // const vectors = schCsv - // .split('\n') - // .map((line: string) => line.split(',')) - // .slice(1, -1); - // for (let vec of vectors) { - // const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec; - // it(`should sign with Schnorr scheme vector ${index}`, async () => { - // if (sec) { - // expect(hex(secp.schnorr.getPublicKey(sec))).toBe(pub.toLowerCase()); - // const sig = await secp.schnorr.sign(msg, sec, rnd); - // const sigS = secp.schnorr.signSync(msg, sec, rnd); - // expect(hex(sig)).toBe(expSig.toLowerCase()); - // expect(hex(sigS)).toBe(expSig.toLowerCase()); - // expect(await secp.schnorr.verify(sigS, msg, pub)).toBe(true); - // expect(secp.schnorr.verifySync(sig, msg, pub)).toBe(true); - // } else { - // const passed = await secp.schnorr.verify(expSig, msg, pub); - // const passedS = secp.schnorr.verifySync(expSig, msg, pub); - // if (passes === 'TRUE') { - // expect(passed).toBeTruthy(); - // expect(passedS).toBeTruthy(); - // } else { - // expect(passed).toBeFalsy(); - // expect(passedS).toBeFalsy(); - // } - // } - // }); - // } - // }); - - describe('.recoverPublicKey()', () => { - it('should recover public key from recovery bit', async () => { - const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; - const privateKey = secp.utils.numToField(123456789n); - const publicKey = Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); - const sig = await secp.signAsync(message, privateKey); - const recoveredPubkey = sig.recoverPublicKey(message); - expect(recoveredPubkey).not.toBe(null); - expect(recoveredPubkey.toHex(false)).toBe(publicKey); - expect(secp.verify(sig, message, publicKey)).toBe(true); - }); - it('should not recover zero points', () => { - const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; - const sig = - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; - const recovery = 0; - const sigi = secp.Signature.fromCompact(sig); - const sigir = new secp.Signature(sigi.r, sigi.s, recovery); - expect(() => sigir.recoverPublicKey(msgHash)).toThrowError(); - }); - it('should handle all-zeros msghash', async () => { - const privKey = secp.utils.randomPrivateKey(); - const pub = secp.getPublicKey(privKey); - const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; - const sig = await secp.signAsync(zeros, privKey); - const recoveredKey = sig.recoverPublicKey(zeros); - expect(recoveredKey.toRawBytes()).toEqual(pub); - }); - it('should handle RFC 6979 vectors', async () => { - for (const vector of ecdsa.valid) { - if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue; - let sig = await secp.signAsync(vector.m, vector.d); - // let sig = hex(usig); - const vpub = secp.getPublicKey(vector.d); - const recovered = sig.recoverPublicKey(vector.m)!; - expect(recovered.toHex()).toBe(hex(vpub)); - } - }); - }); - - describe('.getSharedSecret()', () => { - // TODO: Real implementation. - function derToPub(der: string) { - return der.slice(46); - } - it('should produce correct results', () => { - // TODO: Once der is there, run all tests. - for (const vector of ecdh.testGroups[0].tests.slice(0, 230)) { - if (vector.result === 'invalid' || vector.private.length !== 64) { - expect(() => { - secp.getSharedSecret(vector.private, derToPub(vector.public), true); - }).toThrowError(); - } else if (vector.result === 'valid') { - const res = secp.getSharedSecret(vector.private, derToPub(vector.public), true); - expect(hex(res.slice(1))).toBe(`${vector.shared}`); - } - } - }); - it('priv/pub order matters', () => { - for (const vector of ecdh.testGroups[0].tests.slice(0, 100)) { - if (vector.result === 'valid') { - let priv = vector.private; - priv = priv.length === 66 ? priv.slice(2) : priv; - expect(() => secp.getSharedSecret(derToPub(vector.public), priv, true)).toThrowError(); - } - } - }); - it('rejects invalid keys', () => { - expect(() => secp.getSharedSecret('01', '02')).toThrowError(); - }); - }); - - describe('utils', () => { - it('isValidPrivateKey()', () => { - // @ts-ignore - for (const vector of privates.valid.isPrivate) { - const { d, expected } = vector; - expect(secp.utils.isValidPrivateKey(d)).toBe(expected); - } - }); - // const normal = secp.utils._normalizePrivateKey; - const normal = (a: any) => { - if (typeof a === 'string') a = secp.utils.hexToBytes(a); - if (a instanceof Uint8Array) return secp.utils.bytesToNumber(a); - if (typeof a === 'number' || typeof a === 'bigint') return BigInt(a); - throw new Error(); - }; - type Hex = string | Uint8Array; - type PrivKey = Hex | bigint | number; - const tweakUtils = { - privateAdd: (privateKey: PrivKey, tweak: Hex): Uint8Array => { - const p = normal(privateKey); - const t = normal(tweak); - return secp.utils.numToField(secp.utils.mod(p + t, secp.CURVE.n)); - }, - - privateNegate: (privateKey: PrivKey): Uint8Array => { - const p = normal(privateKey); - return secp.utils.numToField(secp.CURVE.n - p); - }, - - pointAddScalar: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { - const P = Point.fromHex(p); - const t = normal(tweak); - const Q = P.add(Point.BASE.mul(t)); - // const Q = Point.BASE.multiplyAndAddUnsafe(P, t, 1n); - if (!Q || Q.equals(Point.ZERO)) throw new Error('Tweaked point at infinity'); - return Q.toRawBytes(isCompressed); - }, - - pointMultiply: (p: Hex, tweak: Hex, isCompressed?: boolean): Uint8Array => { - const P = Point.fromHex(p); - const h = typeof tweak === 'string' ? tweak : secp.utils.bytesToHex(tweak); - const t = BigInt(`0x${h}`); - return P.mul(t).toRawBytes(isCompressed); - }, - }; - - it('privateAdd()', () => { - // @ts-ignore - for (const vector of privates.valid.add) { - const { a, b, expected } = vector; - expect(secp.utils.bytesToHex(tweakUtils.privateAdd(a, b))).toBe(expected); - } - }); - it('privateNegate()', () => { - // @ts-ignore - for (const vector of privates.valid.negate) { - const { a, expected } = vector; - expect(secp.utils.bytesToHex(tweakUtils.privateNegate(a))).toBe(expected); - } - }); - it('pointAddScalar()', () => { - for (const vector of points.valid.pointAddScalar) { - const { description, P, d, expected } = vector; - const compressed = !!expected && expected.length === 66; // compressed === 33 bytes - expect(secp.utils.bytesToHex(tweakUtils.pointAddScalar(P, d, compressed))).toBe(expected); - } - }); - it('pointAddScalar() invalid', () => { - for (const vector of points.invalid.pointAddScalar) { - const { P, d, exception } = vector; - expect(() => tweakUtils.pointAddScalar(P, d)).toThrowError(); - } - }); - it('pointMultiply()', () => { - for (const vector of points.valid.pointMultiply) { - const { P, d, expected } = vector; - expect(secp.utils.bytesToHex(tweakUtils.pointMultiply(P, d, true))).toBe(expected); - } - }); - it('pointMultiply() invalid', () => { - for (const vector of points.invalid.pointMultiply) { - const { P, d, exception } = vector; - expect(() => tweakUtils.pointMultiply(P, d)).toThrowError(); - } - }); - }); - - describe('wychenproof vectors', () => { - const sha256 = (m: Uint8Array) => Uint8Array.from(createHash('sha256').update(m).digest()); - it('should pass all tests', async () => { - for (let group of wp.testGroups) { - const pubKey = Point.fromHex(group.key.uncompressed); - for (let test of group.tests) { - const m = sha256(hexToBytes(test.msg)); - if (test.result === 'valid' || test.result === 'acceptable') { - const parsed = DER.toSig(test.sig); - const verified = secp.verify(parsed, m, group.key.uncompressed); - if (parsed.s > secp.CURVE.n >> 1n) { - expect(verified).toBeFalsy(); - } else { - expect(verified).toBeTruthy(); - } - } else if (test.result === 'invalid') { - let failed = false; - try { - const verified = secp.verify(test.sig, m, group.key.uncompressed); - if (!verified) failed = true; - } catch (error) { - failed = true; - } - expect(failed).toBeTruthy(); - } else { - expect(false).toBeTruthy(); - } - } - } - }); - }); -}); - -// describe('JacobianPoint', () => { -// const JZERO = Point.ZERO; -// const AZERO = { x: 0n, y: 0n }; -// expect(AZERO.equals(JZERO)).toBeTruthy(); -// expect(AZERO.toAffine().equals(JZERO.toAffine())).toBeTruthy(); -// }); diff --git a/test/secp256k1.helpers.mjs b/test/secp256k1.helpers.mjs new file mode 100644 index 0000000..a57df37 --- /dev/null +++ b/test/secp256k1.helpers.mjs @@ -0,0 +1,70 @@ +// @ts-ignore +export * as secp from '../lib/esm/index.js'; +// @ts-ignore +import * as secp256k1 from '../lib/esm/index.js'; +import { hmac } from '@noble/hashes/hmac'; +import { sha256 } from '@noble/hashes/sha256'; +secp256k1.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)); +const { bytesToNumberBE: b2n, hexToBytes: h2b } = secp256k1.utils; +export const DER = { + // asn.1 DER encoding utils + Err: class DERErr extends Error { + constructor(m = '') { + super(m); + } + }, + _parseInt(data) { + const { Err: E } = DER; + if (data.length < 2 || data[0] !== 0x02) + throw new E('Invalid signature integer tag'); + const len = data[1]; + const res = data.subarray(2, len + 2); + if (!len || res.length !== len) + throw new E('Invalid signature integer: wrong length'); + if (res[0] === 0x00 && res[1] <= 0x7f) + throw new E('Invalid signature integer: trailing length'); + // ^ Weird condition: not about length, but about first bytes of number. + return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left + }, + toSig(hex) { + // parse DER signature + const { Err: E } = DER; + const data = typeof hex === 'string' ? h2b(hex) : hex; + if (!(data instanceof Uint8Array)) + throw new Error('ui8a expected'); + let l = data.length; + if (l < 2 || data[0] != 0x30) + throw new E('Invalid signature tag'); + if (data[1] !== l - 2) + throw new E('Invalid signature: incorrect length'); + const { d: r, l: sBytes } = DER._parseInt(data.subarray(2)); + const { d: s, l: rBytesLeft } = DER._parseInt(sBytes); + if (rBytesLeft.length) + throw new E('Invalid signature: left bytes after parsing'); + return { r, s }; + }, + hexFromSig(sig) { + const slice = (s) => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER + const h = (num) => { + const hex = num.toString(16); + return hex.length & 1 ? `0${hex}` : hex; + }; + const s = slice(h(sig.s)); + const r = slice(h(sig.r)); + const shl = s.length / 2; + const rhl = r.length / 2; + const sl = h(shl); + const rl = h(rhl); + return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; + }, +}; +export const sigFromDER = (der) => { + const { r, s } = DER.toSig(der); + return new secp256k1.Signature(r, s); +}; +export const sigToDER = (sig) => DER.hexFromSig(sig); +export const selectHash = (secp) => sha256; +export const normVerifySig = (s) => DER.toSig(s); +export const bytesToNumberBE = secp256k1.utils.bytesToNumberBE; +export const numberToBytesBE = secp256k1.utils.numberToBytesBE; +export const mod = secp256k1.utils.mod; diff --git a/test/secp256k1.helpers.mts b/test/secp256k1.helpers.mts new file mode 100644 index 0000000..fc2d8b0 --- /dev/null +++ b/test/secp256k1.helpers.mts @@ -0,0 +1,66 @@ +// @ts-ignore +export * as secp from '../lib/esm/index.js'; +// @ts-ignore +import * as secp256k1 from '../lib/esm/index.js'; +import { hmac } from '@noble/hashes/hmac'; +import { sha256 } from '@noble/hashes/sha256'; +secp256k1.utils.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) + +const { bytesToNumberBE: b2n, hexToBytes: h2b } = secp256k1.utils; +export const DER = { + // asn.1 DER encoding utils + Err: class DERErr extends Error { + constructor(m = '') { + super(m); + } + }, + _parseInt(data: Uint8Array): { d: bigint; l: Uint8Array } { + const { Err: E } = DER; + if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag'); + const len = data[1]; + const res = data.subarray(2, len + 2); + if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length'); + if (res[0] === 0x00 && res[1] <= 0x7f) + throw new E('Invalid signature integer: trailing length'); + // ^ Weird condition: not about length, but about first bytes of number. + return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left + }, + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { + // parse DER signature + const { Err: E } = DER; + const data = typeof hex === 'string' ? h2b(hex) : hex; + if (!(data instanceof Uint8Array)) throw new Error('ui8a expected'); + let l = data.length; + if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); + if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); + const { d: r, l: sBytes } = DER._parseInt(data.subarray(2)); + const { d: s, l: rBytesLeft } = DER._parseInt(sBytes); + if (rBytesLeft.length) throw new E('Invalid signature: left bytes after parsing'); + return { r, s }; + }, + hexFromSig(sig: { r: bigint; s: bigint }): string { + const slice = (s: string): string => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER + const h = (num: number | bigint) => { + const hex = num.toString(16); + return hex.length & 1 ? `0${hex}` : hex; + }; + const s = slice(h(sig.s)); + const r = slice(h(sig.r)); + const shl = s.length / 2; + const rhl = r.length / 2; + const sl = h(shl); + const rl = h(rhl); + return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; + }, +}; + +export const sigFromDER = (der: string | Uint8Array) => { + const { r, s } = DER.toSig(der); + return new secp256k1.Signature(r, s); +}; +export const sigToDER = (sig: any) => DER.hexFromSig(sig); +export const selectHash = (secp: any) => sha256; +export const normVerifySig = (s: any) => DER.toSig(s); +export const bytesToNumberBE = secp256k1.utils.bytesToNumberBE; +export const numberToBytesBE = secp256k1.utils.numberToBytesBE; +export const mod = secp256k1.utils.mod; diff --git a/test/secp256k1.test.mjs b/test/secp256k1.test.mjs new file mode 100644 index 0000000..87a8fb3 --- /dev/null +++ b/test/secp256k1.test.mjs @@ -0,0 +1,536 @@ +import { hexToBytes, bytesToHex as hex } from '@noble/hashes/utils'; +import { deepStrictEqual, throws } from 'assert'; +import * as fc from 'fast-check'; +import { readFileSync } from 'fs'; +import { should, describe } from 'micro-should'; +// prettier-ignore +import { + secp, sigFromDER, sigToDER, selectHash, normVerifySig, mod, bytesToNumberBE, numberToBytesBE +} from './secp256k1.helpers.mjs'; + +import { default as ecdsa } from './vectors/ecdsa.json' assert { type: 'json' }; +import { default as ecdh } from './vectors/ecdh.json' assert { type: 'json' }; +import { default as privates } from './vectors/privates.json' assert { type: 'json' }; +import { default as points } from './vectors/points.json' assert { type: 'json' }; +import { default as wp } from './vectors/wychenproof.json' assert { type: 'json' }; + +const Point = secp.ProjectivePoint; +const privatesTxt = readFileSync('./test/vectors/privates-2.txt', 'utf-8'); + +const FC_BIGINT = fc.bigInt(1n + 1n, secp.CURVE.n - 1n); +// prettier-ignore +const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxy', secp.CURVE.n + 2n]; + +const toBEHex = (n) => n.toString(16).padStart(64, '0'); + +function hexToNumber(hex) { + if (typeof hex !== 'string') { + throw new Error('hexToNumber: expected string, got ' + typeof hex); + } + // Big Endian + return BigInt(`0x${hex}`); +} + +describe('secp256k1', () => { + should('getPublicKey()', () => { + const data = privatesTxt + .split('\n') + .filter((line) => line) + .map((line) => line.split(':')); + for (let [priv, x, y] of data) { + const point = Point.fromPrivateKey(BigInt(priv)); + deepStrictEqual(toBEHex(point.x), x); + deepStrictEqual(toBEHex(point.y), y); + + const point2 = Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))); + deepStrictEqual(toBEHex(point2.x), x); + deepStrictEqual(toBEHex(point2.y), y); + + const point3 = Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv))))); + deepStrictEqual(toBEHex(point3.x), x); + deepStrictEqual(toBEHex(point3.y), y); + } + }); + should('getPublicKey() rejects invalid keys', () => { + for (const item of INVALID_ITEMS) { + throws(() => secp.getPublicKey(item)); + } + }); + should('precompute', () => { + secp.utils.precompute(4); + const data = privatesTxt + .split('\n') + .filter((line) => line) + .map((line) => line.split(':')); + for (let [priv, x, y] of data) { + const point = Point.fromPrivateKey(BigInt(priv)); + deepStrictEqual(toBEHex(point.x), x); + deepStrictEqual(toBEHex(point.y), y); + + const point2 = Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv)))); + deepStrictEqual(toBEHex(point2.x), x); + deepStrictEqual(toBEHex(point2.y), y); + + const point3 = Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv))))); + deepStrictEqual(toBEHex(point3.x), x); + deepStrictEqual(toBEHex(point3.y), y); + } + }); + + describe('Point', () => { + should('fromHex() assertValidity', () => { + for (const vector of points.valid.isPoint) { + const { P, expected } = vector; + if (expected) { + Point.fromHex(P); + } else { + throws(() => Point.fromHex(P)); + } + } + }); + + should('.fromPrivateKey()', () => { + for (const vector of points.valid.pointFromScalar) { + const { d, expected } = vector; + let p = Point.fromPrivateKey(d); + deepStrictEqual(p.toHex(true), expected); + } + }); + + should('#toHex(compressed)', () => { + for (const vector of points.valid.pointCompress) { + const { P, compress, expected } = vector; + let p = Point.fromHex(P); + deepStrictEqual(p.toHex(compress), expected); + } + }); + + should('#toHex() roundtrip (failed case)', () => { + const point1 = + Point.fromPrivateKey( + 88572218780422190464634044548753414301110513745532121983949500266768436236425n + ); + // const hex = point1.toHex(true); + // deepStrictEqual(Point.fromHex(hex).toHex(true), hex); + }); + + should('#toHex() roundtrip', () => { + fc.assert( + fc.property(FC_BIGINT, (x) => { + const point1 = Point.fromPrivateKey(x); + const hex = point1.toHex(true); + deepStrictEqual(Point.fromHex(hex).toHex(true), hex); + }) + ); + }); + + should('#add(other)', () => { + for (const vector of points.valid.pointAdd) { + const { P, Q, expected } = vector; + let p = Point.fromHex(P); + let q = Point.fromHex(Q); + if (expected) { + deepStrictEqual(p.add(q).toHex(true), expected); + } else { + if (!p.equals(q.negate())) { + throws(() => p.add(q).toHex(true)); + } + } + } + }); + + should('#multiply(privateKey)', () => { + for (const vector of points.valid.pointMultiply) { + const { P, d, expected } = vector; + const p = Point.fromHex(P); + if (expected) { + deepStrictEqual(p.multiply(hexToNumber(d)).toHex(true), expected, P); + } else { + throws(() => { + p.multiply(hexToNumber(d)).toHex(true); + }); + } + } + + for (const vector of points.invalid.pointMultiply) { + const { P, d } = vector; + if (hexToNumber(d) < secp.CURVE.n) { + throws(() => { + const p = Point.fromHex(P); + p.multiply(hexToNumber(d)).toHex(true); + }); + } + } + for (const num of [0n, 0, -1n, -1, 1.1]) { + throws(() => Point.BASE.multiply(num)); + } + }); + }); + + // multiply() should equal multiplyUnsafe() + // should('ProjectivePoint#multiplyUnsafe', () => { + // const p0 = new secp.ProjectivePoint( + // 55066263022277343669578718895168534326250603453777594175500187360389116729240n, + // 32670510020758816978083085130507043184471273380659243275938904335757337482424n, + // 1n + // ); + // const z = 106011723082030650010038151861333186846790370053628296836951575624442507889495n; + // console.log(p0.multiply(z)); + // console.log(secp.ProjectivePoint.normalizeZ([p0.multiplyUnsafe(z)])[0]) + // }); + describe('Signature', () => { + should('.fromCompactHex() roundtrip', () => { + fc.assert( + fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { + const sig = new secp.Signature(r, s); + deepStrictEqual(secp.Signature.fromCompact(sig.toCompactHex()), sig); + }) + ); + }); + + should('.fromDERHex() roundtrip', () => { + fc.assert( + fc.property(FC_BIGINT, FC_BIGINT, (r, s) => { + const sig = new secp.Signature(r, s); + deepStrictEqual(sigFromDER(sigToDER(sig)), sig); + }) + ); + }); + }); + + describe('sign()', () => { + should('create deterministic signatures with RFC 6979', () => { + for (const vector of ecdsa.valid) { + let usig = secp.sign(vector.m, vector.d); + let sig = usig.toCompactHex(); + const vsig = vector.signature; + deepStrictEqual(sig.slice(0, 64), vsig.slice(0, 64)); + deepStrictEqual(sig.slice(64, 128), vsig.slice(64, 128)); + } + }); + + should('not create invalid deterministic signatures with RFC 6979', () => { + for (const vector of ecdsa.invalid.sign) { + throws(() => secp.sign(vector.m, vector.d)); + } + }); + + should('edge cases', () => { + throws(() => secp.sign()); + throws(() => secp.sign('')); + }); + + should('create correct DER encoding against libsecp256k1', () => { + const CASES = [ + [ + 'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b', + '304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b', + ], + [ + '5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82', + '3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c', + ], + [ + '0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808', + '3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73', + ], + ]; + const privKey = hexToBytes( + '0101010101010101010101010101010101010101010101010101010101010101' + ); + for (const [msg, exp] of CASES) { + const res = secp.sign(msg, privKey, { extraEntropy: undefined }); + deepStrictEqual(sigToDER(res), exp); + const rs = sigFromDER(sigToDER(res)).toCompactHex(); + deepStrictEqual(sigToDER(secp.Signature.fromCompact(rs)), exp); + } + }); + should('handle {extraData} option', () => { + const ent1 = '0000000000000000000000000000000000000000000000000000000000000000'; + const ent2 = '0000000000000000000000000000000000000000000000000000000000000001'; + const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33'; + const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; + const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; + + for (const e of ecdsa.extraEntropy) { + const sign = (extraEntropy) => { + const s = secp.sign(e.m, e.d, { extraEntropy }).toCompactHex(); + return s; + }; + deepStrictEqual(sign(), e.signature); + deepStrictEqual(sign(ent1), e.extraEntropy0); + deepStrictEqual(sign(ent2), e.extraEntropy1); + deepStrictEqual(sign(ent3), e.extraEntropyRand); + deepStrictEqual(sign(ent4), e.extraEntropyN); + deepStrictEqual(sign(ent5), e.extraEntropyMax); + } + }); + }); + + describe('verify()', () => { + should('verify signature', () => { + const MSG = '01'.repeat(32); + const PRIV_KEY = 0x2n; + const signature = secp.sign(MSG, PRIV_KEY); + const publicKey = secp.getPublicKey(PRIV_KEY); + deepStrictEqual(publicKey.length, 33); + deepStrictEqual(secp.verify(signature, MSG, publicKey), true); + }); + should(' not verify signature with wrong public key', () => { + const MSG = '01'.repeat(32); + const PRIV_KEY = '01'.repeat(32); + const WRONG_PRIV_KEY = '02'.repeat(32); + const signature = secp.sign(MSG, PRIV_KEY); + const publicKey = Point.fromPrivateKey(WRONG_PRIV_KEY).toHex(); + deepStrictEqual(publicKey.length, 66); + deepStrictEqual(secp.verify(signature, MSG, publicKey), false); + }); + should('not verify signature with wrong hash', () => { + const MSG = '01'.repeat(32); + const PRIV_KEY = 0x2n; + const WRONG_MSG = '11'.repeat(32); + const signature = secp.sign(MSG, PRIV_KEY); + const publicKey = secp.getPublicKey(PRIV_KEY); + deepStrictEqual(publicKey.length, 33); + deepStrictEqual(secp.verify(signature, WRONG_MSG, publicKey), false); + }); + should('verify random signatures', () => + fc.assert( + fc.property(FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), (privKey, msg) => { + const pub = secp.getPublicKey(privKey); + const sig = secp.sign(msg, privKey); + deepStrictEqual(secp.verify(sig, msg, pub), true); + }) + ) + ); + should('not verify signature with invalid r/s', () => { + const msg = new Uint8Array([ + 0xbb, 0x5a, 0x52, 0xf4, 0x2f, 0x9c, 0x92, 0x61, 0xed, 0x43, 0x61, 0xf5, 0x94, 0x22, 0xa1, + 0xe3, 0x00, 0x36, 0xe7, 0xc3, 0x2b, 0x27, 0x0c, 0x88, 0x07, 0xa4, 0x19, 0xfe, 0xca, 0x60, + 0x50, 0x23, + ]); + const x = 100260381870027870612475458630405506840396644859280795015145920502443964769584n; + const y = 41096923727651821103518389640356553930186852801619204169823347832429067794568n; + const r = 1n; + const s = 115792089237316195423570985008687907852837564279074904382605163141518162728904n; + + const pub = new Point(x, y, 1n).toRawBytes(); + const signature = new secp.Signature(2n, 2n); + signature.r = r; + signature.s = s; + + const verified = secp.verify(signature, msg, pub); + // Verifies, but it shouldn't, because signature S > curve order + deepStrictEqual(verified, false); + }); + should('not verify msg = curve order', () => { + const msg = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'; + const x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n; + const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n; + const r = 104546003225722045112039007203142344920046999340768276760147352389092131869133n; + const s = 96900796730960181123786672629079577025401317267213807243199432755332205217369n; + const pub = new Point(x, y, 1n).toRawBytes(); + const sig = new secp.Signature(r, s); + deepStrictEqual(secp.verify(sig, msg, pub), false); + }); + should('verify non-strict msg bb5a...', () => { + const msg = 'bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023'; + const x = 3252872872578928810725465493269682203671229454553002637820453004368632726370n; + const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n; + const r = 432420386565659656852420866390673177323n; + const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n; + const pub = new Point(x, y, 1n).toRawBytes(); + const sig = new secp.Signature(r, s); + deepStrictEqual(secp.verify(sig, msg, pub, { lowS: false }), true); + }); + should('not verify invalid deterministic signatures with RFC 6979', () => { + for (const vector of ecdsa.invalid.verify) { + const res = secp.verify(vector.signature, vector.m, vector.Q); + deepStrictEqual(res, false); + } + }); + }); + describe('recoverPublicKey()', () => { + should('recover public key from recovery bit', () => { + const message = '00000000000000000000000000000000000000000000000000000000deadbeef'; + const privateKey = 123456789n; + const publicKey = Point.fromHex(secp.getPublicKey(privateKey)).toHex(false); + const sig = secp.sign(message, privateKey); + const recoveredPubkey = sig.recoverPublicKey(message); + // const recoveredPubkey = secp.recoverPublicKey(message, signature, recovery); + deepStrictEqual(recoveredPubkey !== null, true); + deepStrictEqual(recoveredPubkey.toHex(false), publicKey); + deepStrictEqual(secp.verify(sig, message, publicKey), true); + }); + should('not recover zero points', () => { + const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; + const sig = + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9'; + const recovery = 0; + throws(() => secp.recoverPublicKey(msgHash, sig, recovery)); + }); + should('handle all-zeros msghash', () => { + const privKey = secp.utils.randomPrivateKey(); + const pub = secp.getPublicKey(privKey); + const zeros = '0000000000000000000000000000000000000000000000000000000000000000'; + const sig = secp.sign(zeros, privKey); + const recoveredKey = sig.recoverPublicKey(zeros); + deepStrictEqual(recoveredKey.toRawBytes(), pub); + }); + should('handle RFC 6979 vectors', () => { + for (const vector of ecdsa.valid) { + let usig = secp.sign(vector.m, vector.d); + let sig = sigToDER(usig); + const vpub = secp.getPublicKey(vector.d); + const recovered = usig.recoverPublicKey(vector.m); + deepStrictEqual(recovered.toHex(), hex(vpub)); + } + }); + }); + + describe('getSharedSecret()', () => { + // TODO: Real implementation. + function derToPub(der) { + return der.slice(46); + } + should('produce correct results', () => { + // TODO: Once der is there, run all tests. + for (const vector of ecdh.testGroups[0].tests.slice(0, 230)) { + if (vector.result === 'invalid' || vector.private.length !== 64) { + throws(() => { + secp.getSharedSecret(vector.private, derToPub(vector.public), true); + }); + } else if (vector.result === 'valid') { + const res = secp.getSharedSecret(vector.private, derToPub(vector.public), true); + deepStrictEqual(hex(res.slice(1)), `${vector.shared}`); + } + } + }); + should('priv/pub order matters', () => { + for (const vector of ecdh.testGroups[0].tests.slice(0, 100)) { + if (vector.result === 'valid') { + let priv = vector.private; + priv = priv.length === 66 ? priv.slice(2) : priv; + throws(() => secp.getSharedSecret(derToPub(vector.public), priv, true)); + } + } + }); + should('reject invalid keys', () => { + throws(() => secp.getSharedSecret('01', '02')); + }); + }); + + should('utils.isValidPrivateKey()', () => { + for (const vector of privates.valid.isPrivate) { + const { d, expected } = vector; + deepStrictEqual(secp.utils.isValidPrivateKey(d), expected); + } + }); + should('have proper curve equation in assertValidity()', () => { + throws(() => { + const { Fp } = secp.CURVE; + let point = new Point(Fp.create(-2n), Fp.create(-1n), Fp.create(1n)); + point.assertValidity(); + }); + }); + + describe('tweak utilities (legacy)', () => { + const normal = secp.utils.normPrivateKeyToScalar; + const tweakUtils = { + privateAdd: (privateKey, tweak) => { + return numberToBytesBE(mod(normal(privateKey) + normal(tweak), secp.CURVE.n), 32); + }, + + privateNegate: (privateKey) => { + return numberToBytesBE(mod(-normal(privateKey), secp.CURVE.n), 32); + }, + + pointAddScalar: (p, tweak, isCompressed) => { + const tweaked = Point.fromHex(p).add(Point.fromPrivateKey(tweak)); + if (tweaked.equals(Point.ZERO)) throw new Error('Tweaked point at infinity'); + return tweaked.toRawBytes(isCompressed); + }, + + pointMultiply: (p, tweak, isCompressed) => { + if (typeof tweak === 'string') tweak = hexToBytes(tweak); + const t = bytesToNumberBE(tweak); + return Point.fromHex(p).multiply(t).toRawBytes(isCompressed); + }, + }; + + should('privateAdd()', () => { + for (const vector of privates.valid.add) { + const { a, b, expected } = vector; + deepStrictEqual(hex(tweakUtils.privateAdd(a, b)), expected); + } + }); + should('privateNegate()', () => { + for (const vector of privates.valid.negate) { + const { a, expected } = vector; + deepStrictEqual(hex(tweakUtils.privateNegate(a)), expected); + } + }); + should('pointAddScalar()', () => { + for (const vector of points.valid.pointAddScalar) { + const { description, P, d, expected } = vector; + const compressed = !!expected && expected.length === 66; // compressed === 33 bytes + deepStrictEqual(hex(tweakUtils.pointAddScalar(P, d, compressed)), expected); + } + }); + should('pointAddScalar() invalid', () => { + for (const vector of points.invalid.pointAddScalar) { + const { P, d, exception } = vector; + throws(() => tweakUtils.pointAddScalar(P, d)); + } + }); + should('pointMultiply()', () => { + for (const vector of points.valid.pointMultiply) { + const { P, d, expected } = vector; + deepStrictEqual(hex(tweakUtils.pointMultiply(P, d, true)), expected); + } + }); + should('pointMultiply() invalid', () => { + for (const vector of points.invalid.pointMultiply) { + const { P, d, exception } = vector; + throws(() => tweakUtils.pointMultiply(P, d)); + } + }); + }); + + should('wycheproof vectors', () => { + for (let group of wp.testGroups) { + // const pubKey = Point.fromHex().toRawBytes(); + const pubKey = group.key.uncompressed; + for (let test of group.tests) { + const h = selectHash(secp); + + const m = h(hexToBytes(test.msg)); + if (test.result === 'valid' || test.result === 'acceptable') { + const verified = secp.verify(normVerifySig(test.sig), m, pubKey); + if (sigFromDER(test.sig).hasHighS()) { + deepStrictEqual(verified, false); + } else { + deepStrictEqual(verified, true); + } + } else if (test.result === 'invalid') { + let failed = false; + try { + const verified = secp.verify(test.sig, m, pubKey); + if (!verified) failed = true; + } catch (error) { + failed = true; + } + deepStrictEqual(failed, true); + } else { + deepStrictEqual(false, true); + } + } + } + }); +}); + +// ESM is broken. +import url from 'url'; +if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { + should.run(); +} diff --git a/test/tsconfig.json b/test/tsconfig.json index 14e868a..12e568c 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -2,12 +2,12 @@ "compilerOptions": { "strict": true, "target": "es2020", - "module": "commonjs", + "module": "es6", + "moduleResolution": "node16", "noImplicitAny": true, - "removeComments": true, "preserveConstEnums": true, "resolveJsonModule": true }, - "include": ["*.ts"], + "include": ["secp256k1.helpers.mts"], "exclude": ["node_modules"] } From 12039c12e2c95a54be4c1d2653a3b2e691bb1fba Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 20:30:42 +0000 Subject: [PATCH 043/145] pkg.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6cfb48d..7b669dd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", "version": "2.0.0-pre", - "description": "Fastest JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures", + "description": "Fastest 9KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures compliant with RFC6979", "files": [ "lib" ], From 7db987c99e57950207b28cf300d0fd36eadbc125 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 9 Feb 2023 20:34:32 +0000 Subject: [PATCH 044/145] ci: use node 19 --- .github/workflows/nodejs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 875aeff..2528878 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -3,14 +3,14 @@ name: Node CI on: [push, pull_request] jobs: test: - name: v18 @ ubuntu-latest + name: v19 @ ubuntu-latest runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 19 - run: npm install - run: npm run build --if-present - run: npm test From 61276e45bc24179f2bd7146b3bfb60c467b93855 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 11 Feb 2023 21:06:49 +0000 Subject: [PATCH 045/145] use node:crypto --- index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 7d86b1d..7a0a1f4 100644 --- a/index.ts +++ b/index.ts @@ -220,7 +220,7 @@ const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be us const i2o = (num: bigint): Bytes => n2b(num); // int to octets declare const globalThis: Record | undefined; // Typescript global symbol available in const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependence on @types/dom - node: typeof require === 'function' && require('crypto'), // node.js require('crypto') + node: typeof require === 'function' && require('node:crypto'), // node.js require('crypto') web: typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined, // browser-only var }; type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); From 9247e0587cb5ec1767c2d68b247f74b14648856f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 15 Mar 2023 23:02:17 +0000 Subject: [PATCH 046/145] Fix import --- index.ts | 33 +++++++++++++++------------------ test/secp256k1.helpers.mjs | 3 +++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/index.ts b/index.ts index 7a0a1f4..54280bf 100644 --- a/index.ts +++ b/index.ts @@ -218,11 +218,9 @@ const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be us return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets -declare const globalThis: Record | undefined; // Typescript global symbol available in -const cr: { node?: any; web?: any } = { // browsers only. Ensure no dependence on @types/dom - node: typeof require === 'function' && require('node:crypto'), // node.js require('crypto') - web: typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined, // browser-only var -}; +declare const globalThis: Record | undefined; // Typescript symbol present in browsers +const cr = () => // We support: 1) browsers 2) node.js 19+ + typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it const stdo: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() @@ -363,7 +361,7 @@ export const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): b return v === r; // mod(R.x, n) == r } export const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true) => { - return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); + return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH }; const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation hash = toU8(hash); // produces private keys with modulo bias @@ -379,26 +377,25 @@ const ut = { // utilities bytesToNumberBE: b2n, numberToBytesBE: n2b, normPrivateKeyToScalar: toPriv, randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) - return cr.web ? cr.web.getRandomValues(u8n(len)) : - cr.node ? u8fr(cr.node.randomBytes(len)) : err('CSPRNG not present'); + const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: + // import { webcrypto } from 'node:crypto'; + // globalThis.crypto = webcrypto; + if (!crypto) err('crypto.getRandomValues must be defined'); + return crypto.getRandomValues(u8n(len)); }, hashToPrivateKey, hmacSha256Async: async (key: Bytes, ...msgs: Bytes[]): Promise => { const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! - if (cr.web) { // browser built-in version - const s = cr.web.subtle; - const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); - return u8n(await s.sign('HMAC', k, m)); - } else if (cr.node) { // node.js built-in version - return u8fr(cr.node.createHmac('sha256', key).update(m).digest()); - } else { - return err('utils.hmacSha256 not set'); - } + const crypto = cr(); + if (!crypto) return err('utils.hmacSha256Async not set'); + const s = crypto.subtle; + const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); + return u8n(await s.sign('HMAC', k, m)); }, hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below randomPrivateKey: (): Bytes => hashToPrivateKey(ut.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, - precompute(p: Point) {return p;} + precompute(p: Point) { return p; } // no-op }; Object.defineProperties(ut, { hmacSha256Sync: { // Allow setting it once, ignore then configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, diff --git a/test/secp256k1.helpers.mjs b/test/secp256k1.helpers.mjs index a57df37..ad2bf13 100644 --- a/test/secp256k1.helpers.mjs +++ b/test/secp256k1.helpers.mjs @@ -1,4 +1,7 @@ // @ts-ignore +import { webcrypto } from 'node:crypto'; +globalThis.crypto = webcrypto; +// @ts-ignore export * as secp from '../lib/esm/index.js'; // @ts-ignore import * as secp256k1 from '../lib/esm/index.js'; From 49fa33db550f188c8c035be47f0675cbb7193f53 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 15 Mar 2023 23:10:15 +0000 Subject: [PATCH 047/145] Fix deno --- README.md | 11 ++--------- mod.ts | 13 ++++--------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 64af7d0..3dbfa07 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@ Check out [Upgrading](#upgrading) section for v1 to v2 transition instructions. ## Usage -Use NPM in node.js / browser, or include single file from +Use NPM in browser, deno and node.js, or include single file from [GitHub's releases page](https://github.com/paulmillr/noble-secp256k1/releases): > npm install @noble/secp256k1 ```js -// Common.js and ECMAScript Modules (ESM) +// ECMAScript Modules (ESM). Common.js not supported without a bundler import * as secp from '@noble/secp256k1'; // If you're using single file, use global variable instead: `window.nobleSecp256k1` @@ -49,13 +49,6 @@ import * as secp from '@noble/secp256k1'; })(); ``` -To use the module with [Deno](https://deno.land), -you will need [import map](https://deno.land/manual/linking_to_external_code/import_maps): - -- `deno run --import-map=imports.json app.ts` -- app.ts: `import * as secp from "https://deno.land/x/secp256k1/mod.ts";` -- imports.json: `{"imports": {"crypto": "https://deno.land/std@0.153.0/node/crypto.ts"}}` - ## API - [`getPublicKey(privateKey)`](#getpublickeyprivatekey) diff --git a/mod.ts b/mod.ts index 8ab3b16..900edd0 100644 --- a/mod.ts +++ b/mod.ts @@ -4,7 +4,8 @@ import { getPublicKey, sign, signAsync, verify, getSharedSecret, utils, } from './index.ts'; -import { HmacSha256 } from 'https://deno.land/std@0.175.0/hash/sha256.ts'; +import { hmac } from 'npm:@noble/hashes@1.2.0/hmac'; +import { sha256 } from 'npm:@noble/hashes@1.2.0/sha256'; import { crypto } from 'https://deno.land/std@0.175.0/crypto/mod.ts'; utils.sha256 = async (...msgs: Uint8Array[]): Promise => { @@ -14,16 +15,10 @@ utils.sha256Sync = (...msgs: Uint8Array[]): Uint8Array => { return new Uint8Array(crypto.subtle.digestSync('SHA-256', utils.concatBytes(...msgs))); }; -function hmac(key: Uint8Array, ...messages: Uint8Array[]): Uint8Array { - const sha = new HmacSha256(key); - for (let msg of messages) sha.update(msg); - return new Uint8Array(sha.arrayBuffer()); +utils.hmacSha256Sync = function hmac(key: Uint8Array, ...messages: Uint8Array[]): Uint8Array { + return hmac(sha256, key, ...messages); } -utils.hmacSha256 = async (key: Uint8Array, ...messages: Uint8Array[]) => - Promise.resolve(hmac(key, ...messages)); -utils.hmacSha256Sync = (key: Uint8Array, ...messages: Uint8Array[]) => hmac(key, ...messages); - // prettier-ignore export { CURVE, ProjectivePoint, Signature, From 9c7d552120b115e2792f4206103353b0f60cf510 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 15 Mar 2023 23:12:10 +0000 Subject: [PATCH 048/145] Line-up --- index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.ts b/index.ts index 54280bf..3a6bc4f 100644 --- a/index.ts +++ b/index.ts @@ -123,7 +123,7 @@ class Point { // Point in 3d xyz proje toRawBytes(isCompressed = true) { // Encodes point to Uint8Array return h2b(this.toHex(isCompressed)); // Re-use toHex(), convert hex to bytes } - static fromPrivateKey(n: PrivKey) { // Create point from a private key. Multiply + static fromPrivateKey(n: PrivKey) { // Create point from a private key. Multiply return G.mul(toPriv(n)); // base point by bigint(n) } } @@ -176,8 +176,8 @@ const n2b = (num: bigint): Bytes => { // number to bytes. must }; const n2h = (num: bigint): string => b2h(n2b(num)); // number to hex const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Array-s - const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length - let pad = 0; // walk through each array, ensure + const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length + let pad = 0; // walk through each array, ensure arrs.forEach(a => { r.set(au8(a), pad); pad += a.length }); // they have proper type return r; }; From 375b026d278d12666a5e2593d39b14ea737c0aad Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 15 Mar 2023 23:30:24 +0000 Subject: [PATCH 049/145] Pure-ESM package --- README.md | 14 ++++++++------ index.ts | 38 +++++++++++++++++++------------------- lib/esm/package.json | 6 ------ package.json | 19 +++++++++---------- test/benchmark.js | 12 +++++++----- test/secp256k1.helpers.mjs | 17 ++++++++--------- test/secp256k1.helpers.mts | 17 ++++++++++------- tsconfig.esm.json | 16 ---------------- tsconfig.json | 5 ++--- 9 files changed, 63 insertions(+), 81 deletions(-) delete mode 100644 lib/esm/package.json delete mode 100644 tsconfig.esm.json diff --git a/README.md b/README.md index 3dbfa07..bb2c258 100644 --- a/README.md +++ b/README.md @@ -228,14 +228,16 @@ We however consider infrastructure attacks like rogue NPM modules very important ## Speed +Use [noble-curves](https://github.com/paulmillr/noble-curves) if you need even higher performance. + Benchmarks measured with Apple M2 on MacOS 13 with node.js 19. - getPublicKey(utils.randomPrivateKey()) x 5,695 ops/sec @ 175μs/op - sign x 4,737 ops/sec @ 211μs/op - verify x 523 ops/sec @ 1ms/op - getSharedSecret x 441 ops/sec @ 2ms/op - recoverPublicKey x 534 ops/sec @ 1ms/op - Point.fromHex (decompression) x 8,538 ops/sec @ 117μs/op + getPublicKey(utils.randomPrivateKey()) x 5,047 ops/sec @ 198μs/op + sign x 2,955 ops/sec @ 338μs/op + verify x 470 ops/sec @ 2ms/op + getSharedSecret x 403 ops/sec @ 2ms/op + recoverPublicKey x 485 ops/sec @ 2ms/op + Point.fromHex (decompression) x 7,546 ops/sec @ 132μs/op Compare to other libraries on M1 (`openssl` uses native bindings, not JS): diff --git a/index.ts b/index.ts index 3a6bc4f..295c437 100644 --- a/index.ts +++ b/index.ts @@ -237,7 +237,7 @@ const prepSig = (msgh: Hex, priv: Hex, opts = stdo): BC => { // prepare for RFC6 const seed = [i2o(d), h1o]; // Step D of RFC6979 3.2 let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - if (ent === true) ent = ut.randomBytes(fLen); // if true, use CSPRNG to generate data + if (ent === true) ent = etc.randomBytes(fLen); // if true, use CSPRNG to generate data const e = toU8(ent); // convert Hex|Bytes to Bytes if (e.length !== fLen) err(); // Expected 32 bytes of extra data seed.push(e); @@ -272,7 +272,7 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async const reset = () => { v.fill(1); k.fill(0); i = 0; }; const _e = 'drbg: tried 1000 values'; if (asynchronous) { // asynchronous=true - const h = (...b: Bytes[]) => ut.hmacSha256Async(k, v, ...b); // hmac(k)(v, ...values) + const h = (...b: Bytes[]) => etc.hmacSha256Async(k, v, ...b); // hmac(k)(v, ...values) const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) v = await h(); // v = hmac(K || V) @@ -370,20 +370,10 @@ const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compli const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); }; -const ut = { // utilities +export const etc = { // Not placed in `utils` because utils + hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. + concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, // math utilities - concatBytes: concatB, - hexToBytes: h2b, bytesToHex: b2h, - bytesToNumberBE: b2n, numberToBytesBE: n2b, - normPrivateKeyToScalar: toPriv, - randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) - const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: - // import { webcrypto } from 'node:crypto'; - // globalThis.crypto = webcrypto; - if (!crypto) err('crypto.getRandomValues must be defined'); - return crypto.getRandomValues(u8n(len)); - }, - hashToPrivateKey, hmacSha256Async: async (key: Bytes, ...msgs: Bytes[]): Promise => { const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! const crypto = cr(); @@ -393,11 +383,22 @@ const ut = { // utilities return u8n(await s.sign('HMAC', k, m)); }, hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below - randomPrivateKey: (): Bytes => hashToPrivateKey(ut.randomBytes(fLen + 8)), // FIPS 186 B.4.1. + hashToPrivateKey, + randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) + const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: + // import { webcrypto } from 'node:crypto'; + // if (!globalThis.crypto) globalThis.crypto = webcrypto; + if (!crypto) err('crypto.getRandomValues must be defined'); + return crypto.getRandomValues(u8n(len)); + }, +} +export const utils = { // utilities + normPrivateKeyToScalar: toPriv, + randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, - precompute(p: Point) { return p; } // no-op + precompute(p: Point, windowSize = 8) { return p; } // no-op }; -Object.defineProperties(ut, { hmacSha256Sync: { // Allow setting it once, ignore then +Object.defineProperties(etc, { hmacSha256Sync: { // Allow setting it once, ignore then configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, } }); const W = 8; // Precomputes-related code. W = window size @@ -439,4 +440,3 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo return { p, f } // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() export const ProjectivePoint = Point; -export const utils = ut; diff --git a/lib/esm/package.json b/lib/esm/package.json deleted file mode 100644 index e8309c4..0000000 --- a/lib/esm/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "module", - "browser": { - "crypto": false - } -} \ No newline at end of file diff --git a/package.json b/package.json index 7b669dd..f885ace 100644 --- a/package.json +++ b/package.json @@ -3,18 +3,21 @@ "version": "2.0.0-pre", "description": "Fastest 9KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures compliant with RFC6979", "files": [ - "lib" + "index.js", + "index.d.ts", + "index.ts" ], - "main": "lib/index.js", - "module": "lib/esm/index.js", - "types": "lib/index.d.ts", + "type": "module", + "main": "index.js", + "module": "index.js", + "types": "index.d.ts", "scripts": { - "build": "tsc && tsc -p tsconfig.esm.json", + "build": "tsc", "build:release": "rollup -c rollup.config.js", "test": "node test/secp256k1.test.mjs", "coverage": "jest --coverage", "bench": "node test/benchmark.js", - "min": "terser --ecma 2020 -m -c < lib/esm/index.js", + "min": "terser --ecma 2020 -m -c < lib/index.js", "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts`LOC\"" }, "author": "Paul Miller (https://paulmillr.com)", @@ -24,9 +27,6 @@ "url": "https://github.com/paulmillr/noble-secp256k1.git" }, "license": "MIT", - "browser": { - "crypto": false - }, "devDependencies": { "@noble/hashes": "1.2.0", "@types/node": "17.0.18", @@ -57,7 +57,6 @@ "exports": { ".": { "types": "./lib/index.d.ts", - "import": "./lib/esm/index.js", "default": "./lib/index.js" } }, diff --git a/test/benchmark.js b/test/benchmark.js index 8813cea..4f3338a 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -1,8 +1,10 @@ -const { run, mark, logMem } = require('micro-bmark'); -const secp = require('..'); -const { join } = require('path'); -const points = require('fs') - .readFileSync(join(__dirname, './vectors/points.txt'), 'utf-8') +import { webcrypto } from 'node:crypto'; +if (!globalThis.crypto) globalThis.crypto = webcrypto; +import { run, mark } from 'micro-bmark'; +import * as secp from '../index.js'; +import { join } from 'node:path'; +import { readFileSync } from 'node:fs'; +const points = readFileSync(join('.', 'test/vectors/points.txt'), 'utf-8') .split('\n') .filter((a) => a) .slice(0, 1000); diff --git a/test/secp256k1.helpers.mjs b/test/secp256k1.helpers.mjs index ad2bf13..43fd6ec 100644 --- a/test/secp256k1.helpers.mjs +++ b/test/secp256k1.helpers.mjs @@ -1,14 +1,13 @@ -// @ts-ignore import { webcrypto } from 'node:crypto'; -globalThis.crypto = webcrypto; +if (!globalThis.crypto) globalThis.crypto = webcrypto; // @ts-ignore -export * as secp from '../lib/esm/index.js'; +export * as secp from '../index.js'; // @ts-ignore -import * as secp256k1 from '../lib/esm/index.js'; +import * as secp256k1 from '../index.js'; import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; -secp256k1.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)); -const { bytesToNumberBE: b2n, hexToBytes: h2b } = secp256k1.utils; +secp256k1.etc.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.etc.concatBytes(...msgs)); +const { bytesToNumberBE: b2n, hexToBytes: h2b } = secp256k1.etc; export const DER = { // asn.1 DER encoding utils Err: class DERErr extends Error { @@ -68,6 +67,6 @@ export const sigFromDER = (der) => { export const sigToDER = (sig) => DER.hexFromSig(sig); export const selectHash = (secp) => sha256; export const normVerifySig = (s) => DER.toSig(s); -export const bytesToNumberBE = secp256k1.utils.bytesToNumberBE; -export const numberToBytesBE = secp256k1.utils.numberToBytesBE; -export const mod = secp256k1.utils.mod; +export const bytesToNumberBE = secp256k1.etc.bytesToNumberBE; +export const numberToBytesBE = secp256k1.etc.numberToBytesBE; +export const mod = secp256k1.etc.mod; diff --git a/test/secp256k1.helpers.mts b/test/secp256k1.helpers.mts index fc2d8b0..52f526e 100644 --- a/test/secp256k1.helpers.mts +++ b/test/secp256k1.helpers.mts @@ -1,12 +1,15 @@ +import { webcrypto } from 'node:crypto'; // @ts-ignore -export * as secp from '../lib/esm/index.js'; +if (!globalThis.crypto) globalThis.crypto = webcrypto; // @ts-ignore // @ts-ignore -import * as secp256k1 from '../lib/esm/index.js'; +export * as secp from '../index.js'; +// @ts-ignore +import * as secp256k1 from '../index.js'; import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; -secp256k1.utils.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs)) +secp256k1.etc.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, secp256k1.etc.concatBytes(...msgs)) -const { bytesToNumberBE: b2n, hexToBytes: h2b } = secp256k1.utils; +const { bytesToNumberBE: b2n, hexToBytes: h2b } = secp256k1.etc; export const DER = { // asn.1 DER encoding utils Err: class DERErr extends Error { @@ -61,6 +64,6 @@ export const sigFromDER = (der: string | Uint8Array) => { export const sigToDER = (sig: any) => DER.hexFromSig(sig); export const selectHash = (secp: any) => sha256; export const normVerifySig = (s: any) => DER.toSig(s); -export const bytesToNumberBE = secp256k1.utils.bytesToNumberBE; -export const numberToBytesBE = secp256k1.utils.numberToBytesBE; -export const mod = secp256k1.utils.mod; +export const bytesToNumberBE = secp256k1.etc.bytesToNumberBE; +export const numberToBytesBE = secp256k1.etc.numberToBytesBE; +export const mod = secp256k1.etc.mod; diff --git a/tsconfig.esm.json b/tsconfig.esm.json deleted file mode 100644 index 8fc2504..0000000 --- a/tsconfig.esm.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "target": "es2020", - "lib": ["es2020"], - "module": "es6", - "moduleResolution": "node", - "outDir": "lib/esm", - "noImplicitAny": true, - "removeComments": true, - "preserveConstEnums": true, - "baseUrl": ".", - }, - "include": ["index.ts"], - "exclude": ["node_modules", "lib"] -} diff --git a/tsconfig.json b/tsconfig.json index 9c457a7..e8a97e3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,13 +5,12 @@ "declarationMap": false, "target": "es2020", "lib": ["es2020"], - "module": "commonjs", + "module": "es6", "moduleResolution": "node", - "outDir": "lib", + "outDir": ".", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, - "resolveJsonModule": true, "baseUrl": ".", }, "include": ["index.ts"], From 2d4cddb80fe828a9b0cadac17693b747150309dd Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 01:35:46 +0000 Subject: [PATCH 050/145] README: 80-char limit --- README.md | 307 ++++++++++++++++++------------------- test/secp256k1.helpers.mjs | 3 +- 2 files changed, 150 insertions(+), 160 deletions(-) diff --git a/README.md b/README.md index bb2c258..1ee6d8e 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,9 @@ an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. -Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). +The library does not use dependencies and is as minimal as possible. [noble-curves](https://github.com/paulmillr/noble-curves) is advanced drop-in replacement for noble-secp256k1 with more features such as Schnorr signatures, DER encoding and support for different hash functions. -The library does not use dependencies and is as minimal as possible. [noble-curves](https://github.com/paulmillr/noble-curves) is even faster drop-in replacement for noble-secp256k1 with more features such as Schnorr signatures, DER encoding, support for different hash functions. - -Check out [Upgrading](#upgrading) section for v1 to v2 transition instructions. +Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions; [the online demo](https://paulmillr.com/ecc) and blog post [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). ### This library belongs to _noble_ crypto @@ -26,205 +24,196 @@ Check out [Upgrading](#upgrading) section for v1 to v2 transition instructions. ## Usage -Use NPM in browser, deno and node.js, or include single file from -[GitHub's releases page](https://github.com/paulmillr/noble-secp256k1/releases): +Use NPM in browser and node.js: > npm install @noble/secp256k1 -```js -// ECMAScript Modules (ESM). Common.js not supported without a bundler -import * as secp from '@noble/secp256k1'; -// If you're using single file, use global variable instead: `window.nobleSecp256k1` +For [Deno](https://deno.land), the module is available at `x/secp256k1`; or you can use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers). -// Supports both async and sync methods, see docs +```js +import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js (async () => { // keys, messages & other inputs can be Uint8Arrays or hex strings // Uint8Array.from([0xde, 0xad, 0xbe, 0xef]) === 'deadbeef' - const privKey = secp.utils.randomPrivateKey(); - const pubKey = secp.getPublicKey(privKey); + const privKey = secp.utils.randomPrivateKey(); // Secure random private key // sha256 of 'hello world' const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; - const signature = await secp.signAsync(msgHash, privKey); - const isValid = secp.verify(signature, msgHash, pubKey); -})(); -``` - -## API - -- [`getPublicKey(privateKey)`](#getpublickeyprivatekey) -- [`sign(msgHash, privateKey)`](#signmsghash-privatekey) -- [`verify(signature, msgHash, publicKey)`](#verifysignature-msghash-publickey) -- [`getSharedSecret(privateKeyA, publicKeyB)`](#getsharedsecretprivatekeya-publickeyb) -- [`signature.recoverPublicKey(msgHash)`](#signaturerecoverpublickeyhash) -- [Utilities](#utilities) - -#### `getPublicKey(privateKey)` - -```typescript -function getPublicKey( - privateKey: Uint8Array | string | bigint, - isCompressed = true // Optional argument: default `true` produces 33-byte compressed -): Uint8Array; -``` - -Creates 33-byte compact public key for the private key. + const pubKey = secp.getPublicKey(privKey); // Make pubkey from the private key + const signature = await secp.signAsync(msgHash, privKey); // sign + const isValid = secp.verify(signature, msgHash, pubKey); // verify -```js -const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; -getPublicKey(privKey); -getPublicKey(privKey, false); -// Use `PPoint.fromPrivateKey(privateKey)` if you need `PPoint` instead of `Uint8Array` -``` - -#### `sign(msgHash, privateKey)` - -```typescript -function signAsync( // Available by default - msgHash: Uint8Array | string, // 32-byte message hash (not the message itself) - privateKey: Uint8Array | string, // private key that will sign it - opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional object with params -): Promise; -function sign( // Not available by default: need to set utils.hmacSha256 first - msgHash: Uint8Array | string, // 32-byte message hash (not the message itself) - privateKey: Uint8Array | string, // private key that will sign it - opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional object with params -): Signature; + const pubKey2 = getPublicKey(secp.utils.randomPrivateKey()); // Key of user 2 + secp.getSharedSecret(privKey, alicesPubkey); // Elliptic curve diffie-hellman + signature.recoverPublicKey(msgHash); // Public key recovery +})(); ``` -Generates low-s deterministic-k RFC6979 ECDSA signature. Use with `extraEntropy: true` to improve security. - -```js -const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; -const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; -const sig = await signAsync(msgHash, privKey); +Advanced examples: -// ^ The function is async because we're utilizing built-in HMAC API to not rely on dependencies. -// signSync is disabled by default. To enable it, pass a hmac calculator function +```ts +// 1. Use the shim to enable synchronous methods. +// Only async methods are available by default to keep library dependency-free. import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; -// should be `key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array` -secp.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp.utils.concatBytes(...msgs)) -secp.sign(msgHash, privKey); // Can be used now +secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) +const signature2 = secp.sign(msgHash, privKey); // Can be used now + +// 2. Use the shim only for node.js <= 18 BEFORE importing noble-secp256k1. +// The library depends on global variable crypto to work. It is available in +// all browsers and many environments, but node.js <= 18 don't have it. +import { webcrypto } from 'node:crypto'; +// @ts-ignore +if (!globalThis.crypto) globalThis.crypto = webcrypto; +// Other stuff // Malleable signatures, incompatible with BTC/ETH, but compatible with openssl -// `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) because of malleability -const sigM = sign(msgHash, privKey, { lowS: false }); - -// Signatures with improved security: adds additional entropy `k` for deterministic signature, -// follows section 3.6 of RFC6979. When `true`, it would be filled with 32b from CSPRNG. -// **Strongly recommended** to pass `true` to improve security: -// - No disadvantage: if an entropy generator is broken, sigs would be the same as they are without the option -// - It would help a lot in case there is an error somewhere in `k` gen. Exposing `k` could leak private keys +// `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) because of +// malleability +const signatureMalleable = secp.sign(msgHash, privKey, { lowS: false }); + +// Signatures with improved security: adds additional entropy `k` for +// deterministic signature, follows section 3.6 of RFC6979. When `true`, it +// would be filled with 32b from CSPRNG. **Strongly recommended** to pass `true` +// to improve security: +// - No disadvantage: if an entropy generator is broken, sigs would be the same +// as they are without the option +// - It would help a lot in case there is an error somewhere in `k` gen. +// Exposing `k` could leak private keys // - Sigs with extra entropy would have different `r` / `s`, which means they -// would still be valid, but may break some test vectors if you're cross-testing against other libs -const sigE = sign(msgHash, privKey, { extraEntropy: true }); +// would still be valid, but may break some test vectors if you're +// cross-testing against other libs +const signatureImproved = secp.sign(msgHash, privKey, { extraEntropy: true }); ``` -#### `verify(signature, msgHash, publicKey)` +## API -```typescript -function verify( - signature: Uint8Array | string | Signature, // Signature is returned by sign() - msgHash: Uint8Array | string, // message hash (not the message) that must be verified - publicKey: Uint8Array | string | Point, // public (not private) key - opts?: { lowS: boolean } // if a signature.s must be in the lower-half of CURVE.n. Used in BTC, ETH - // lowS: false should only be used if you need openSSL-compatible signatures -): boolean; // `true` if `signature` is valid for `hash` and `publicKey`; otherwise `false` -``` +There are 3 main methods: `getPublicKey(privateKey)`, +`sign(messageHash, privateKey)` and +`verify(signature, messageHash, publicKey)`. -Verifies signatures against message and public key. +Only **async methods are available by default** to keep library dependency-free. +To enable sync methods, see below. -```js -const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; -const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; -const pub = getPublicKey(privKey); -const sig = await signAsync(msgHash, privKey); -const isValid = verify(sig, msgHash, pub); -``` +```typescript +type Hex = Uint8Array | string; -#### `getSharedSecret(privateKeyA, publicKeyB)` +// Generates 33-byte / 65-byte public key from 32-byte private key. +function getPublicKey( + privateKey: Hex, + isCompressed?: boolean // optional arg. (default) true=33b key, false=65b. +): Uint8Array; +function getPublicKeyAsync( + privateKey: Hex, + isCompressed?: boolean +): Promise; +// Use: +// - `ProjectivePoint.fromPrivateKey(privateKey)` for Point instance +// - `ProjectivePoint.fromHex(publicKey)` to convert hex / bytes into Point. + +// Generates low-s deterministic-k RFC6979 ECDSA signature. +// Use with `extraEntropy: true` to improve security. +function sign( + messageHash: Hex, // message hash (not message) which would be signed + privateKey: Hex, // private key which will sign the hash + opts = {} // optional params `{ lowS: boolean, extraEntropy: boolean | Hex }` +): Signature; +function signAsync(messageHash: Hex, privateKey: Hex, opts = {}): Promise; -```typescript +// Verifies ECDSA signature. +// lowS option Ensures a signature.s is in the lower-half of CURVE.n. +// Used in BTC, ETH. +// `{ lowS: false }` should only be used if you need OpenSSL-compatible signatures +function verify( + signature: Hex | Signature, // returned by the `sign` function + messageHash: Hex, // message hash (not message) that must be verified + publicKey: Hex, // public (not private) key + opts?: { lowS: boolean } // optional params; { lowS: true } by default +): boolean; + +// Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between +// key A and different key B. function getSharedSecret( privateKeyA: Uint8Array | string, // Alices's private key publicKeyB: Uint8Array | string, // Bob's public key - isCompressed = true // optional arg; `true` default returns 33 byte keys, `false` can return 65-byte -): Uint8Array; // Use Point.fromHex(publicKeyB).mul(privateKeyA) if you need Point instance -``` - -Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between key A and different key B. - -```js -const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; -const alicesPubkey = getPublicKey(utils.randomPrivateKey()); -getSharedSecret(privKey, alicesPubkey); -``` - -#### `Signature.recoverPublicKey(hash)` + isCompressed = true // optional arg. (default) true=33b key, false=65b. +): Uint8Array; +// Use `ProjectivePoint.fromHex(publicKeyB).multiply(privateKeyA)` for Point instance -```typescript +// Recover public key from Signature instance with `recovery` bit set signature.recoverPublicKey( msgHash: Uint8Array | string ): Uint8Array | undefined; ``` -`Signature` instance method, recovers public key from message hash. Returns 33-byte compact key. - -```js -const privKey = 'a1b770e7a3ba3b751b8f03d8b0712f0b428aa5a81d69efc8c522579f763ba5f4'; -const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; -const sig = await sign(msgHash, privKey); -sig.recoverPublicKey(msgHash); -``` - -#### Utilities - -The package exposes a few internal utilities for improved developer experience. +A bunch of useful **utilities** are also exposed: ```typescript -secp.utils { - randomPrivateKey: () => Uint8Array; // Returns secure key from CSPRNG - randomBytes: (bytesLength?: number) => Uint8Array; // Returns secure bytes from CSPRNG - isValidPrivateKey(privateKey: PrivKey): boolean; - mod(number: number | bigint, modulo = CURVE.P): bigint; // Modular division - invert(number: bigint, modulo?: bigint): bigint; // Modular inversion - hmacSha256(key: Uint8Array, ...messages: Uint8Array[]) => Promise; - hmacSha256Sync: undefined; // Must be specified if you need `signSync` to work, args are same - bytesToHex(bytes: Uint8Array): string; // If you need hex string as an output +export declare const etc: { + hexToBytes: (hex: string) => Bytes; + bytesToHex: (b: Bytes) => string; + concatBytes: (...arrs: Bytes[]) => Uint8Array; + bytesToNumberBE: (b: Bytes) => bigint; + numberToBytesBE: (num: bigint) => Bytes; + mod: (a: bigint, b?: bigint) => bigint; + invert: (num: bigint, md?: bigint) => bigint; + hmacSha256Async: (key: Bytes, ...msgs: Bytes[]) => Promise; + hmacSha256Sync: HmacFnSync; + hashToPrivateKey: (hash: Hex) => Bytes; + randomBytes: (len: number) => Bytes; +}; +export declare const utils: { + normPrivateKeyToScalar: (p: PrivKey) => bigint; + randomPrivateKey: () => Bytes; + isValidPrivateKey: (key: Hex) => boolean; + precompute(p: Point, windowSize?: number): Point; }; -secp.CURVE { P, n, a, b, Gx, Gy }; // CURVE prime; order; equation params; generator coordinates -secp.PPoint { // Elliptic curve point in Projective (x, y, z) coordinates. - constructor(x: bigint, y: bigint, z?: bigint); - static fromHex(hex: Uint8Array | string); - static fromPrivateKey(privateKey: Uint8Array | string | number | bigint); - ok(): PPoint; // checks Point validity - toRawBytes(isCompressed = false): Uint8Array; - toHex(isCompressed = false): string; - eql(other: Point): boolean; // a.equals(b) - neg(): Point; // negate - add(other: Point): Point; // addition - mul(scalar: bigint): Point; // constant-time scalar multiplication +class ProjectivePoint { + readonly px: bigint; + readonly py: bigint; + readonly pz: bigint; + constructor(px: bigint, py: bigint, pz: bigint); + static readonly BASE: Point; + static readonly ZERO: Point; + get x(): bigint; + get y(): bigint; + equals(other: Point): boolean; + add(other: Point): Point; + mul(n: bigint, safe?: boolean): Point; + mulAddQUns(R: Point, u1: bigint, u2: bigint): Point; + multiply(n: bigint): Point; + negate(): Point; + toAffine(): AffinePoint; + assertValidity(): Point; + static fromHex(hex: Hex): Point; + toHex(isCompressed?: boolean): string; + toRawBytes(isCompressed?: boolean): Uint8Array; + static fromPrivateKey(n: PrivKey): Point; } -secp.Signature { - constructor(r: bigint, s: bigint, recovery?: number); - static fromCompact(hex: Uint8Array | string); // R, S 32-byte each - ok(): Signature; // checks Signature validity - toCompactRawBytes(): Uint8Array; // R, S 32-byte each - toCompactHex(): string; // same, in hex string +class Signature { + readonly r: bigint; + readonly s: bigint; + readonly recovery?: number | undefined; + constructor(r: bigint, s: bigint, recovery?: number | undefined); + ok(): Signature; + static fromCompact(hex: Hex): Signature; + hasHighS(): boolean; + recoverPublicKey(msgh: Hex): Point; + toCompactRawBytes(): Uint8Array; + toCompactHex(): string; } +CURVE // curve prime; order; equation params, generator coordinates ``` ## Security -Noble is production-ready. +The module is production-ready. Use [noble-curves](https://github.com/paulmillr/noble-curves) if you need advanced security. -1. The library, as per version 1.2.0, has been audited by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf). See [changes since audit](https://github.com/paulmillr/noble-secp256k1/compare/1.2.0..main). - - The audit has been [crowdfunded](https://gitcoin.co/grants/2451/audit-of-noble-secp256k1-cryptographic-library) by community with help of [Umbra.cash](https://umbra.cash). -2. The library has also been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). You can run the fuzzer by yourself to check it. +1. The current version is rewrite of v1, which has been audited by cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf) (funded by [Umbra.cash](https://umbra.cash) & community). +2. It's being fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz): run the fuzzer by yourself to check. -We're using built-in JS `BigInt`, which is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack) as [per official spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#cryptography). But, _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library doesn't use constant-time bigints_. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we've hardened implementation of ec curve multiplication to be algorithmically constant time. +Our EC multiplication is hardened to be algorithmically constant time. We're using built-in JS `BigInt`, which is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack) as [per official spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#cryptography). But, _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library doesn't use constant-time bigints_. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. -We however consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector. +We consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector. ## Speed @@ -260,8 +249,6 @@ Compare to other libraries on M1 (`openssl` uses native bindings, not JS): ## Contributing -Check out a blog post about this library: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). - 1. Clone the repository. 2. `npm install` to install build dependencies like TypeScript 3. `npm run build` to compile TypeScript code @@ -286,6 +273,8 @@ Some functionality present in v1, such as schnorr and DER, was removed: use [**n - `Point` is now `ProjectivePoint`, working in 3d xyz projective coordinates instead of 2d xy affine - Removed schnorr signatures, asn.1 DER, custom precomputes. Use noble-curves if you need them - Support for environments that can't parse bigint literals has been removed +- Some utils such as `hmacSha256Sync` have been moved to `etc`: `import { etc } from "@noble/secp256k1"; +- node.js 18 and older are not supported without crypto shim (see [Usage](#usage)) ## License diff --git a/test/secp256k1.helpers.mjs b/test/secp256k1.helpers.mjs index 43fd6ec..79b3ee7 100644 --- a/test/secp256k1.helpers.mjs +++ b/test/secp256k1.helpers.mjs @@ -1,5 +1,6 @@ import { webcrypto } from 'node:crypto'; -if (!globalThis.crypto) globalThis.crypto = webcrypto; +// @ts-ignore +if (!globalThis.crypto) globalThis.crypto = webcrypto; // @ts-ignore // @ts-ignore export * as secp from '../index.js'; // @ts-ignore From 0d7d540951b71f5e54a508be75386ce4a7f50d27 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 01:36:12 +0000 Subject: [PATCH 051/145] Commit build output and lockfile to repo --- index.d.ts | 92 ++++++++ index.js | 519 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 222 ++++++++++++++++++++ 3 files changed, 833 insertions(+) create mode 100644 index.d.ts create mode 100644 index.js create mode 100644 package-lock.json diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..963ad9c --- /dev/null +++ b/index.d.ts @@ -0,0 +1,92 @@ +export declare const CURVE: { + P: bigint; + n: bigint; + a: bigint; + b: bigint; + Gx: bigint; + Gy: bigint; +}; +declare type Bytes = Uint8Array; +declare type Hex = Bytes | string; +declare type PrivKey = Hex | bigint; +interface AffinePoint { + x: bigint; + y: bigint; +} +declare class Point { + readonly px: bigint; + readonly py: bigint; + readonly pz: bigint; + constructor(px: bigint, py: bigint, pz: bigint); + static readonly BASE: Point; + static readonly ZERO: Point; + get x(): bigint; + get y(): bigint; + equals(other: Point): boolean; + neg(): Point; + dbl(): Point; + add(other: Point): Point; + mul(n: bigint, safe?: boolean): Point; + mulAddQUns(R: Point, u1: bigint, u2: bigint): Point; + aff(): AffinePoint; + ok(): Point; + multiply(n: bigint): Point; + negate(): Point; + toAffine(): AffinePoint; + assertValidity(): Point; + static fromHex(hex: Hex): Point; + toHex(isCompressed?: boolean): string; + toRawBytes(isCompressed?: boolean): Uint8Array; + static fromPrivateKey(n: PrivKey): Point; +} +export declare const getPublicKey: (privKey: PrivKey, isCompressed?: boolean) => Uint8Array; +export declare class Signature { + readonly r: bigint; + readonly s: bigint; + readonly recovery?: number | undefined; + constructor(r: bigint, s: bigint, recovery?: number | undefined); + ok(): Signature; + static fromCompact(hex: Hex): Signature; + hasHighS(): boolean; + recoverPublicKey(msgh: Hex): Point; + toCompactRawBytes(): Uint8Array; + toCompactHex(): string; +} +declare type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); +export declare const signAsync: (msgh: Hex, priv: Hex, opts?: { + lowS?: boolean | undefined; + extraEntropy?: boolean | Hex | undefined; +}) => Promise; +export declare const sign: (msgh: Hex, priv: Hex, opts?: { + lowS?: boolean | undefined; + extraEntropy?: boolean | Hex | undefined; +}) => Signature; +declare type SigLike = { + r: bigint; + s: bigint; +}; +export declare const verify: (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts?: { + lowS: boolean; +}) => boolean; +export declare const getSharedSecret: (privA: Hex, pubB: Hex, isCompressed?: boolean) => Uint8Array; +export declare const etc: { + hexToBytes: (hex: string) => Bytes; + bytesToHex: (b: Bytes) => string; + concatBytes: (...arrs: Bytes[]) => Uint8Array; + bytesToNumberBE: (b: Bytes) => bigint; + numberToBytesBE: (num: bigint) => Bytes; + mod: (a: bigint, b?: bigint) => bigint; + invert: (num: bigint, md?: bigint) => bigint; + hmacSha256Async: (key: Bytes, ...msgs: Bytes[]) => Promise; + hmacSha256Sync: HmacFnSync; + hashToPrivateKey: (hash: Hex) => Bytes; + randomBytes: (len: number) => Bytes; +}; +export declare const utils: { + normPrivateKeyToScalar: (p: PrivKey) => bigint; + randomPrivateKey: () => Bytes; + isValidPrivateKey: (key: Hex) => boolean; + precompute(p: Point, windowSize?: number): Point; +}; +export declare const ProjectivePoint: typeof Point; +export {}; diff --git a/index.js b/index.js new file mode 100644 index 0000000..d68b53e --- /dev/null +++ b/index.js @@ -0,0 +1,519 @@ +const B256 = 2n ** 256n; +const P = B256 - 0x1000003d1n; +const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; +const _a = 0n; +const _b = 7n; +const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; +const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; +export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; +const fLen = 32; +const crv = (x) => mod(mod(x * mod(x * x)) + _a * x + _b); +const err = (m = '') => { throw new Error(m); }; +const big = (n) => typeof n === 'bigint'; +const str = (s) => typeof s === 'string'; +const fe = (n) => big(n) && 0n < n && n < P; +const ge = (n) => big(n) && 0n < n && n < N; +const au8 = (a, l) => !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? + err('Uint8Array expected') : a; +const u8n = (data) => new Uint8Array(data); +const u8fr = (arr) => Uint8Array.from(arr); +const toU8 = (a, len) => au8(str(a) ? h2b(a) : a, len); +const toPriv = (p) => { + if (!big(p)) + p = b2n(toU8(p, fLen)); + return ge(p) ? p : err('private key out of range'); +}; +let Gpows = undefined; +const isPoint = (p) => (p instanceof Point ? p : err('Point expected')); +class Point { + constructor(px, py, pz) { + this.px = px; + this.py = py; + this.pz = pz; + } + get x() { return this.aff().x; } + get y() { return this.aff().y; } + equals(other) { + const { px: X1, py: Y1, pz: Z1 } = this; + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); + const X1Z2 = mod(X1 * Z2), X2Z1 = mod(X2 * Z1); + const Y1Z2 = mod(Y1 * Z2), Y2Z1 = mod(Y2 * Z1); + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1; + } + neg() { return new Point(this.px, mod(-this.py), this.pz); } + dbl() { return this.add(this); } + add(other) { + const { px: X1, py: Y1, pz: Z1 } = this; + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); + const { a, b } = CURVE; + let X3 = 0n, Y3 = 0n, Z3 = 0n; + const b3 = mod(b * 3n); + let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); + let t4 = mod(X2 + Y2); + t3 = mod(t3 * t4); + t4 = mod(t0 + t1); + t3 = mod(t3 - t4); + t4 = mod(X1 + Z1); + let t5 = mod(X2 + Z2); + t4 = mod(t4 * t5); + t5 = mod(t0 + t2); + t4 = mod(t4 - t5); + t5 = mod(Y1 + Z1); + X3 = mod(Y2 + Z2); + t5 = mod(t5 * X3); + X3 = mod(t1 + t2); + t5 = mod(t5 - X3); + Z3 = mod(a * t4); + X3 = mod(b3 * t2); + Z3 = mod(X3 + Z3); + X3 = mod(t1 - Z3); + Z3 = mod(t1 + Z3); + Y3 = mod(X3 * Z3); + t1 = mod(t0 + t0); + t1 = mod(t1 + t0); + t2 = mod(a * t2); + t4 = mod(b3 * t4); + t1 = mod(t1 + t2); + t2 = mod(t0 - t2); + t2 = mod(a * t2); + t4 = mod(t4 + t2); + t0 = mod(t1 * t4); + Y3 = mod(Y3 + t0); + t0 = mod(t5 * t4); + X3 = mod(t3 * X3); + X3 = mod(X3 - t0); + t0 = mod(t3 * t1); + Z3 = mod(t5 * Z3); + Z3 = mod(Z3 + t0); + return new Point(X3, Y3, Z3); + } + mul(n, safe = true) { + if (!safe && n === 0n) + return I; + if (!ge(n)) + err('invalid scalar'); + if (this.equals(G)) + return wNAF(n).p; + let p = I, f = G; + for (let d = this; n > 0n; d = d.dbl(), n >>= 1n) { + if (n & 1n) + p = p.add(d); + else if (safe) + f = f.add(d); + } + return p; + } + mulAddQUns(R, u1, u2) { + return this.mul(u1, false).add(R.mul(u2, false)).ok(); + } + aff() { + const { px: x, py: y, pz: z } = this; + if (this.equals(I)) + return { x: 0n, y: 0n }; + if (z === 1n) + return { x, y }; + const iz = inv(z); + if (mod(z * iz) !== 1n) + err('invalid inverse'); + return { x: mod(x * iz), y: mod(y * iz) }; + } + ok() { + const { x, y } = this.aff(); + if (!fe(x) || !fe(y)) + err('Point invalid: x or y'); + return mod(y * y) === crv(x) ? + this : err('Point invalid: not on curve'); + } + multiply(n) { return this.mul(n); } + negate() { return this.neg(); } + toAffine() { return this.aff(); } + assertValidity() { return this.ok(); } + static fromHex(hex) { + hex = toU8(hex); + let p = undefined; + const head = hex[0], tail = hex.subarray(1); + const x = slcNum(tail, 0, fLen), len = hex.length; + if (len === 33 && [0x02, 0x03].includes(head)) { + if (!fe(x)) + err('Point hex invalid: x not FE'); + let y = sqrt(crv(x)); + const isYOdd = (y & 1n) === 1n; + const headOdd = (head & 1) === 1; + if (headOdd !== isYOdd) + y = mod(-y); + p = new Point(x, y, 1n); + } + if (len === 65 && head === 0x04) + p = new Point(x, slcNum(tail, fLen, 2 * fLen), 1n); + return p ? p.ok() : err('Point is not on curve'); + } + toHex(isCompressed = true) { + const { x, y } = this.aff(); + const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; + return `${head}${n2h(x)}${isCompressed ? '' : n2h(y)}`; + } + toRawBytes(isCompressed = true) { + return h2b(this.toHex(isCompressed)); + } + static fromPrivateKey(n) { + return G.mul(toPriv(n)); + } +} +Point.BASE = new Point(Gx, Gy, 1n); +Point.ZERO = new Point(0n, 1n, 0n); +const { BASE: G, ZERO: I } = Point; +const mod = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; +const inv = (num, md = P) => { + if (num === 0n || md <= 0n) + err(`no inverse n=${num} mod=${md}`); + let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; + while (a !== 0n) { + const q = b / a, r = b % a; + const m = x - u * q, n = y - v * q; + b = a, a = r, x = u, y = v, u = m, v = n; + } + return b === 1n ? mod(x, md) : err('no inverse'); +}; +const pow = (num, e, md = P) => { + if (md <= 0n || e < 0n) + err('pow invalid'); + if (md === 1n) + return 0n; + let res = 1n; + for (; e > 0n; e >>= 1n) { + if (e & 1n) + res = (res * num) % md; + num = (num * num) % md; + } + return res; +}; +const sqrt = (n) => { + const r = pow(n, (P + 1n) / 4n, P); + return mod(r * r) === n ? r : err('sqrt invalid'); +}; +const padh = (num, pad) => num.toString(16).padStart(pad, '0'); +const b2h = (b) => Array.from(b).map(e => padh(e, 2)).join(''); +const h2n = (hex) => (str(hex) ? BigInt(`0x${hex || '0'}`) : err()); +const h2b = (hex) => { + const l = hex.length; + if (!str(hex) || l % 2) + err('hex invalid'); + const arr = u8n(l / 2); + for (let i = 0; i < arr.length; i++) { + const j = i * 2; + const h = hex.slice(j, j + 2); + const b = Number.parseInt(h, 16); + if (Number.isNaN(b) || b < 0) + err('hex invalid'); + arr[i] = b; + } + return arr; +}; +const b2n = (b) => h2n(b2h(b)); +const slcNum = (b, from, to) => b2n(b.slice(from, to)); +const n2b = (num) => { + return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); +}; +const n2h = (num) => b2h(n2b(num)); +const concatB = (...arrs) => { + const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); + let pad = 0; + arrs.forEach(a => { r.set(au8(a), pad); pad += a.length; }); + return r; +}; +const moreThanHalfN = (n) => n > (N >> 1n); +export const getPublicKey = (privKey, isCompressed = true) => { + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); +}; +export class Signature { + constructor(r, s, recovery) { + this.r = r; + this.s = s; + this.recovery = recovery; + this.ok(); + } + ok() { return ge(this.r) && ge(this.s) ? this : err(); } + static fromCompact(hex) { + hex = toU8(hex, 64); + return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); + } + hasHighS() { return moreThanHalfN(this.s); } + recoverPublicKey(msgh) { + const { r, s, recovery: rec } = this; + if (![0, 1, 2, 3].includes(rec)) + err('recovery id invalid'); + const h = bits2int_modN(toU8(msgh, 32)); + const radj = rec === 2 || rec === 3 ? r + N : r; + if (radj >= P) + err('q.x invalid'); + const prefix = (rec & 1) === 0 ? '02' : '03'; + const R = Point.fromHex(`${prefix}${n2h(radj)}`); + const ir = inv(radj, N); + const u1 = mod(-h * ir, N); + const u2 = mod(s * ir, N); + return G.mulAddQUns(R, u1, u2); + } + toCompactRawBytes() { return h2b(this.toCompactHex()); } + toCompactHex() { return n2h(this.r) + n2h(this.s); } +} +const bits2int = (bytes) => { + const delta = bytes.length * 8 - 256; + const num = b2n(bytes); + return delta > 0 ? num >> BigInt(delta) : num; +}; +const bits2int_modN = (bytes) => { + return mod(bits2int(bytes), N); +}; +const i2o = (num) => n2b(num); +const cr = () => typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; +let _hmacSync; +const stdo = { lowS: true }; +const vstdo = { lowS: true }; +const prepSig = (msgh, priv, opts = stdo) => { + if (['der', 'recovered', 'canonical'].some(k => k in opts)) + err('sign() legacy options not supported'); + let { lowS } = opts; + if (lowS == null) + lowS = true; + const h1i = bits2int_modN(toU8(msgh)); + const h1o = i2o(h1i); + const d = toPriv(priv); + const seed = [i2o(d), h1o]; + let ent = opts.extraEntropy; + if (ent != null) { + if (ent === true) + ent = etc.randomBytes(fLen); + const e = toU8(ent); + if (e.length !== fLen) + err(); + seed.push(e); + } + const m = h1i; + const k2sig = (kBytes) => { + const k = bits2int(kBytes); + if (!ge(k)) + return; + const ik = inv(k, N); + const q = G.mul(k).aff(); + const r = mod(q.x, N); + if (r === 0n) + return; + const s = mod(ik * mod(m + mod(d * r, N), N), N); + if (s === 0n) + return; + let normS = s; + let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); + if (lowS && moreThanHalfN(s)) { + normS = mod(-s, N); + rec ^= 1; + } + return new Signature(r, normS, rec); + }; + return { seed: concatB(...seed), k2sig }; +}; +function hmacDrbg(asynchronous) { + let v = u8n(fLen); + let k = u8n(fLen); + let i = 0; + const reset = () => { v.fill(1); k.fill(0); i = 0; }; + const _e = 'drbg: tried 1000 values'; + if (asynchronous) { + const h = (...b) => etc.hmacSha256Async(k, v, ...b); + const reseed = async (seed = u8n()) => { + k = await h(u8fr([0x00]), seed); + v = await h(); + if (seed.length === 0) + return; + k = await h(u8fr([0x01]), seed); + v = await h(); + }; + const gen = async () => { + if (i++ >= 1000) + err(_e); + v = await h(); + return v; + }; + return async (seed, pred) => { + reset(); + await reseed(seed); + let res = undefined; + while (!(res = pred(await gen()))) + await reseed(); + reset(); + return res; + }; + } + else { + const h = (...b) => { + const f = _hmacSync; + if (!f) + err('utils.hmacSha256Sync not set'); + return f(k, v, ...b); + }; + const reseed = (seed = u8n()) => { + k = h(u8fr([0x00]), seed); + v = h(); + if (seed.length === 0) + return; + k = h(u8fr([0x01]), seed); + v = h(); + }; + const gen = () => { + if (i++ >= 1000) + err(_e); + v = h(); + return v; + }; + return (seed, pred) => { + reset(); + reseed(seed); + let res = undefined; + while (!(res = pred(gen()))) + reseed(); + reset(); + return res; + }; + } +} +; +export const signAsync = async (msgh, priv, opts = stdo) => { + const { seed, k2sig } = prepSig(msgh, priv, opts); + const genUntil = hmacDrbg(true); + return genUntil(seed, k2sig); +}; +export const sign = (msgh, priv, opts = stdo) => { + const { seed, k2sig } = prepSig(msgh, priv, opts); + const genUntil = hmacDrbg(false); + return genUntil(seed, k2sig); +}; +export const verify = (sig, msgh, pub, opts = vstdo) => { + let { lowS } = opts; + if (lowS == null) + lowS = true; + if ('strict' in opts) + err('verify() legacy options not supported'); + let sig_, h, P; + const rs = sig && typeof sig === 'object' && 'r' in sig; + if (!rs && (toU8(sig).length !== 2 * fLen)) + err('signature must be 64 bytes'); + try { + sig_ = rs ? new Signature(sig.r, sig.s).ok() : Signature.fromCompact(sig); + h = bits2int_modN(toU8(msgh, fLen)); + P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); + } + catch (e) { + return false; + } + if (!sig_) + return false; + const { r, s } = sig_; + if (lowS && moreThanHalfN(s)) + return false; + let R; + try { + const is = inv(s, N); + const u1 = mod(h * is, N); + const u2 = mod(r * is, N); + R = G.mulAddQUns(P, u1, u2).aff(); + } + catch (error) { + return false; + } + if (!R) + return false; + const v = mod(R.x, N); + return v === r; +}; +export const getSharedSecret = (privA, pubB, isCompressed = true) => { + return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); +}; +const hashToPrivateKey = (hash) => { + hash = toU8(hash); + const minLen = fLen + 8; + if (hash.length < minLen || hash.length > 1024) + err('expected proper params'); + const num = mod(b2n(hash), N - 1n) + 1n; + return n2b(num); +}; +export const etc = { + hexToBytes: h2b, bytesToHex: b2h, + concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, + mod, invert: inv, + hmacSha256Async: async (key, ...msgs) => { + const m = concatB(...msgs); + const crypto = cr(); + if (!crypto) + return err('utils.hmacSha256Async not set'); + const s = crypto.subtle; + const k = await s.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); + return u8n(await s.sign('HMAC', k, m)); + }, + hmacSha256Sync: _hmacSync, + hashToPrivateKey, + randomBytes: (len) => { + const crypto = cr(); + if (!crypto) + err('crypto.getRandomValues must be defined'); + return crypto.getRandomValues(u8n(len)); + }, +}; +export const utils = { + normPrivateKeyToScalar: toPriv, + randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 8)), + isValidPrivateKey: (key) => { try { + return !!toPriv(key); + } + catch (e) { + return false; + } }, + precompute(p, windowSize = 8) { return p; } +}; +Object.defineProperties(etc, { hmacSha256Sync: { + configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) + _hmacSync = f; }, + } }); +const W = 8; +const precompute = () => { + const points = []; + const windows = 256 / W + 1; + let p = G, b = p; + for (let w = 0; w < windows; w++) { + b = p; + points.push(b); + for (let i = 1; i < 2 ** (W - 1); i++) { + b = b.add(p); + points.push(b); + } + p = b.dbl(); + } + return points; +}; +const wNAF = (n) => { + const comp = Gpows || (Gpows = precompute()); + const neg = (cnd, p) => { let n = p.neg(); return cnd ? n : p; }; + let p = I, f = G; + const windows = 1 + 256 / W; + const wsize = 2 ** (W - 1); + const mask = BigInt(2 ** W - 1); + const maxNum = 2 ** W; + const shiftBy = BigInt(W); + for (let w = 0; w < windows; w++) { + const off = w * wsize; + let wbits = Number(n & mask); + n >>= shiftBy; + if (wbits > wsize) { + wbits -= maxNum; + n += 1n; + } + const off1 = off, off2 = off + Math.abs(wbits) - 1; + const cnd1 = w % 2 !== 0, cnd2 = wbits < 0; + if (wbits === 0) { + f = f.add(neg(cnd1, comp[off1])); + } + else { + p = p.add(neg(cnd2, comp[off2])); + } + } + return { p, f }; +}; +export const ProjectivePoint = Point; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6b5f7db --- /dev/null +++ b/package-lock.json @@ -0,0 +1,222 @@ +{ + "name": "@noble/secp256k1", + "version": "2.0.0-pre", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@noble/secp256k1", + "version": "2.0.0-pre", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "devDependencies": { + "@noble/hashes": "1.2.0", + "@types/node": "17.0.18", + "fast-check": "3.0.0", + "micro-bmark": "0.3.0", + "micro-should": "0.4.0", + "terser": "5.16.1", + "typescript": "4.7.3" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@types/node": { + "version": "17.0.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", + "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/fast-check": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.0.0.tgz", + "integrity": "sha512-uujtrFJEQQqnIMO52ARwzPcuV4omiL1OJBUBLE9WnNFeu0A97sREXDOmCIHY+Z6KLVcemUf09rWr0q0Xy/Y/Ew==", + "dev": true, + "dependencies": { + "pure-rand": "^5.0.1" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + }, + "node_modules/micro-bmark": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/micro-bmark/-/micro-bmark-0.3.0.tgz", + "integrity": "sha512-rYu+AtUq8lC3zPCoxkOOtwhgJoMpCDGe0/BXUCkj6+H9f/U/TunH/n/qkN98yh04dCCtDV8Aj9uYO3+DKxYrcw==", + "dev": true + }, + "node_modules/micro-should": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/micro-should/-/micro-should-0.4.0.tgz", + "integrity": "sha512-Vclj8yrngSYc9Y3dL2C+AdUlTkyx/syWc4R7LYfk4h7+icfF0DoUBGjjUIaEDzZA19RzoI+Hg8rW9IRoNGP0tQ==", + "dev": true + }, + "node_modules/pure-rand": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-5.0.5.tgz", + "integrity": "sha512-BwQpbqxSCBJVpamI6ydzcKqyFmnd5msMWUGvzXLm1aXvusbbgkbOto/EUPM00hjveJEaJtdbhUjKSzWRhQVkaw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + } + } +} From 7a2bfec24159ea455fc9499ad62a952b807b532b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 01:39:51 +0000 Subject: [PATCH 052/145] Separate build directory for terser --- build/package-lock.json | 135 ++++++++++++++++++++++++++++++++++++++++ build/package.json | 16 +++++ package-lock.json | 127 ------------------------------------- package.json | 4 +- 4 files changed, 152 insertions(+), 130 deletions(-) create mode 100644 build/package-lock.json create mode 100644 build/package.json diff --git a/build/package-lock.json b/build/package-lock.json new file mode 100644 index 0000000..b3f326c --- /dev/null +++ b/build/package-lock.json @@ -0,0 +1,135 @@ +{ + "name": "build", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "build", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "terser": "5.16.6" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", + "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + } + } +} diff --git a/build/package.json b/build/package.json new file mode 100644 index 0000000..bade171 --- /dev/null +++ b/build/package.json @@ -0,0 +1,16 @@ +{ + "name": "build", + "private": true, + "version": "1.0.0", + "description": "Builds minified file", + "main": "noble-secp256k1.js", + "scripts": { + "terser": "terser --ecma 2020 -m -c < ../index.js" + }, + "keywords": [], + "author": "", + "license": "MIT", + "devDependencies": { + "terser": "5.16.6" + } +} diff --git a/package-lock.json b/package-lock.json index 6b5f7db..81199e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,72 +16,12 @@ "license": "MIT", "devDependencies": { "@noble/hashes": "1.2.0", - "@types/node": "17.0.18", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", - "terser": "5.16.1", "typescript": "4.7.3" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, "node_modules/@noble/hashes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", @@ -94,36 +34,6 @@ } ] }, - "node_modules/@types/node": { - "version": "17.0.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", - "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "node_modules/fast-check": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.0.0.tgz", @@ -168,43 +78,6 @@ } ] }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/typescript": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", diff --git a/package.json b/package.json index f885ace..ba80829 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "test": "node test/secp256k1.test.mjs", "coverage": "jest --coverage", "bench": "node test/benchmark.js", - "min": "terser --ecma 2020 -m -c < lib/index.js", + "min": "cd build; npm install; npm run terser", "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts`LOC\"" }, "author": "Paul Miller (https://paulmillr.com)", @@ -29,11 +29,9 @@ "license": "MIT", "devDependencies": { "@noble/hashes": "1.2.0", - "@types/node": "17.0.18", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", - "terser": "5.16.1", "typescript": "4.7.3" }, "keywords": [ From 9aebbc9e6e326dec4132b8751eda7dbc7e5b9f33 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 01:43:35 +0000 Subject: [PATCH 053/145] Produce index.js with comments --- index.js | 457 +++++++++++++++++++++++++------------------------- tsconfig.json | 1 - 2 files changed, 232 insertions(+), 226 deletions(-) diff --git a/index.js b/index.js index d68b53e..cce3a0b 100644 --- a/index.js +++ b/index.js @@ -1,185 +1,187 @@ -const B256 = 2n ** 256n; -const P = B256 - 0x1000003d1n; -const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; -const _a = 0n; -const _b = 7n; -const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; -const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; -export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; -const fLen = 32; -const crv = (x) => mod(mod(x * mod(x * x)) + _a * x + _b); -const err = (m = '') => { throw new Error(m); }; -const big = (n) => typeof n === 'bigint'; -const str = (s) => typeof s === 'string'; -const fe = (n) => big(n) && 0n < n && n < P; -const ge = (n) => big(n) && 0n < n && n < N; -const au8 = (a, l) => !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? +/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ +const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve +const P = B256 - 0x1000003d1n; // curve's field prime +const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order +const _a = 0n; // a equation's param +const _b = 7n; // b equation's param +const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x +const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y +export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables +const fLen = 32; // field / group byte length +const crv = (x) => mod(mod(x * mod(x * x)) + _a * x + _b); // x³ + ax + b weierstrass formula +const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace +const big = (n) => typeof n === 'bigint'; // is big integer +const str = (s) => typeof s === 'string'; // is string +const fe = (n) => big(n) && 0n < n && n < P; // is field element (invertible) +const ge = (n) => big(n) && 0n < n && n < N; // is group element +const au8 = (a, l) => // is Uint8Array (of specific length) + !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; -const u8n = (data) => new Uint8Array(data); -const u8fr = (arr) => Uint8Array.from(arr); -const toU8 = (a, len) => au8(str(a) ? h2b(a) : a, len); +const u8n = (data) => new Uint8Array(data); // creates Uint8Array +const u8fr = (arr) => Uint8Array.from(arr); // another shortcut +const toU8 = (a, len) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a const toPriv = (p) => { if (!big(p)) - p = b2n(toU8(p, fLen)); - return ge(p) ? p : err('private key out of range'); + p = b2n(toU8(p, fLen)); // convert to bigint when bytes + return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; -let Gpows = undefined; -const isPoint = (p) => (p instanceof Point ? p : err('Point expected')); +let Gpows = undefined; // precomputes for base point G +const isPoint = (p) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { constructor(px, py, pz) { this.px = px; this.py = py; this.pz = pz; - } - get x() { return this.aff().x; } - get y() { return this.aff().y; } + } // z is optional + get x() { return this.aff().x; } // .x, .y will call expensive toAffine. + get y() { return this.aff().y; } // Should be used with care. equals(other) { const { px: X1, py: Y1, pz: Z1 } = this; - const { px: X2, py: Y2, pz: Z2 } = isPoint(other); + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // isPoint() checks class equality const X1Z2 = mod(X1 * Z2), X2Z1 = mod(X2 * Z1); const Y1Z2 = mod(Y1 * Z2), Y2Z1 = mod(Y2 * Z1); return X1Z2 === X2Z1 && Y1Z2 === Y2Z1; } - neg() { return new Point(this.px, mod(-this.py), this.pz); } - dbl() { return this.add(this); } + neg() { return new Point(this.px, mod(-this.py), this.pz); } // negate, flips point over y coord + dbl() { return this.add(this); } // point doubling add(other) { - const { px: X1, py: Y1, pz: Z1 } = this; - const { px: X2, py: Y2, pz: Z2 } = isPoint(other); + const { px: X1, py: Y1, pz: Z1 } = this; // formula from Renes-Costello-Batina + const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 const { a, b } = CURVE; - let X3 = 0n, Y3 = 0n, Z3 = 0n; + let X3 = 0n, Y3 = 0n, Z3 = 0n; // Cost: 12M + 0S + 3*a + 3*b3 + 23add const b3 = mod(b * 3n); - let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); - let t4 = mod(X2 + Y2); + let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); // step 1 + let t4 = mod(X2 + Y2); // step 5 t3 = mod(t3 * t4); t4 = mod(t0 + t1); t3 = mod(t3 - t4); t4 = mod(X1 + Z1); - let t5 = mod(X2 + Z2); + let t5 = mod(X2 + Z2); // step 10 t4 = mod(t4 * t5); t5 = mod(t0 + t2); t4 = mod(t4 - t5); t5 = mod(Y1 + Z1); - X3 = mod(Y2 + Z2); + X3 = mod(Y2 + Z2); // step 15 t5 = mod(t5 * X3); X3 = mod(t1 + t2); t5 = mod(t5 - X3); Z3 = mod(a * t4); - X3 = mod(b3 * t2); + X3 = mod(b3 * t2); // step 20 Z3 = mod(X3 + Z3); X3 = mod(t1 - Z3); Z3 = mod(t1 + Z3); Y3 = mod(X3 * Z3); - t1 = mod(t0 + t0); + t1 = mod(t0 + t0); // step 25 t1 = mod(t1 + t0); t2 = mod(a * t2); t4 = mod(b3 * t4); t1 = mod(t1 + t2); - t2 = mod(t0 - t2); + t2 = mod(t0 - t2); // step 30 t2 = mod(a * t2); t4 = mod(t4 + t2); t0 = mod(t1 * t4); Y3 = mod(Y3 + t0); - t0 = mod(t5 * t4); + t0 = mod(t5 * t4); // step 35 X3 = mod(t3 * X3); X3 = mod(X3 - t0); t0 = mod(t3 * t1); Z3 = mod(t5 * Z3); - Z3 = mod(Z3 + t0); + Z3 = mod(Z3 + t0); // step 40 return new Point(X3, Y3, Z3); } mul(n, safe = true) { if (!safe && n === 0n) - return I; + return I; // in unsafe mode, allow zero if (!ge(n)) - err('invalid scalar'); + err('invalid scalar'); // must be 0 < n < CURVE.n if (this.equals(G)) - return wNAF(n).p; - let p = I, f = G; - for (let d = this; n > 0n; d = d.dbl(), n >>= 1n) { + return wNAF(n).p; // Use precomputes for base point + let p = I, f = G; // init result point & fake point + for (let d = this; n > 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder if (n & 1n) - p = p.add(d); + p = p.add(d); // if bit is present, add to point else if (safe) - f = f.add(d); + f = f.add(d); // if not, add to fake for timing safety } return p; } mulAddQUns(R, u1, u2) { - return this.mul(u1, false).add(R.mul(u2, false)).ok(); - } + return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related + } // to private keys. Doesn't use Shamir trick aff() { - const { px: x, py: y, pz: z } = this; + const { px: x, py: y, pz: z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) if (this.equals(I)) - return { x: 0n, y: 0n }; + return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) - return { x, y }; - const iz = inv(z); + return { x, y }; // if z is 1, pass affine coordinates as-is + const iz = inv(z); // z^-1: invert z if (mod(z * iz) !== 1n) - err('invalid inverse'); - return { x: mod(x * iz), y: mod(y * iz) }; + err('invalid inverse'); // (z * z^-1) must be 1, otherwise bad math + return { x: mod(x * iz), y: mod(y * iz) }; // x = x*z^-1; y = y*z^-1 } ok() { - const { x, y } = this.aff(); + const { x, y } = this.aff(); // convert to 2d xy affine point. if (!fe(x) || !fe(y)) - err('Point invalid: x or y'); - return mod(y * y) === crv(x) ? + err('Point invalid: x or y'); // x and y must be in range 0 < n < P + return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal this : err('Point invalid: not on curve'); } - multiply(n) { return this.mul(n); } + multiply(n) { return this.mul(n); } // Aliases for compatibilty negate() { return this.neg(); } toAffine() { return this.aff(); } assertValidity() { return this.ok(); } static fromHex(hex) { - hex = toU8(hex); + hex = toU8(hex); // converts hex string to Uint8Array let p = undefined; - const head = hex[0], tail = hex.subarray(1); - const x = slcNum(tail, 0, fLen), len = hex.length; - if (len === 33 && [0x02, 0x03].includes(head)) { + const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data + const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate + if (len === 33 && [0x02, 0x03].includes(head)) { // compressed points: 33b, start if (!fe(x)) - err('Point hex invalid: x not FE'); - let y = sqrt(crv(x)); - const isYOdd = (y & 1n) === 1n; - const headOdd = (head & 1) === 1; + err('Point hex invalid: x not FE'); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; +Point.BASE = new Point(Gx, Gy, 1n); // generator / base point. +Point.ZERO = new Point(0n, 1n, 0n); // identity / zero point +const { BASE: G, ZERO: I } = Point; // Generator, identity points +const mod = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num, md = P) => { if (num === 0n || md <= 0n) - err(`no inverse n=${num} mod=${md}`); + err(`no inverse n=${num} mod=${md}`); // negative exponent not supported let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; - while (a !== 0n) { - const q = b / a, r = b % a; + while (a !== 0n) { // uses euclidean gcd algorithm + const q = b / a, r = b % a; // not constant-time const m = x - u * q, n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } - return b === 1n ? mod(x, md) : err('no inverse'); + return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point }; const pow = (num, e, md = P) => { if (md <= 0n || e < 0n) - err('pow invalid'); + err('pow invalid'); // exponentiation by squaring if (md === 1n) - return 0n; - let res = 1n; + return 0n; // the ladder can leak exponent bits + let res = 1n; // and is vulnerable to timing attacks for (; e > 0n; e >>= 1n) { if (e & 1n) res = (res * num) % md; @@ -188,42 +190,42 @@ const pow = (num, e, md = P) => { return res; }; const sqrt = (n) => { - const r = pow(n, (P + 1n) / 4n, P); - return mod(r * r) === n ? r : err('sqrt invalid'); + const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square + return mod(r * r) === n ? r : err('sqrt invalid'); // Roots from 1;24,51,10 to Dan Shanks" }; const padh = (num, pad) => num.toString(16).padStart(pad, '0'); -const b2h = (b) => Array.from(b).map(e => padh(e, 2)).join(''); -const h2n = (hex) => (str(hex) ? BigInt(`0x${hex || '0'}`) : err()); +const b2h = (b) => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex +const h2n = (hex) => (str(hex) ? BigInt(`0x${hex || '0'}`) : err()); // hex to number const h2b = (hex) => { - const l = hex.length; + const l = hex.length; // error if not string, if (!str(hex) || l % 2) - err('hex invalid'); - const arr = u8n(l / 2); + err('hex invalid'); // or has odd length like 3, 5. + const arr = u8n(l / 2); // create result array for (let i = 0; i < arr.length; i++) { const j = i * 2; - const h = hex.slice(j, j + 2); - const b = Number.parseInt(h, 16); + const h = hex.slice(j, j + 2); // hexByte. slice is faster than substr + const b = Number.parseInt(h, 16); // byte, created from string part if (Number.isNaN(b) || b < 0) - err('hex invalid'); + err('hex invalid'); // byte must be valid 0 <= byte < 256 arr[i] = b; } return arr; }; -const b2n = (b) => h2n(b2h(b)); -const slcNum = (b, from, to) => b2n(b.slice(from, to)); +const b2n = (b) => h2n(b2h(b)); // bytes to number +const slcNum = (b, from, to) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num) => { return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; -const n2h = (num) => b2h(n2b(num)); +const n2h = (num) => b2h(n2b(num)); // number to hex const concatB = (...arrs) => { - const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); - let pad = 0; - arrs.forEach(a => { r.set(au8(a), pad); pad += a.length; }); + const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length + let pad = 0; // walk through each array, ensure + arrs.forEach(a => { r.set(au8(a), pad); pad += a.length; }); // they have proper type return r; }; -const moreThanHalfN = (n) => n > (N >> 1n); +const moreThanHalfN = (n) => n > (N >> 1n); // if a number is bigger than CURVE.n/2 export const getPublicKey = (privKey, isCompressed = true) => { - return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private }; export class Signature { constructor(r, s, recovery) { @@ -232,111 +234,112 @@ export class Signature { this.recovery = recovery; this.ok(); } - ok() { return ge(this.r) && ge(this.s) ? this : err(); } + ok() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n static fromCompact(hex) { - hex = toU8(hex, 64); + hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } hasHighS() { return moreThanHalfN(this.s); } recoverPublicKey(msgh) { - const { r, s, recovery: rec } = this; + const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 if (![0, 1, 2, 3].includes(rec)) - err('recovery id invalid'); - const h = bits2int_modN(toU8(msgh, 32)); - const radj = rec === 2 || rec === 3 ? r + N : r; + err('recovery id invalid'); // check recovery id + const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash + const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) - err('q.x invalid'); - const prefix = (rec & 1) === 0 ? '02' : '03'; - const R = Point.fromHex(`${prefix}${n2h(radj)}`); - const ir = inv(radj, N); - const u1 = mod(-h * ir, N); - const u2 = mod(s * ir, N); - return G.mulAddQUns(R, u1, u2); + err('q.x invalid'); // ensure q.x is still a field element + const prefix = (rec & 1) === 0 ? '02' : '03'; // prefix is 0x02 or 0x03 + const R = Point.fromHex(`${prefix}${n2h(radj)}`); // concat prefix + hex repr of r + const ir = inv(radj, N); // r^-1 + const u1 = mod(-h * ir, N); // -hr^-1 + const u2 = mod(s * ir, N); // sr^-1 + return G.mulAddQUns(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) } - toCompactRawBytes() { return h2b(this.toCompactHex()); } - toCompactHex() { return n2h(this.r) + n2h(this.s); } + toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr + toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr } const bits2int = (bytes) => { - const delta = bytes.length * 8 - 256; - const num = b2n(bytes); - return delta > 0 ? num >> BigInt(delta) : num; + const delta = bytes.length * 8 - 256; // RFC suggests optional truncating via bits2octets + const num = b2n(bytes); // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which + return delta > 0 ? num >> BigInt(delta) : num; // matches bits2int. bits2int can produce res>N. }; const bits2int_modN = (bytes) => { - return mod(bits2int(bytes), N); + return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; -const i2o = (num) => n2b(num); -const cr = () => typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; -let _hmacSync; -const stdo = { lowS: true }; -const vstdo = { lowS: true }; +const i2o = (num) => n2b(num); // int to octets +const cr = () => // We support: 1) browsers 2) node.js 19+ + typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; +let _hmacSync; // Can be redefined by use in utils; built-ins don't provide it +const stdo = { lowS: true }; // opts for sign() +const vstdo = { lowS: true }; // standard opts for verify() const prepSig = (msgh, priv, opts = stdo) => { - if (['der', 'recovered', 'canonical'].some(k => k in opts)) + if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); - let { lowS } = opts; + let { lowS } = opts; // generates low-s sigs by default if (lowS == null) - lowS = true; + lowS = true; // RFC6979 3.2: we skip step A, because const h1i = bits2int_modN(toU8(msgh)); const h1o = i2o(h1i); - const d = toPriv(priv); - const seed = [i2o(d), h1o]; - let ent = opts.extraEntropy; - if (ent != null) { + const d = toPriv(priv); // validate private key, convert to bigint + const seed = [i2o(d), h1o]; // Step D of RFC6979 3.2 + let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) + if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') if (ent === true) - ent = etc.randomBytes(fLen); - const e = toU8(ent); + ent = etc.randomBytes(fLen); // if true, use CSPRNG to generate data + const e = toU8(ent); // convert Hex|Bytes to Bytes if (e.length !== fLen) - err(); + err(); // Expected 32 bytes of extra data seed.push(e); } - const m = h1i; + const m = h1i; // convert msg to bigint const k2sig = (kBytes) => { - const k = bits2int(kBytes); + const k = bits2int(kBytes); // Transforms k into Signature if (!ge(k)) - return; - const ik = inv(k, N); - const q = G.mul(k).aff(); - const r = mod(q.x, N); + return; // Check 0 < k < CURVE.n + const ik = inv(k, N); // k^-1 mod n, NOT mod P + const q = G.mul(k).aff(); // q = Gk + const r = mod(q.x, N); // r = q.x mod n if (r === 0n) - return; - const s = mod(ik * mod(m + mod(d * r, N), N), N); + return; // r=0 invalid + const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1(m + rd) mod n if (s === 0n) - return; + return; // s=0 invalid let normS = s; - let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); - if (lowS && moreThanHalfN(s)) { - normS = mod(-s, N); + let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit + if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always + normS = mod(-s, N); // in the bottom half of CURVE.n rec ^= 1; } - return new Signature(r, normS, rec); + return new Signature(r, normS, rec); // use normS, not s }; return { seed: concatB(...seed), k2sig }; }; function hmacDrbg(asynchronous) { - let v = u8n(fLen); - let k = u8n(fLen); - let i = 0; + let v = u8n(fLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(fLen); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same + let i = 0; // Iterations counter, will throw when over 1000 const reset = () => { v.fill(1); k.fill(0); i = 0; }; const _e = 'drbg: tried 1000 values'; - if (asynchronous) { - const h = (...b) => etc.hmacSha256Async(k, v, ...b); + if (asynchronous) { // asynchronous=true + const h = (...b) => etc.hmacSha256Async(k, v, ...b); // hmac(k)(v, ...values) const reseed = async (seed = u8n()) => { - k = await h(u8fr([0x00]), seed); - v = await h(); + k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) + v = await h(); // v = hmac(K || V) if (seed.length === 0) return; - k = await h(u8fr([0x01]), seed); - v = await h(); + k = await h(u8fr([0x01]), seed); // k = hmac(K || V || 0x01 || seed) + v = await h(); // v = hmac(K || V) }; const gen = async () => { if (i++ >= 1000) err(_e); - v = await h(); + v = await h(); // v = hmac(K || V) return v; }; return async (seed, pred) => { - reset(); - await reseed(seed); - let res = undefined; + reset(); // the returned fn, don't, it's: 1. slower (JIT). 2. unsafe (async race conditions) + await reseed(seed); // Steps D-G + let res = undefined; // Step H: grind until k is in [1..n-1] while (!(res = pred(await gen()))) await reseed(); reset(); @@ -348,26 +351,26 @@ function hmacDrbg(asynchronous) { const f = _hmacSync; if (!f) err('utils.hmacSha256Sync not set'); - return f(k, v, ...b); + return f(k, v, ...b); // hmac(k)(v, ...values) }; const reseed = (seed = u8n()) => { - k = h(u8fr([0x00]), seed); - v = h(); + k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) + v = h(); // v = hmac(k || v) if (seed.length === 0) return; - k = h(u8fr([0x01]), seed); - v = h(); + k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) + v = h(); // v = hmac(k || v) }; const gen = () => { if (i++ >= 1000) err(_e); - v = h(); + v = h(); // v = hmac(k || v) return v; }; return (seed, pred) => { reset(); - reseed(seed); - let res = undefined; + reseed(seed); // Steps D-G + let res = undefined; // Step H: grind until k is in [1..n-1] while (!(res = pred(gen()))) reseed(); reset(); @@ -376,6 +379,7 @@ function hmacDrbg(asynchronous) { } } ; +// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2. hmacDrbg() export const signAsync = async (msgh, priv, opts = stdo) => { const { seed, k2sig } = prepSig(msgh, priv, opts); const genUntil = hmacDrbg(true); @@ -387,52 +391,52 @@ export const sign = (msgh, priv, opts = stdo) => { return genUntil(seed, k2sig); }; export const verify = (sig, msgh, pub, opts = vstdo) => { - let { lowS } = opts; + let { lowS } = opts; // ECDSA signature verification if (lowS == null) - lowS = true; + lowS = true; // Default lowS=true if ('strict' in opts) - err('verify() legacy options not supported'); - let sig_, h, P; - const rs = sig && typeof sig === 'object' && 'r' in sig; - if (!rs && (toU8(sig).length !== 2 * fLen)) + err('verify() legacy options not supported'); // legacy param + let sig_, h, P; // secg.org/sec1-v2.pdf 4.1.4 + const rs = sig && typeof sig === 'object' && 'r' in sig; // Previous ver supported DER sigs. We + if (!rs && (toU8(sig).length !== 2 * fLen)) // throw error when DER is suspected now. err('signature must be 64 bytes'); try { sig_ = rs ? new Signature(sig.r, sig.s).ok() : Signature.fromCompact(sig); - h = bits2int_modN(toU8(msgh, fLen)); - P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); + h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash + P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { return false; - } + } // Check sig for validity in both cases if (!sig_) return false; const { r, s } = sig_; if (lowS && moreThanHalfN(s)) - return false; + return false; // lowS bans sig.s >= CURVE.n/2 let R; try { - const is = inv(s, N); - const u1 = mod(h * is, N); - const u2 = mod(r * is, N); - R = G.mulAddQUns(P, u1, u2).aff(); + const is = inv(s, N); // s^-1 + const u1 = mod(h * is, N); // u1 = hs^-1 mod n + const u2 = mod(r * is, N); // u2 = rs^-1 mod n + R = G.mulAddQUns(P, u1, u2).aff(); // R = u1⋅G + u2⋅P } catch (error) { return false; } if (!R) - return false; + return false; // stop if R is identity / zero point const v = mod(R.x, N); - return v === r; + return v === r; // mod(R.x, n) == r }; export const getSharedSecret = (privA, pubB, isCompressed = true) => { - return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); + return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH }; const hashToPrivateKey = (hash) => { - hash = toU8(hash); - const minLen = fLen + 8; + hash = toU8(hash); // produces private keys with modulo bias + const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); - const num = mod(b2n(hash), N - 1n) + 1n; + const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); }; export const etc = { @@ -440,7 +444,7 @@ export const etc = { concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, hmacSha256Async: async (key, ...msgs) => { - const m = concatB(...msgs); + const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! const crypto = cr(); if (!crypto) return err('utils.hmacSha256Async not set'); @@ -451,7 +455,9 @@ export const etc = { hmacSha256Sync: _hmacSync, hashToPrivateKey, randomBytes: (len) => { - const crypto = cr(); + const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: + // import { webcrypto } from 'node:crypto'; + // if (!globalThis.crypto) globalThis.crypto = webcrypto; if (!crypto) err('crypto.getRandomValues must be defined'); return crypto.getRandomValues(u8n(len)); @@ -466,54 +472,55 @@ export const utils = { catch (e) { return false; } }, - precompute(p, windowSize = 8) { return p; } + precompute(p, windowSize = 8) { return p; } // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, } }); -const W = 8; +const W = 8; // Precomputes-related code. W = window size const precompute = () => { - const points = []; - const windows = 256 / W + 1; - let p = G, b = p; - for (let w = 0; w < windows; w++) { - b = p; - points.push(b); + const points = []; // 10x sign(), 2x verify(). To achieve this, + const windows = 256 / W + 1; // app needs to spend 40ms+ to calculate + let p = G, b = p; // a lot of points related to base point G. + for (let w = 0; w < windows; w++) { // Points are stored in array and used + b = p; // any time Gx multiplication is done. + points.push(b); // They consume 16-32 MiB of RAM. for (let i = 1; i < 2 ** (W - 1); i++) { b = b.add(p); points.push(b); } - p = b.dbl(); - } - return points; + p = b.dbl(); // Precomputes don't speed-up getSharedKey, + } // which multiplies user point by scalar, + return points; // when precomputes are using base point }; const wNAF = (n) => { - const comp = Gpows || (Gpows = precompute()); - const neg = (cnd, p) => { let n = p.neg(); return cnd ? n : p; }; - let p = I, f = G; - const windows = 1 + 256 / W; - const wsize = 2 ** (W - 1); - const mask = BigInt(2 ** W - 1); - const maxNum = 2 ** W; - const shiftBy = BigInt(W); + // Compared to other point mult methods, + const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction + const neg = (cnd, p) => { let n = p.neg(); return cnd ? n : p; }; // negate + let p = I, f = G; // f must be G, or could become I in the end + const windows = 1 + 256 / W; // W=8 17 windows + const wsize = 2 ** (W - 1); // W=8 128 window size + const mask = BigInt(2 ** W - 1); // W=8 will create mask 0b11111111 + const maxNum = 2 ** W; // W=8 256 + const shiftBy = BigInt(W); // W=8 8 for (let w = 0; w < windows; w++) { const off = w * wsize; - let wbits = Number(n & mask); - n >>= shiftBy; + let wbits = Number(n & mask); // extract W bits. + n >>= shiftBy; // shift number by W bits. if (wbits > wsize) { wbits -= maxNum; n += 1n; - } - const off1 = off, off2 = off + Math.abs(wbits) - 1; - const cnd1 = w % 2 !== 0, cnd2 = wbits < 0; + } // split if bits > max: +224 => 256-32 + const off1 = off, off2 = off + Math.abs(wbits) - 1; // offsets, evaluate both + const cnd1 = w % 2 !== 0, cnd2 = wbits < 0; // conditions, evaluate both if (wbits === 0) { - f = f.add(neg(cnd1, comp[off1])); + f = f.add(neg(cnd1, comp[off1])); // bits are 0: add garbage to fake point } - else { - p = p.add(neg(cnd2, comp[off2])); + else { // ^ can't add off2, off2 = I + p = p.add(neg(cnd2, comp[off2])); // bits are 1: add to result point } } - return { p, f }; -}; + return { p, f }; // return both real and fake points for JIT +}; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() export const ProjectivePoint = Point; diff --git a/tsconfig.json b/tsconfig.json index e8a97e3..4edd974 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,6 @@ "moduleResolution": "node", "outDir": ".", "noImplicitAny": true, - "removeComments": true, "preserveConstEnums": true, "baseUrl": ".", }, From 9e0336f3718f666b97a7b3fe17a170d4800709b3 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 01:52:47 +0000 Subject: [PATCH 054/145] readme 80-char limit --- README.md | 72 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1ee6d8e..e8262cc 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,14 @@ an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. -The library does not use dependencies and is as minimal as possible. [noble-curves](https://github.com/paulmillr/noble-curves) is advanced drop-in replacement for noble-secp256k1 with more features such as Schnorr signatures, DER encoding and support for different hash functions. +The library does not use dependencies and is as minimal as possible. +[noble-curves](https://github.com/paulmillr/noble-curves) is advanced drop-in +replacement for noble-secp256k1 with more features such as Schnorr signatures, +DER encoding and support for different hash functions. -Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions; [the online demo](https://paulmillr.com/ecc) and blog post [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). +Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions; +[the online demo](https://paulmillr.com/ecc) and blog post +[Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). ### This library belongs to _noble_ crypto @@ -28,7 +33,8 @@ Use NPM in browser and node.js: > npm install @noble/secp256k1 -For [Deno](https://deno.land), the module is available at `x/secp256k1`; or you can use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers). +For [Deno](https://deno.land), the module is available at `x/secp256k1`; +or you can use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers). ```js import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js @@ -148,6 +154,7 @@ signature.recoverPublicKey( A bunch of useful **utilities** are also exposed: ```typescript +type Bytes = Uint8Array; export declare const etc: { hexToBytes: (hex: string) => Bytes; bytesToHex: (b: Bytes) => string; @@ -178,8 +185,6 @@ class ProjectivePoint { get y(): bigint; equals(other: Point): boolean; add(other: Point): Point; - mul(n: bigint, safe?: boolean): Point; - mulAddQUns(R: Point, u1: bigint, u2: bigint): Point; multiply(n: bigint): Point; negate(): Point; toAffine(): AffinePoint; @@ -206,14 +211,30 @@ CURVE // curve prime; order; equation params, generator coordinates ## Security -The module is production-ready. Use [noble-curves](https://github.com/paulmillr/noble-curves) if you need advanced security. - -1. The current version is rewrite of v1, which has been audited by cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf) (funded by [Umbra.cash](https://umbra.cash) & community). -2. It's being fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz): run the fuzzer by yourself to check. - -Our EC multiplication is hardened to be algorithmically constant time. We're using built-in JS `BigInt`, which is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack) as [per official spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#cryptography). But, _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library doesn't use constant-time bigints_. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. - -We consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector. +The module is production-ready. Use +[noble-curves](https://github.com/paulmillr/noble-curves) if you need advanced security. + +1. The current version is rewrite of v1, which has been audited by cure53: +[PDF](https://cure53.de/pentest-report_noble-lib.pdf) (funded by [Umbra.cash](https://umbra.cash) & community). +2. It's being fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz): +run the fuzzer by yourself to check. + +Our EC multiplication is hardened to be algorithmically constant time. +We're using built-in JS `BigInt`, which is potentially vulnerable to +[timing attacks](https://en.wikipedia.org/wiki/Timing_attack) as +[per MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#cryptography). +But, _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard +to achieve in a scripting language. Which means _any other JS library doesn't +use constant-time bigints_. Including bn.js or anything else. +Even statically typed Rust, a language without GC, +[makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) +for some cases. If your goal is absolute security, don't use any JS lib — +including bindings to native ones. Use low-level libraries & languages. + +We consider infrastructure attacks like rogue NPM modules very important; +that's why it's crucial to minimize the amount of 3rd-party dependencies & native +bindings. If your app uses 500 dependencies, any dep could get hacked and you'll +be downloading malware with every `npm install`. Our goal is to minimize this attack vector. ## Speed @@ -254,20 +275,29 @@ Compare to other libraries on M1 (`openssl` uses native bindings, not JS): 3. `npm run build` to compile TypeScript code 4. `npm test` to run jest on `test/index.ts` -Special thanks to [Roman Koblov](https://github.com/romankoblov), who have helped to improve scalar multiplication speed. +Special thanks to [Roman Koblov](https://github.com/romankoblov), who have +helped to improve scalar multiplication speed. ## Upgrading -noble-secp256k1 v2.0 has been reduced 4x to just over 400 lines. It features improved security and smaller attack surface. +noble-secp256k1 v2.0 has been reduced 4x to just over 400 lines. It features +improved security and smaller attack surface. -Some functionality present in v1, such as schnorr and DER, was removed: use [**noble-curves**](https://github.com/paulmillr/noble-curves) if you still need it. +Some functionality present in v1, such as schnorr and DER, was removed: +use [**noble-curves**](https://github.com/paulmillr/noble-curves) if you still need it. -- `getPublicKey()` and `getSharedSecret()` now produce compressed 33-byte signatures by default. If you - need the old 65-byte behavior, set `isCompressed` option as `false`: `getPublicKey(priv, false)`, `getSharedSecret(a, b, false)` -- `sign()`: now returns `Signature` instance with `{ r, s, recovery }` properties. It could still be passed to `verify` as-is. - - `canonical` has been renamed to `lowS`. The default value is the same as before: `lowS: true` +- `getPublicKey()` and `getSharedSecret()` now produce compressed 33-byte + signatures by default. If you need the old 65-byte behavior, set isCompresse=false: + `getPublicKey(priv, false)`, `getSharedSecret(a, b, false)` +- `sign()`: now returns `Signature` instance with `{ r, s, recovery }` properties. + It could still be passed to `verify` as-is. + - `canonical` is now => `lowS`. The default value is the same as before: `lowS: true` - `recovered` has been removed. Recovery bit is always returned in the `Signature` instance - - `der` has been removed. DER encoding is no longer supported. Use compact format (32-byte r + 32-byte s), `Signature` instance methods `toCompactRawBytes` / `toCompactHex()`: `(await sign(msgHash, priv)).toCompactRawBytes()`. Use curves if you still need der + - `der` has been removed. DER encoding is no longer supported. Use compact + format (32-byte r + 32-byte s), `Signature` instance methods + `toCompactRawBytes` / `toCompactHex()`: + `(await sign(msgHash, priv)).toCompactRawBytes()`. + Use noble-curves if you still need DER - `verify()`: `strict` option has been renamed to `lowS`, default value is still the same - `recoverPublicKey(msgHash, sig, recovery)` has been changed to `sig.recoverPublicKey(msgHash)` - `Point` is now `ProjectivePoint`, working in 3d xyz projective coordinates instead of 2d xy affine From 13a2a7a72867fbb76413a13735d7dcc76dcf0951 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 02:01:44 +0000 Subject: [PATCH 055/145] Update benchmark --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e8262cc..8ffd2ed 100644 --- a/README.md +++ b/README.md @@ -242,12 +242,12 @@ Use [noble-curves](https://github.com/paulmillr/noble-curves) if you need even h Benchmarks measured with Apple M2 on MacOS 13 with node.js 19. - getPublicKey(utils.randomPrivateKey()) x 5,047 ops/sec @ 198μs/op - sign x 2,955 ops/sec @ 338μs/op - verify x 470 ops/sec @ 2ms/op - getSharedSecret x 403 ops/sec @ 2ms/op - recoverPublicKey x 485 ops/sec @ 2ms/op - Point.fromHex (decompression) x 7,546 ops/sec @ 132μs/op + getPublicKey(utils.randomPrivateKey()) x 5,540 ops/sec @ 180μs/op + sign x 3,301 ops/sec @ 302μs/op + verify x 517 ops/sec @ 1ms/op + getSharedSecret x 433 ops/sec @ 2ms/op + recoverPublicKey x 526 ops/sec @ 1ms/op + Point.fromHex (decompression) x 8,415 ops/sec @ 118μs/op Compare to other libraries on M1 (`openssl` uses native bindings, not JS): From 3b431d1038a1e4cbf76dcd61436be96643a0c4f2 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 02:03:13 +0000 Subject: [PATCH 056/145] Fix package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ba80829..6d00e58 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,8 @@ ], "exports": { ".": { - "types": "./lib/index.d.ts", - "default": "./lib/index.js" + "types": "./index.d.ts", + "default": "./index.js" } }, "funding": [ From 3b8a25f03ff3850b912656e34139b2cae022b2f5 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 02:05:47 +0000 Subject: [PATCH 057/145] Move min build dir --- build/package-lock.json | 135 ----------------------------- package.json | 2 +- {build => test/build}/package.json | 2 +- 3 files changed, 2 insertions(+), 137 deletions(-) delete mode 100644 build/package-lock.json rename {build => test/build}/package.json (81%) diff --git a/build/package-lock.json b/build/package-lock.json deleted file mode 100644 index b3f326c..0000000 --- a/build/package-lock.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "name": "build", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "build", - "version": "1.0.0", - "license": "MIT", - "devDependencies": { - "terser": "5.16.6" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - } - } -} diff --git a/package.json b/package.json index 6d00e58..1c7f59b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "test": "node test/secp256k1.test.mjs", "coverage": "jest --coverage", "bench": "node test/benchmark.js", - "min": "cd build; npm install; npm run terser", + "min": "cd test/build; npm install; npm run terser", "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts`LOC\"" }, "author": "Paul Miller (https://paulmillr.com)", diff --git a/build/package.json b/test/build/package.json similarity index 81% rename from build/package.json rename to test/build/package.json index bade171..408095d 100644 --- a/build/package.json +++ b/test/build/package.json @@ -5,7 +5,7 @@ "description": "Builds minified file", "main": "noble-secp256k1.js", "scripts": { - "terser": "terser --ecma 2020 -m -c < ../index.js" + "terser": "terser --ecma 2020 -m -c < ../../index.js" }, "keywords": [], "author": "", From 31313b5c67fbcb43df026da325ab86c492804dc5 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 02:06:42 +0000 Subject: [PATCH 058/145] Add min lockfile --- test/build/package-lock.json | 135 +++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 test/build/package-lock.json diff --git a/test/build/package-lock.json b/test/build/package-lock.json new file mode 100644 index 0000000..b3f326c --- /dev/null +++ b/test/build/package-lock.json @@ -0,0 +1,135 @@ +{ + "name": "build", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "build", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "terser": "5.16.6" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", + "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + } + } +} From 7dc72782a846032512f09dc57842d7f8a6c03752 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 02:15:37 +0000 Subject: [PATCH 059/145] It's 4KB! --- README.md | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8ffd2ed..e435829 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # noble-secp256k1 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) -[Fastest](#speed) 9KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), +[Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. diff --git a/package.json b/package.json index 1c7f59b..c205129 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", "version": "2.0.0-pre", - "description": "Fastest 9KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures compliant with RFC6979", + "description": "Fastest 4KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures compliant with RFC6979", "files": [ "index.js", "index.d.ts", @@ -18,7 +18,7 @@ "coverage": "jest --coverage", "bench": "node test/benchmark.js", "min": "cd test/build; npm install; npm run terser", - "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts`LOC\"" + "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts` LOC, `npm run --silent min | gzip -c8 | wc -c`B gzipped\"" }, "author": "Paul Miller (https://paulmillr.com)", "homepage": "https://paulmillr.com/noble/", From 5a44c9804b7d137ab15e4cf4508d2f9e77ddd89f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 02:24:21 +0000 Subject: [PATCH 060/145] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e435829..31eb0e0 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The library does not use dependencies and is as minimal as possible. replacement for noble-secp256k1 with more features such as Schnorr signatures, DER encoding and support for different hash functions. -Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions; +Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, [the online demo](https://paulmillr.com/ecc) and blog post [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). From 884f8015e54d048cc0fe89810c4bb111d9250959 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 16 Mar 2023 17:48:37 +0000 Subject: [PATCH 061/145] Upgrade to Typescript 5 --- README.md | 9 ++++----- index.d.ts | 10 +++++----- package-lock.json | 10 +++++----- package.json | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 31eb0e0..7c4d7bd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, -ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979. +ECDH key agreement protocol and deterministic **ECDSA** signatures from RFC6979. The library does not use dependencies and is as minimal as possible. [noble-curves](https://github.com/paulmillr/noble-curves) is advanced drop-in @@ -29,15 +29,14 @@ Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, ## Usage -Use NPM in browser and node.js: +Browser, deno, node.js and unpkg are supported: > npm install @noble/secp256k1 -For [Deno](https://deno.land), the module is available at `x/secp256k1`; -or you can use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers). - ```js import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js +// import * as secp from "https://deno.land/x/secp256k1/mod.ts"; // Deno +// import * as secp from "https://unpkg.com/@noble/secp256k1"; // Unpkg (async () => { // keys, messages & other inputs can be Uint8Arrays or hex strings // Uint8Array.from([0xde, 0xad, 0xbe, 0xef]) === 'deadbeef' diff --git a/index.d.ts b/index.d.ts index 963ad9c..532403a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -6,9 +6,9 @@ export declare const CURVE: { Gx: bigint; Gy: bigint; }; -declare type Bytes = Uint8Array; -declare type Hex = Bytes | string; -declare type PrivKey = Hex | bigint; +type Bytes = Uint8Array; +type Hex = Bytes | string; +type PrivKey = Hex | bigint; interface AffinePoint { x: bigint; y: bigint; @@ -52,7 +52,7 @@ export declare class Signature { toCompactRawBytes(): Uint8Array; toCompactHex(): string; } -declare type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); +type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); export declare const signAsync: (msgh: Hex, priv: Hex, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; @@ -61,7 +61,7 @@ export declare const sign: (msgh: Hex, priv: Hex, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; }) => Signature; -declare type SigLike = { +type SigLike = { r: bigint; s: bigint; }; diff --git a/package-lock.json b/package-lock.json index 81199e9..4497db8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", - "typescript": "4.7.3" + "typescript": "5.0.2" } }, "node_modules/@noble/hashes": { @@ -79,16 +79,16 @@ ] }, "node_modules/typescript": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", - "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } } } diff --git a/package.json b/package.json index c205129..32d41a7 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", - "typescript": "4.7.3" + "typescript": "5.0.2" }, "keywords": [ "secp256k1", From d28d8ee8684101cd58db4f101f41ce52dadcdaac Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 18 Mar 2023 21:28:01 +0000 Subject: [PATCH 062/145] Refactor more. 8936, 432 loc, 3978b gzipped --- index.d.ts | 45 ++++++------ index.js | 197 +++++++++++++++++++++++-------------------------- index.ts | 210 +++++++++++++++++++++++++---------------------------- 3 files changed, 214 insertions(+), 238 deletions(-) diff --git a/index.d.ts b/index.d.ts index 532403a..8bf34b4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,5 @@ export declare const CURVE: { - P: bigint; + p: bigint; n: bigint; a: bigint; b: bigint; @@ -20,55 +20,56 @@ declare class Point { constructor(px: bigint, py: bigint, pz: bigint); static readonly BASE: Point; static readonly ZERO: Point; + static fromPrivateKey(k: PrivKey): Point; + static fromHex(hex: Hex): Point; get x(): bigint; get y(): bigint; equals(other: Point): boolean; - neg(): Point; - dbl(): Point; + negate(): Point; + double(): Point; add(other: Point): Point; - mul(n: bigint, safe?: boolean): Point; + multiply(n: bigint, safe?: boolean): Point; mulAddQUns(R: Point, u1: bigint, u2: bigint): Point; - aff(): AffinePoint; - ok(): Point; - multiply(n: bigint): Point; - negate(): Point; toAffine(): AffinePoint; assertValidity(): Point; - static fromHex(hex: Hex): Point; + mul(n: bigint, safe?: boolean): Point; + aff(): AffinePoint; + ok(): Point; toHex(isCompressed?: boolean): string; toRawBytes(isCompressed?: boolean): Uint8Array; - static fromPrivateKey(n: PrivKey): Point; } -export declare const getPublicKey: (privKey: PrivKey, isCompressed?: boolean) => Uint8Array; +export declare function getPublicKey(privKey: PrivKey, isCompressed?: boolean): Uint8Array; export declare class Signature { readonly r: bigint; readonly s: bigint; readonly recovery?: number | undefined; constructor(r: bigint, s: bigint, recovery?: number | undefined); - ok(): Signature; static fromCompact(hex: Hex): Signature; + assertValidity(): this; + addRecoveryBit(rec: number): Signature; hasHighS(): boolean; recoverPublicKey(msgh: Hex): Point; toCompactRawBytes(): Uint8Array; toCompactHex(): string; } type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); -export declare const signAsync: (msgh: Hex, priv: Hex, opts?: { +export declare function signAsync(msgh: Hex, priv: Hex, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; -}) => Promise; -export declare const sign: (msgh: Hex, priv: Hex, opts?: { +}): Promise; +export declare function sign(msgh: Hex, priv: Hex, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; -}) => Signature; +}): Signature; type SigLike = { r: bigint; s: bigint; }; -export declare const verify: (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts?: { - lowS: boolean; -}) => boolean; -export declare const getSharedSecret: (privA: Hex, pubB: Hex, isCompressed?: boolean) => Uint8Array; +export declare function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts?: { + lowS?: boolean | undefined; +}): boolean; +export declare function getSharedSecret(privA: Hex, pubB: Hex, isCompressed?: boolean): Bytes; +declare function hashToPrivateKey(hash: Hex): Bytes; export declare const etc: { hexToBytes: (hex: string) => Bytes; bytesToHex: (b: Bytes) => string; @@ -79,14 +80,14 @@ export declare const etc: { invert: (num: bigint, md?: bigint) => bigint; hmacSha256Async: (key: Bytes, ...msgs: Bytes[]) => Promise; hmacSha256Sync: HmacFnSync; - hashToPrivateKey: (hash: Hex) => Bytes; + hashToPrivateKey: typeof hashToPrivateKey; randomBytes: (len: number) => Bytes; }; export declare const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; randomPrivateKey: () => Bytes; isValidPrivateKey: (key: Hex) => boolean; - precompute(p: Point, windowSize?: number): Point; + precompute(w?: number, p?: Point): Point; }; export declare const ProjectivePoint: typeof Point; export {}; diff --git a/index.js b/index.js index cce3a0b..853a975 100644 --- a/index.js +++ b/index.js @@ -6,9 +6,9 @@ const _a = 0n; // a equation's param const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables +export const CURVE = { p: P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length -const crv = (x) => mod(mod(x * mod(x * x)) + _a * x + _b); // x³ + ax + b weierstrass formula +const crv = (x) => mod(mod(x * mod(x * x)) + _b); // x³ + ax + b weierstrass formula; w/o a const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n) => typeof n === 'bigint'; // is big integer const str = (s) => typeof s === 'string'; // is string @@ -33,8 +33,28 @@ class Point { this.py = py; this.pz = pz; } // z is optional - get x() { return this.aff().x; } // .x, .y will call expensive toAffine. - get y() { return this.aff().y; } // Should be used with care. + static fromPrivateKey(k) { return G.mul(toPriv(k)); } // Create point from a private key. + static fromHex(hex) { + hex = toU8(hex); // convert hex string to Uint8Array + let p = undefined; + const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data + const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate + if (len === 33 && [0x02, 0x03].includes(head)) { // compressed points: 33b, start + if (!fe(x)) + err('Point hex invalid: x not FE'); // with byte 0x02 or 0x03. Check if 0 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder + for (let d = this; n > 0n; d = d.double(), n >>= 1n) { // double-and-add ladder if (n & 1n) p = p.add(d); // if bit is present, add to point else if (safe) @@ -108,7 +128,7 @@ class Point { mulAddQUns(R, u1, u2) { return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related } // to private keys. Doesn't use Shamir trick - aff() { + toAffine() { const { px: x, py: y, pz: z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) if (this.equals(I)) return { x: 0n, y: 0n }; // fast-path for zero point @@ -119,55 +139,32 @@ class Point { err('invalid inverse'); // (z * z^-1) must be 1, otherwise bad math return { x: mod(x * iz), y: mod(y * iz) }; // x = x*z^-1; y = y*z^-1 } - ok() { + assertValidity() { const { x, y } = this.aff(); // convert to 2d xy affine point. if (!fe(x) || !fe(y)) err('Point invalid: x or y'); // x and y must be in range 0 < n < P return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal this : err('Point invalid: not on curve'); } - multiply(n) { return this.mul(n); } // Aliases for compatibilty - negate() { return this.neg(); } - toAffine() { return this.aff(); } - assertValidity() { return this.ok(); } - static fromHex(hex) { - hex = toU8(hex); // converts hex string to Uint8Array - let p = undefined; - const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data - const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate - if (len === 33 && [0x02, 0x03].includes(head)) { // compressed points: 33b, start - if (!fe(x)) - err('Point hex invalid: x not FE'); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num, md = P) => { if (num === 0n || md <= 0n) - err(`no inverse n=${num} mod=${md}`); // negative exponent not supported + err(`no inverse n=${num} mod=${md}`); // no negative exponent for now let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { // uses euclidean gcd algorithm const q = b / a, r = b % a; // not constant-time @@ -176,26 +173,17 @@ const inv = (num, md = P) => { } return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point }; -const pow = (num, e, md = P) => { - if (md <= 0n || e < 0n) - err('pow invalid'); // exponentiation by squaring - if (md === 1n) - return 0n; // the ladder can leak exponent bits - let res = 1n; // and is vulnerable to timing attacks - for (; e > 0n; e >>= 1n) { +const sqrt = (n) => { + let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". + for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. if (e & 1n) - res = (res * num) % md; - num = (num * num) % md; + r = (r * num) % P; + num = (num * num) % P; } - return res; + return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid }; -const sqrt = (n) => { - const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square - return mod(r * r) === n ? r : err('sqrt invalid'); // Roots from 1;24,51,10 to Dan Shanks" -}; -const padh = (num, pad) => num.toString(16).padStart(pad, '0'); +const padh = (n, pad) => n.toString(16).padStart(pad, '0'); const b2h = (b) => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex -const h2n = (hex) => (str(hex) ? BigInt(`0x${hex || '0'}`) : err()); // hex to number const h2b = (hex) => { const l = hex.length; // error if not string, if (!str(hex) || l % 2) @@ -211,7 +199,7 @@ const h2b = (hex) => { } return arr; }; -const b2n = (b) => h2n(b2h(b)); // bytes to number +const b2n = (b) => BigInt(`0x${b2h(b) || '0'}`); // bytes to number const slcNum = (b, from, to) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num) => { return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); @@ -224,21 +212,22 @@ const concatB = (...arrs) => { return r; }; const moreThanHalfN = (n) => n > (N >> 1n); // if a number is bigger than CURVE.n/2 -export const getPublicKey = (privKey, isCompressed = true) => { - return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private -}; +export function getPublicKey(privKey, isCompressed = true) { + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output +} export class Signature { constructor(r, s, recovery) { this.r = r; this.s = s; this.recovery = recovery; - this.ok(); - } - ok() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n + this.assertValidity(); // recovery bit is optional when + } // constructed outside. static fromCompact(hex) { hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } + assertValidity() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n + addRecoveryBit(rec) { return new Signature(this.r, this.s, rec); } hasHighS() { return moreThanHalfN(this.s); } recoverPublicKey(msgh) { const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 @@ -267,23 +256,23 @@ const bits2int_modN = (bytes) => { return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; const i2o = (num) => n2b(num); // int to octets -const cr = () => // We support: 1) browsers 2) node.js 19+ +const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with `crypto` typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; let _hmacSync; // Can be redefined by use in utils; built-ins don't provide it -const stdo = { lowS: true }; // opts for sign() -const vstdo = { lowS: true }; // standard opts for verify() -const prepSig = (msgh, priv, opts = stdo) => { +const optS = { lowS: true }; // opts for sign() +const optV = { lowS: true }; // standard opts for verify() +function prepSig(msgh, priv, opts = optS) { if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); let { lowS } = opts; // generates low-s sigs by default if (lowS == null) - lowS = true; // RFC6979 3.2: we skip step A, because - const h1i = bits2int_modN(toU8(msgh)); - const h1o = i2o(h1i); + lowS = true; // RFC6979 3.2: we skip step A + const h1i = bits2int_modN(toU8(msgh)); // msg bigint + const h1o = i2o(h1i); // msg octets const d = toPriv(priv); // validate private key, convert to bigint const seed = [i2o(d), h1o]; // Step D of RFC6979 3.2 let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) - if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + if (ent) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') if (ent === true) ent = etc.randomBytes(fLen); // if true, use CSPRNG to generate data const e = toU8(ent); // convert Hex|Bytes to Bytes @@ -293,7 +282,7 @@ const prepSig = (msgh, priv, opts = stdo) => { } const m = h1i; // convert msg to bigint const k2sig = (kBytes) => { - const k = bits2int(kBytes); // Transforms k into Signature + const k = bits2int(kBytes); // RFC6979 method. if (!ge(k)) return; // Check 0 < k < CURVE.n const ik = inv(k, N); // k^-1 mod n, NOT mod P @@ -313,7 +302,7 @@ const prepSig = (msgh, priv, opts = stdo) => { return new Signature(r, normS, rec); // use normS, not s }; return { seed: concatB(...seed), k2sig }; -}; +} function hmacDrbg(asynchronous) { let v = u8n(fLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. let k = u8n(fLen); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same @@ -341,7 +330,7 @@ function hmacDrbg(asynchronous) { await reseed(seed); // Steps D-G let res = undefined; // Step H: grind until k is in [1..n-1] while (!(res = pred(await gen()))) - await reseed(); + await reseed(); // test predicate until it returns ok reset(); return res; }; @@ -350,7 +339,7 @@ function hmacDrbg(asynchronous) { const h = (...b) => { const f = _hmacSync; if (!f) - err('utils.hmacSha256Sync not set'); + err('etc.hmacSha256Sync not set'); return f(k, v, ...b); // hmac(k)(v, ...values) }; const reseed = (seed = u8n()) => { @@ -372,25 +361,22 @@ function hmacDrbg(asynchronous) { reseed(seed); // Steps D-G let res = undefined; // Step H: grind until k is in [1..n-1] while (!(res = pred(gen()))) - reseed(); + reseed(); // test predicate until it returns ok reset(); return res; }; } } -; -// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2. hmacDrbg() -export const signAsync = async (msgh, priv, opts = stdo) => { +// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k +export async function signAsync(msgh, priv, opts = optS) { const { seed, k2sig } = prepSig(msgh, priv, opts); - const genUntil = hmacDrbg(true); - return genUntil(seed, k2sig); -}; -export const sign = (msgh, priv, opts = stdo) => { + return hmacDrbg(true)(seed, k2sig); +} +export function sign(msgh, priv, opts = optS) { const { seed, k2sig } = prepSig(msgh, priv, opts); - const genUntil = hmacDrbg(false); - return genUntil(seed, k2sig); -}; -export const verify = (sig, msgh, pub, opts = vstdo) => { + return hmacDrbg(false)(seed, k2sig); +} +export function verify(sig, msgh, pub, opts = optV) { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true @@ -401,7 +387,7 @@ export const verify = (sig, msgh, pub, opts = vstdo) => { if (!rs && (toU8(sig).length !== 2 * fLen)) // throw error when DER is suspected now. err('signature must be 64 bytes'); try { - sig_ = rs ? new Signature(sig.r, sig.s).ok() : Signature.fromCompact(sig); + sig_ = rs ? new Signature(sig.r, sig.s).assertValidity() : Signature.fromCompact(sig); h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } @@ -425,32 +411,31 @@ export const verify = (sig, msgh, pub, opts = vstdo) => { } if (!R) return false; // stop if R is identity / zero point - const v = mod(R.x, N); + const v = mod(R.x, N); // <== The weird ECDSA part. R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r -}; -export const getSharedSecret = (privA, pubB, isCompressed = true) => { +} +export function getSharedSecret(privA, pubB, isCompressed = true) { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH -}; -const hashToPrivateKey = (hash) => { +} +function hashToPrivateKey(hash) { hash = toU8(hash); // produces private keys with modulo bias const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); -}; +} export const etc = { hexToBytes: h2b, bytesToHex: b2h, concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, hmacSha256Async: async (key, ...msgs) => { - const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! - const crypto = cr(); + const crypto = cr(); // HMAC-SHA256 async. No sync built-in! if (!crypto) - return err('utils.hmacSha256Async not set'); + return err('etc.hmacSha256Async not set'); // Uses webcrypto: native cryptography. const s = crypto.subtle; const k = await s.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); - return u8n(await s.sign('HMAC', k, m)); + return u8n(await s.sign('HMAC', k, concatB(...msgs))); }, hmacSha256Sync: _hmacSync, hashToPrivateKey, @@ -472,7 +457,7 @@ export const utils = { catch (e) { return false; } }, - precompute(p, windowSize = 8) { return p; } // no-op + precompute(w = 8, p = G) { p.multiply(3n); return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) @@ -490,14 +475,14 @@ const precompute = () => { b = b.add(p); points.push(b); } - p = b.dbl(); // Precomputes don't speed-up getSharedKey, + p = b.double(); // Precomputes don't speed-up getSharedKey, } // which multiplies user point by scalar, return points; // when precomputes are using base point }; const wNAF = (n) => { // Compared to other point mult methods, const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction - const neg = (cnd, p) => { let n = p.neg(); return cnd ? n : p; }; // negate + const neg = (cnd, p) => { let n = p.negate(); return cnd ? n : p; }; // negate let p = I, f = G; // f must be G, or could become I in the end const windows = 1 + 256 / W; // W=8 17 windows const wsize = 2 ** (W - 1); // W=8 128 window size diff --git a/index.ts b/index.ts index 295c437..bd02f26 100644 --- a/index.ts +++ b/index.ts @@ -6,10 +6,10 @@ const _a = 0n; // a equation's param const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = { P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables +export const CURVE = { p: P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; -const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _a * x + _b); // x³ + ax + b weierstrass formula +const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _b); // x³ + ax + b weierstrass formula; w/o a const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: any): s is string => typeof s === 'string'; // is string @@ -20,8 +20,8 @@ const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of spe err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut -const toU8 = (a: any, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a -const toPriv = (p: PrivKey): bigint => { // normalize private key to bigint +const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a +const toPriv = (p: PrivKey): bigint => { // normalize private key to bigint if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; @@ -30,24 +30,41 @@ interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { // Point in 3d xyz projective coords constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} // z is optional - static readonly BASE = new Point(Gx, Gy, 1n); // generator / base point. - static readonly ZERO = new Point(0n, 1n, 0n); // identity / zero point - get x() { return this.aff().x; } // .x, .y will call expensive toAffine. - get y() { return this.aff().y; } // Should be used with care. - equals(other: Point): boolean { // equality check: compare points + static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point. + static readonly ZERO = new Point(0n, 1n, 0n); // Identity / zero point + static fromPrivateKey(k: PrivKey) { return G.mul(toPriv(k)); } // Create point from a private key. + static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point + hex = toU8(hex); // convert hex string to Uint8Array + let p: Point | undefined = undefined; + const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data + const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate + if (len === 33 && [0x02, 0x03].includes(head)) { // compressed points: 33b, start + if (!fe(x)) err('Point hex invalid: x not FE'); // with byte 0x02 or 0x03. Check if 0 0n; d = d.dbl(), n >>= 1n) { // double-and-add ladder + for (let d: Point = this; n > 0n; d = d.double(), n >>= 1n) { // double-and-add ladder if (n & 1n) p = p.add(d); // if bit is present, add to point else if (safe) f = f.add(d); // if not, add to fake for timing safety } return p; } - mulAddQUns(R: Point, u1: bigint, u2: bigint) { // Q = u1⋅G + u2⋅R: double scalar mult. + mulAddQUns(R: Point, u1: bigint, u2: bigint) { // Double scalar mult. Q = u1⋅G + u2⋅R. return this.mul(u1, false).add(R.mul(u2, false)).ok(); // Unsafe: do NOT use for stuff related } // to private keys. Doesn't use Shamir trick - aff(): AffinePoint { // Converts point to 2d xy affine point + toAffine(): AffinePoint { // Convert point to 2d xy affine point. const { px: x, py: y, pz: z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) if (this.equals(I)) return { x: 0n, y: 0n }; // fast-path for zero point if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is @@ -89,48 +106,28 @@ class Point { // Point in 3d xyz proje if (mod(z * iz) !== 1n) err('invalid inverse'); // (z * z^-1) must be 1, otherwise bad math return { x: mod(x * iz), y: mod(y * iz) }; // x = x*z^-1; y = y*z^-1 } - ok(): Point { // Checks if the point is valid and on-curve + assertValidity(): Point { // Checks if the point is valid and on-curve const { x, y } = this.aff(); // convert to 2d xy affine point. if (!fe(x) || !fe(y)) err('Point invalid: x or y'); // x and y must be in range 0 < n < P return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal this : err('Point invalid: not on curve'); } - multiply(n: bigint) { return this.mul(n); } // Aliases for compatibilty - negate() { return this.neg(); } - toAffine() { return this.aff(); } - assertValidity() { return this.ok(); } - static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point - hex = toU8(hex); // converts hex string to Uint8Array - let p: Point | undefined = undefined; - const head = hex[0], tail = hex.subarray(1); // first byte is prefix, rest is data - const x = slcNum(tail, 0, fLen), len = hex.length; // next 32 bytes are x coordinate - if (len === 33 && [0x02, 0x03].includes(head)) { // compressed points: 33b, start - if (!fe(x)) err('Point hex invalid: x not FE'); // with byte 0x02 or 0x03. Check if 0 { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const inv = (num: bigint, md = P): bigint => { // modular inversion - if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // negative exponent not supported + if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // no negative exponent for now let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { // uses euclidean gcd algorithm const q = b / a, r = b % a; // not constant-time @@ -139,23 +136,16 @@ const inv = (num: bigint, md = P): bigint => { // modular inversion } return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point }; -const pow = (num: bigint, e: bigint, md = P): bigint => { // modular exponentiation num^e - if (md <= 0n || e < 0n) err('pow invalid'); // exponentiation by squaring - if (md === 1n) return 0n; // the ladder can leak exponent bits - let res = 1n; // and is vulnerable to timing attacks - for (; e > 0n; e >>= 1n) { - if (e & 1n) res = (res * num) % md; - num = (num * num) % md; - } - return res; -}; const sqrt = (n: bigint) => { // √n = n^((p+1)/4) for fields p = 3 mod 4 - const r = pow(n, (P + 1n) / 4n, P); // So, a special, fast case. Paper: "Square - return mod(r * r) === n ? r : err('sqrt invalid'); // Roots from 1;24,51,10 to Dan Shanks" + let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". + for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. + if (e & 1n) r = (r * num) % P; + num = (num * num) % P; + } + return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid }; -const padh = (num: number | bigint, pad: number) => num.toString(16).padStart(pad, '0'); +const padh = (n: number | bigint, pad: number) => n.toString(16).padStart(pad, '0'); const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex -const h2n = (hex: string): bigint => (str(hex) ? BigInt(`0x${hex||'0'}`) : err()); // hex to number const h2b = (hex: string): Bytes => { // hex to bytes const l = hex.length; // error if not string, if (!str(hex) || l % 2) err('hex invalid'); // or has odd length like 3, 5. @@ -169,7 +159,7 @@ const h2b = (hex: string): Bytes => { // hex to bytes } return arr; }; -const b2n = (b: Bytes): bigint => h2n(b2h(b)); // bytes to number +const b2n = (b: Bytes): bigint => BigInt(`0x${b2h(b)||'0'}`); // bytes to number const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num: bigint): Bytes => { // number to bytes. must be 0 <= num < B256 return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); @@ -182,16 +172,19 @@ const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Arra return r; }; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 -export const getPublicKey = (privKey: PrivKey, isCompressed = true) => { // calculate public - return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // key from private -}; -export class Signature { // calculates signature - constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { this.ok(); } - ok(): Signature { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n +export function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv + return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output +} +export class Signature { // ECDSA Signature class + constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { + this.assertValidity(); // recovery bit is optional when + } // constructed outside. static fromCompact(hex: Hex) { // create signature from 64b compact repr hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } + assertValidity() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n + addRecoveryBit(rec: number) { return new Signature(this.r, this.s, rec); } hasHighS() { return moreThanHalfN(this.s); } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 @@ -219,32 +212,32 @@ const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be us }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets declare const globalThis: Record | undefined; // Typescript symbol present in browsers -const cr = () => // We support: 1) browsers 2) node.js 19+ +const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with `crypto` typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it -const stdo: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() -const vstdo = { lowS: true }; // standard opts for verify() -type BC = { seed: Bytes, k2sig : (kb: Bytes) => Signature | undefined }; -const prepSig = (msgh: Hex, priv: Hex, opts = stdo): BC => { // prepare for RFC6979 sig generation +const optS: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() +const optV: { lowS?: boolean } = { lowS: true }; // standard opts for verify() +type BC = { seed: Bytes, k2sig : (kb: Bytes) => Signature | undefined }; // Bytes+predicate checker +function prepSig(msgh: Hex, priv: Hex, opts = optS): BC { // prepare for RFC6979 sig generation if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); let { lowS } = opts; // generates low-s sigs by default - if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because - const h1i = bits2int_modN(toU8(msgh)); - const h1o = i2o(h1i); + if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A + const h1i = bits2int_modN(toU8(msgh)); // msg bigint + const h1o = i2o(h1i); // msg octets const d = toPriv(priv); // validate private key, convert to bigint const seed = [i2o(d), h1o]; // Step D of RFC6979 3.2 let ent = opts.extraEntropy; // RFC6979 3.6: additional k' (optional) - if (ent != null) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - if (ent === true) ent = etc.randomBytes(fLen); // if true, use CSPRNG to generate data + if (ent) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + if (ent === true) ent = etc.randomBytes(fLen); // if true, use CSPRNG to generate data const e = toU8(ent); // convert Hex|Bytes to Bytes if (e.length !== fLen) err(); // Expected 32 bytes of extra data seed.push(e); } const m = h1i; // convert msg to bigint - const k2sig = (kBytes: Bytes): Signature | undefined => { - const k = bits2int(kBytes); // Transforms k into Signature + const k2sig = (kBytes: Bytes): Signature | undefined => { // Transform k into Signature. + const k = bits2int(kBytes); // RFC6979 method. if (!ge(k)) return; // Check 0 < k < CURVE.n const ik = inv(k, N); // k^-1 mod n, NOT mod P const q = G.mul(k).aff(); // q = Gk @@ -261,7 +254,7 @@ const prepSig = (msgh: Hex, priv: Hex, opts = stdo): BC => { // prepare for RFC6 return new Signature(r, normS, rec); // use normS, not s }; return { seed: concatB(...seed), k2sig } -}; +} type Pred = (v: Uint8Array) => T | undefined; function hmacDrbg(asynchronous: true): (seed: Bytes, predicate: Pred) => Promise; function hmacDrbg(asynchronous: false): (seed: Bytes, predicate: Pred) => T; @@ -289,14 +282,14 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async reset(); // the returned fn, don't, it's: 1. slower (JIT). 2. unsafe (async race conditions) await reseed(seed); // Steps D-G let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] - while (!(res = pred(await gen()))) await reseed(); + while (!(res = pred(await gen()))) await reseed(); // test predicate until it returns ok reset(); return res!; }; } else { const h = (...b: Bytes[]) => { // Same, but synchronous const f = _hmacSync; - if (!f) err('utils.hmacSha256Sync not set'); + if (!f) err('etc.hmacSha256Sync not set'); return f!(k, v, ...b); // hmac(k)(v, ...values) }; const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G @@ -315,25 +308,23 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async reset(); reseed(seed); // Steps D-G let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] - while (!(res = pred(gen()))) reseed(); + while (!(res = pred(gen()))) reseed(); // test predicate until it returns ok reset(); return res!; }; } -}; -// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2. hmacDrbg() -export const signAsync = async (msgh: Hex, priv: Hex, opts = stdo): Promise => { +} +// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k +export async function signAsync(msgh: Hex, priv: Hex, opts = optS): Promise { const { seed, k2sig } = prepSig(msgh, priv, opts); - const genUntil = hmacDrbg(true); - return genUntil(seed, k2sig); -}; -export const sign = (msgh: Hex, priv: Hex, opts = stdo): Signature => { + return hmacDrbg(true)(seed, k2sig); +} +export function sign(msgh: Hex, priv: Hex, opts = optS): Signature { const { seed, k2sig } = prepSig(msgh, priv, opts); - const genUntil = hmacDrbg(false); - return genUntil(seed, k2sig); -}; + return hmacDrbg(false)(seed, k2sig); +} type SigLike = { r: bigint, s: bigint }; -export const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): boolean => { +export function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true if ('strict' in opts) err('verify() legacy options not supported'); // legacy param @@ -342,7 +333,7 @@ export const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): b if (!rs && (toU8(sig).length !== 2 * fLen)) // throw error when DER is suspected now. err('signature must be 64 bytes'); try { - sig_ = rs ? new Signature(sig.r, sig.s).ok() : Signature.fromCompact(sig); + sig_ = rs ? new Signature(sig.r, sig.s).assertValidity() : Signature.fromCompact(sig); h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { return false; } // Check sig for validity in both cases @@ -357,30 +348,29 @@ export const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = vstdo): b R = G.mulAddQUns(P, u1, u2).aff(); // R = u1⋅G + u2⋅P } catch (error) { return false; } if (!R) return false; // stop if R is identity / zero point - const v = mod(R.x, N); + const v = mod(R.x, N); // <== The weird ECDSA part. R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r } -export const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true) => { +export function getSharedSecret(privA: Hex, pubB: Hex, isCompressed = true): Bytes { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH -}; -const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation +} +function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compliant key generation hash = toU8(hash); // produces private keys with modulo bias const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); -}; +} export const etc = { // Not placed in `utils` because utils hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, // math utilities hmacSha256Async: async (key: Bytes, ...msgs: Bytes[]): Promise => { - const m = concatB(...msgs); // HMAC-SHA256 async. No sync built-in! - const crypto = cr(); - if (!crypto) return err('utils.hmacSha256Async not set'); + const crypto = cr(); // HMAC-SHA256 async. No sync built-in! + if (!crypto) return err('etc.hmacSha256Async not set'); // Uses webcrypto: native cryptography. const s = crypto.subtle; const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); - return u8n(await s.sign('HMAC', k, m)); + return u8n(await s.sign('HMAC', k, concatB(...msgs))); }, hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below hashToPrivateKey, @@ -396,7 +386,7 @@ export const utils = { // utilities normPrivateKeyToScalar: toPriv, randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, - precompute(p: Point, windowSize = 8) { return p; } // no-op + precompute(w=8, p: Point = G) { p.multiply(3n); return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { // Allow setting it once, ignore then configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, @@ -410,14 +400,14 @@ const precompute = () => { // They give 12x faster b = p; // any time Gx multiplication is done. points.push(b); // They consume 16-32 MiB of RAM. for (let i = 1; i < 2 ** (W - 1); i++) { b = b.add(p); points.push(b); } - p = b.dbl(); // Precomputes don't speed-up getSharedKey, + p = b.double(); // Precomputes don't speed-up getSharedKey, } // which multiplies user point by scalar, return points; // when precomputes are using base point } const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method. // Compared to other point mult methods, const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction - const neg = (cnd: boolean, p: Point) => { let n = p.neg(); return cnd ? n : p; } // negate + const neg = (cnd: boolean, p: Point) => { let n = p.negate(); return cnd ? n : p; } // negate let p = I, f = G; // f must be G, or could become I in the end const windows = 1 + 256 / W; // W=8 17 windows const wsize = 2 ** (W - 1); // W=8 128 window size From ec7b5731808538c7cc32cba3234822a003958345 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 19 Mar 2023 04:58:28 +0000 Subject: [PATCH 063/145] Refactor more. 8900, 431 loc, 3968b gzipped --- README.md | 59 +++++++++++++++++++++++++------------------------------ index.js | 17 ++++++++-------- index.ts | 53 ++++++++++++++++++++++++------------------------- 3 files changed, 61 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 7c4d7bd..52b447b 100644 --- a/README.md +++ b/README.md @@ -96,21 +96,12 @@ There are 3 main methods: `getPublicKey(privateKey)`, `sign(messageHash, privateKey)` and `verify(signature, messageHash, publicKey)`. -Only **async methods are available by default** to keep library dependency-free. -To enable sync methods, see below. - ```typescript type Hex = Uint8Array | string; -// Generates 33-byte / 65-byte public key from 32-byte private key. -function getPublicKey( - privateKey: Hex, - isCompressed?: boolean // optional arg. (default) true=33b key, false=65b. -): Uint8Array; -function getPublicKeyAsync( - privateKey: Hex, - isCompressed?: boolean -): Promise; +// Generates public key from 32-byte private key. +// isCompressed=true by default, meaning 33-byte output. Set to false for 65b. +function getPublicKey(privateKey: Hex, isCompressed?: boolean): Uint8Array; // Use: // - `ProjectivePoint.fromPrivateKey(privateKey)` for Point instance // - `ProjectivePoint.fromHex(publicKey)` to convert hex / bytes into Point. @@ -120,9 +111,13 @@ function getPublicKeyAsync( function sign( messageHash: Hex, // message hash (not message) which would be signed privateKey: Hex, // private key which will sign the hash - opts = {} // optional params `{ lowS: boolean, extraEntropy: boolean | Hex }` + opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional params ): Signature; -function signAsync(messageHash: Hex, privateKey: Hex, opts = {}): Promise; +function signAsync( + messageHash: Hex, + privateKey: Hex, + opts?: { lowS: boolean; extraEntropy: boolean | Hex } +): Promise; // Verifies ECDSA signature. // lowS option Ensures a signature.s is in the lower-half of CURVE.n. @@ -174,24 +169,24 @@ export declare const utils: { precompute(p: Point, windowSize?: number): Point; }; class ProjectivePoint { - readonly px: bigint; - readonly py: bigint; - readonly pz: bigint; - constructor(px: bigint, py: bigint, pz: bigint); - static readonly BASE: Point; - static readonly ZERO: Point; - get x(): bigint; - get y(): bigint; - equals(other: Point): boolean; - add(other: Point): Point; - multiply(n: bigint): Point; - negate(): Point; - toAffine(): AffinePoint; - assertValidity(): Point; - static fromHex(hex: Hex): Point; - toHex(isCompressed?: boolean): string; - toRawBytes(isCompressed?: boolean): Uint8Array; - static fromPrivateKey(n: PrivKey): Point; + readonly px: bigint; + readonly py: bigint; + readonly pz: bigint; + constructor(px: bigint, py: bigint, pz: bigint); + static readonly BASE: Point; + static readonly ZERO: Point; + static fromHex(hex: Hex): Point; + static fromPrivateKey(n: PrivKey): Point; + get x(): bigint; + get y(): bigint; + equals(other: Point): boolean; + add(other: Point): Point; + multiply(n: bigint): Point; + negate(): Point; + toAffine(): AffinePoint; + assertValidity(): Point; + toHex(isCompressed?: boolean): string; + toRawBytes(isCompressed?: boolean): Uint8Array; } class Signature { readonly r: bigint; diff --git a/index.js b/index.js index 853a975..683e05d 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y export const CURVE = { p: P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables const fLen = 32; // field / group byte length -const crv = (x) => mod(mod(x * mod(x * x)) + _b); // x³ + ax + b weierstrass formula; w/o a +const crv = (x) => mod(mod(x * x) * x + _b); // x³ + ax + b weierstrass formula; no a const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n) => typeof n === 'bigint'; // is big integer const str = (s) => typeof s === 'string'; // is string @@ -18,7 +18,6 @@ const au8 = (a, l) => // is Uint8Array (of specific length) !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data) => new Uint8Array(data); // creates Uint8Array -const u8fr = (arr) => Uint8Array.from(arr); // another shortcut const toU8 = (a, len) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a const toPriv = (p) => { if (!big(p)) @@ -158,7 +157,7 @@ class Point { return h2b(this.toHex(isCompressed)); // re-use toHex(), convert hex to bytes } } -Point.BASE = new Point(Gx, Gy, 1n); // Generator / base point. +Point.BASE = new Point(Gx, Gy, 1n); // Generator / base point Point.ZERO = new Point(0n, 1n, 0n); // Identity / zero point const { BASE: G, ZERO: I } = Point; // Generator, identity points const mod = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division @@ -177,8 +176,8 @@ const sqrt = (n) => { let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. if (e & 1n) - r = (r * num) % P; - num = (num * num) % P; + r = (r * num) % P; // Uses exponentiation by squaring. + num = (num * num) % P; // Not constant-time. } return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid }; @@ -312,11 +311,11 @@ function hmacDrbg(asynchronous) { if (asynchronous) { // asynchronous=true const h = (...b) => etc.hmacSha256Async(k, v, ...b); // hmac(k)(v, ...values) const reseed = async (seed = u8n()) => { - k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) + k = await h(u8n([0x00]), seed); // k = hmac(K || V || 0x00 || seed) v = await h(); // v = hmac(K || V) if (seed.length === 0) return; - k = await h(u8fr([0x01]), seed); // k = hmac(K || V || 0x01 || seed) + k = await h(u8n([0x01]), seed); // k = hmac(K || V || 0x01 || seed) v = await h(); // v = hmac(K || V) }; const gen = async () => { @@ -343,11 +342,11 @@ function hmacDrbg(asynchronous) { return f(k, v, ...b); // hmac(k)(v, ...values) }; const reseed = (seed = u8n()) => { - k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) + k = h(u8n([0x00]), seed); // k = hmac(k || v || 0x00 || seed) v = h(); // v = hmac(k || v) if (seed.length === 0) return; - k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) + k = h(u8n([0x01]), seed); // k = hmac(k || v || 0x01 || seed) v = h(); // v = hmac(k || v) }; const gen = () => { diff --git a/index.ts b/index.ts index bd02f26..e30cad4 100644 --- a/index.ts +++ b/index.ts @@ -6,21 +6,20 @@ const _a = 0n; // a equation's param const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = { p: P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables +export const CURVE = {p: P, n: N, a: _a, b: _b, Gx, Gy};// exported variables const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; -const crv = (x: bigint) => mod(mod(x * mod(x*x)) + _b); // x³ + ax + b weierstrass formula; w/o a +const crv = (x: bigint) => mod(mod(x * x) * x + _b); // x³ + ax + b weierstrass formula; no a const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace -const big = (n: any): n is bigint => typeof n === 'bigint'; // is big integer -const str = (s: any): s is string => typeof s === 'string'; // is string +const big = (n: unknown): n is bigint => typeof n === 'bigint'; // is big integer +const str = (s: unknown): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array -const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut -const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a +const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a const toPriv = (p: PrivKey): bigint => { // normalize private key to bigint if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err('private key out of range'); // check if bigint is in range @@ -30,7 +29,7 @@ interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point class Point { // Point in 3d xyz projective coords constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} // z is optional - static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point. + static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point static readonly ZERO = new Point(0n, 1n, 0n); // Identity / zero point static fromPrivateKey(k: PrivKey) { return G.mul(toPriv(k)); } // Create point from a private key. static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point @@ -139,8 +138,8 @@ const inv = (num: bigint, md = P): bigint => { // modular inversion const sqrt = (n: bigint) => { // √n = n^((p+1)/4) for fields p = 3 mod 4 let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. - if (e & 1n) r = (r * num) % P; - num = (num * num) % P; + if (e & 1n) r = (r * num) % P; // Uses exponentiation by squaring. + num = (num * num) % P; // Not constant-time. } return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid }; @@ -264,44 +263,44 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async let i = 0; // Iterations counter, will throw when over 1000 const reset = () => { v.fill(1); k.fill(0); i = 0; }; const _e = 'drbg: tried 1000 values'; - if (asynchronous) { // asynchronous=true + if (asynchronous) { // asynchronous=true const h = (...b: Bytes[]) => etc.hmacSha256Async(k, v, ...b); // hmac(k)(v, ...values) - const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G - k = await h(u8fr([0x00]), seed); // k = hmac(K || V || 0x00 || seed) - v = await h(); // v = hmac(K || V) + const reseed = async (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G + k = await h(u8n([0x00]), seed); // k = hmac(K || V || 0x00 || seed) + v = await h(); // v = hmac(K || V) if (seed.length === 0) return; - k = await h(u8fr([0x01]), seed); // k = hmac(K || V || 0x01 || seed) - v = await h(); // v = hmac(K || V) + k = await h(u8n([0x01]), seed); // k = hmac(K || V || 0x01 || seed) + v = await h(); // v = hmac(K || V) }; - const gen = async () => { // HMAC-DRBG generate() function + const gen = async () => { // HMAC-DRBG generate() function if (i++ >= 1000) err(_e); - v = await h(); // v = hmac(K || V) + v = await h(); // v = hmac(K || V) return v; }; return async (seed: Bytes, pred: Pred): Promise => { // Even though it feels safe to reuse reset(); // the returned fn, don't, it's: 1. slower (JIT). 2. unsafe (async race conditions) await reseed(seed); // Steps D-G let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] - while (!(res = pred(await gen()))) await reseed(); // test predicate until it returns ok + while (!(res = pred(await gen()))) await reseed();// test predicate until it returns ok reset(); return res!; }; } else { - const h = (...b: Bytes[]) => { // Same, but synchronous + const h = (...b: Bytes[]) => { // asynchronous=false; same, but synchronous const f = _hmacSync; if (!f) err('etc.hmacSha256Sync not set'); - return f!(k, v, ...b); // hmac(k)(v, ...values) + return f!(k, v, ...b); // hmac(k)(v, ...values) }; - const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G - k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) - v = h(); // v = hmac(k || v) + const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G + k = h(u8n([0x00]), seed); // k = hmac(k || v || 0x00 || seed) + v = h(); // v = hmac(k || v) if (seed.length === 0) return; - k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) - v = h(); // v = hmac(k || v) + k = h(u8n([0x01]), seed); // k = hmac(k || v || 0x01 || seed) + v = h(); // v = hmac(k || v) }; - const gen = () => { // HMAC-DRBG generate() function + const gen = () => { // HMAC-DRBG generate() function if (i++ >= 1000) err(_e); - v = h(); // v = hmac(k || v) + v = h(); // v = hmac(k || v) return v; }; return (seed: Bytes, pred: Pred): T => { From a9ecf7259fae5eb5501b2483ce58e5b619f7789c Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 20 Mar 2023 22:02:29 +0000 Subject: [PATCH 064/145] docs --- README.md | 61 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 52b447b..116f887 100644 --- a/README.md +++ b/README.md @@ -274,31 +274,42 @@ helped to improve scalar multiplication speed. ## Upgrading -noble-secp256k1 v2.0 has been reduced 4x to just over 400 lines. It features -improved security and smaller attack surface. - -Some functionality present in v1, such as schnorr and DER, was removed: -use [**noble-curves**](https://github.com/paulmillr/noble-curves) if you still need it. - -- `getPublicKey()` and `getSharedSecret()` now produce compressed 33-byte - signatures by default. If you need the old 65-byte behavior, set isCompresse=false: - `getPublicKey(priv, false)`, `getSharedSecret(a, b, false)` -- `sign()`: now returns `Signature` instance with `{ r, s, recovery }` properties. - It could still be passed to `verify` as-is. - - `canonical` is now => `lowS`. The default value is the same as before: `lowS: true` - - `recovered` has been removed. Recovery bit is always returned in the `Signature` instance - - `der` has been removed. DER encoding is no longer supported. Use compact - format (32-byte r + 32-byte s), `Signature` instance methods - `toCompactRawBytes` / `toCompactHex()`: - `(await sign(msgHash, priv)).toCompactRawBytes()`. - Use noble-curves if you still need DER -- `verify()`: `strict` option has been renamed to `lowS`, default value is still the same -- `recoverPublicKey(msgHash, sig, recovery)` has been changed to `sig.recoverPublicKey(msgHash)` -- `Point` is now `ProjectivePoint`, working in 3d xyz projective coordinates instead of 2d xy affine -- Removed schnorr signatures, asn.1 DER, custom precomputes. Use noble-curves if you need them -- Support for environments that can't parse bigint literals has been removed -- Some utils such as `hmacSha256Sync` have been moved to `etc`: `import { etc } from "@noble/secp256k1"; -- node.js 18 and older are not supported without crypto shim (see [Usage](#usage)) +noble-secp256k1 v2.0 features improved security and smaller attack surface. +The goal of v2 is to provide minimum possible JS library which is safe and fast. + +That means the library was reduced 4x, to just over 400 lines. In order to +achieve the goal, **some features were moved** to +[noble-curves](https://github.com/paulmillr/noble-curves), which is +even safer and faster drop-in replacement library with same API. +Switch to curves if you intend to keep using these features: + +- DER encoding: toDERHex, toDERRawBytes, signing / verification of DER sigs +- Schnorr signatures +- Using `utils.precompute()` for non-base point +- Support for environments which don't support bigint literals +- Common.js support +- Support for node.js 18 and older without [shim](#usage) + +Other changes: + +- `getPublicKey` + - now produce 33-byte compressed signatures by default + - to use old behavior, which produced 65-byte uncompressed keys, set + second argument `isCompressed` to `false`: `getPublicKey(priv, false)` +- `sign` + - now returns `Signature` instance with `{ r, s, recovery }` properties + - `canonical` option was renamed to `lowS` + - `recovered` option has been removed because recovery bit is always returned now + - `der` option has been removed. There are 2 options: + 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`. + Compact encoding is simply a concatenation of 32-byte r and 32-byte s. + 2. If you must use DER encoding, switch to noble-curves (see above). +- `verify` + - `strict` option was renamed to `lowS` +- `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)` +- `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz) +- `utils` were split into `utils` (same api as in noble-curves) and + `etc` (`hmacSha256Sync` and others) ## License From 79ffcefd37c0434df67a96783acb09cddaba8cf0 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 20 Mar 2023 22:04:49 +0000 Subject: [PATCH 065/145] docs --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 116f887..6863fe0 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ Other changes: - `getPublicKey` - now produce 33-byte compressed signatures by default - to use old behavior, which produced 65-byte uncompressed keys, set - second argument `isCompressed` to `false`: `getPublicKey(priv, false)` + argument `isCompressed` to `false`: `getPublicKey(priv, false)` - `sign` - now returns `Signature` instance with `{ r, s, recovery }` properties - `canonical` option was renamed to `lowS` @@ -306,6 +306,10 @@ Other changes: 2. If you must use DER encoding, switch to noble-curves (see above). - `verify` - `strict` option was renamed to `lowS` +- `getSharedSecret` + - now produce 33-byte compressed signatures by default + - to use old behavior, which produced 65-byte uncompressed keys, set + argument `isCompressed` to `false`: `getSharedSecret(a, b, false)` - `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)` - `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz) - `utils` were split into `utils` (same api as in noble-curves) and From a8aa7d211814b4493f66e9a4731f303a126e6931 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 21 Mar 2023 05:49:34 +0000 Subject: [PATCH 066/145] 8952, 430 loc, 3988b --- README.md | 10 +++++--- index.d.ts | 7 ++--- index.js | 75 +++++++++++++++++++++++++++--------------------------- index.ts | 75 +++++++++++++++++++++++++++--------------------------- 4 files changed, 84 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 6863fe0..989f7d7 100644 --- a/README.md +++ b/README.md @@ -205,8 +205,9 @@ CURVE // curve prime; order; equation params, generator coordinates ## Security -The module is production-ready. Use -[noble-curves](https://github.com/paulmillr/noble-curves) if you need advanced security. +The module is production-ready. +It is cross-tested against [noble-curves](https://github.com/paulmillr/noble-curves), +and has similar security. 1. The current version is rewrite of v1, which has been audited by cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf) (funded by [Umbra.cash](https://umbra.cash) & community). @@ -274,7 +275,7 @@ helped to improve scalar multiplication speed. ## Upgrading -noble-secp256k1 v2.0 features improved security and smaller attack surface. +noble-secp256k1 v2 features improved security and smaller attack surface. The goal of v2 is to provide minimum possible JS library which is safe and fast. That means the library was reduced 4x, to just over 400 lines. In order to @@ -290,13 +291,14 @@ Switch to curves if you intend to keep using these features: - Common.js support - Support for node.js 18 and older without [shim](#usage) -Other changes: +Other changes for upgrading from @noble/secp256k1 1.7 to 2.0: - `getPublicKey` - now produce 33-byte compressed signatures by default - to use old behavior, which produced 65-byte uncompressed keys, set argument `isCompressed` to `false`: `getPublicKey(priv, false)` - `sign` + - is now sync; use `signAsync` for async version - now returns `Signature` instance with `{ r, s, recovery }` properties - `canonical` option was renamed to `lowS` - `recovered` option has been removed because recovery bit is always returned now diff --git a/index.d.ts b/index.d.ts index 8bf34b4..ba834d3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -20,8 +20,9 @@ declare class Point { constructor(px: bigint, py: bigint, pz: bigint); static readonly BASE: Point; static readonly ZERO: Point; - static fromPrivateKey(k: PrivKey): Point; + static fromAffine(p: AffinePoint): Point; static fromHex(hex: Hex): Point; + static fromPrivateKey(k: PrivKey): Point; get x(): bigint; get y(): bigint; equals(other: Point): boolean; @@ -38,6 +39,7 @@ declare class Point { toHex(isCompressed?: boolean): string; toRawBytes(isCompressed?: boolean): Uint8Array; } +export declare const ProjectivePoint: typeof Point; export declare function getPublicKey(privKey: PrivKey, isCompressed?: boolean): Uint8Array; export declare class Signature { readonly r: bigint; @@ -85,9 +87,8 @@ export declare const etc: { }; export declare const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; - randomPrivateKey: () => Bytes; isValidPrivateKey: (key: Hex) => boolean; + randomPrivateKey: () => Bytes; precompute(w?: number, p?: Point): Point; }; -export declare const ProjectivePoint: typeof Point; export {}; diff --git a/index.js b/index.js index 683e05d..14459e9 100644 --- a/index.js +++ b/index.js @@ -2,13 +2,11 @@ const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve const P = B256 - 0x1000003d1n; // curve's field prime const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order -const _a = 0n; // a equation's param -const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = { p: P, n: N, a: _a, b: _b, Gx, Gy }; // exported variables +export const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy }; // exported variables incl. a, b const fLen = 32; // field / group byte length -const crv = (x) => mod(mod(x * x) * x + _b); // x³ + ax + b weierstrass formula; no a +const crv = (x) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; no a const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n) => typeof n === 'bigint'; // is big integer const str = (s) => typeof s === 'string'; // is string @@ -18,21 +16,17 @@ const au8 = (a, l) => // is Uint8Array (of specific length) !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data) => new Uint8Array(data); // creates Uint8Array -const toU8 = (a, len) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a -const toPriv = (p) => { - if (!big(p)) - p = b2n(toU8(p, fLen)); // convert to bigint when bytes - return ge(p) ? p : err('private key out of range'); // check if bigint is in range -}; -let Gpows = undefined; // precomputes for base point G +const toU8 = (a, len) => au8(str(a) ? h2b(a) : u8n(a), len); // norm(hex/u8a) to u8a +const mod = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const isPoint = (p) => (p instanceof Point ? p : err('Point expected')); // is 3d point +let Gpows = undefined; // precomputes for base point G class Point { constructor(px, py, pz) { this.px = px; this.py = py; this.pz = pz; } // z is optional - static fromPrivateKey(k) { return G.mul(toPriv(k)); } // Create point from a private key. + static fromAffine(p) { return new Point(p.x, p.y, 1n); } static fromHex(hex) { hex = toU8(hex); // convert hex string to Uint8Array let p = undefined; @@ -52,6 +46,7 @@ class Point { p = new Point(x, slcNum(tail, fLen, 2 * fLen), 1n); return p ? p.ok() : err('Point is not on curve'); // Verify the result } + static fromPrivateKey(k) { return G.mul(toPriv(k)); } // Create point from a private key. get x() { return this.aff().x; } // .x, .y will call expensive toAffine: get y() { return this.aff().y; } // should be used with care. equals(other) { @@ -160,40 +155,20 @@ class Point { Point.BASE = new Point(Gx, Gy, 1n); // Generator / base point Point.ZERO = new Point(0n, 1n, 0n); // Identity / zero point const { BASE: G, ZERO: I } = Point; // Generator, identity points -const mod = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division -const inv = (num, md = P) => { - if (num === 0n || md <= 0n) - err(`no inverse n=${num} mod=${md}`); // no negative exponent for now - let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; - while (a !== 0n) { // uses euclidean gcd algorithm - const q = b / a, r = b % a; // not constant-time - const m = x - u * q, n = y - v * q; - b = a, a = r, x = u, y = v, u = m, v = n; - } - return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point -}; -const sqrt = (n) => { - let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". - for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. - if (e & 1n) - r = (r * num) % P; // Uses exponentiation by squaring. - num = (num * num) % P; // Not constant-time. - } - return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid -}; +export const ProjectivePoint = Point; const padh = (n, pad) => n.toString(16).padStart(pad, '0'); const b2h = (b) => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2b = (hex) => { const l = hex.length; // error if not string, if (!str(hex) || l % 2) - err('hex invalid'); // or has odd length like 3, 5. + err('hex invalid 1'); // or has odd length like 3, 5. const arr = u8n(l / 2); // create result array for (let i = 0; i < arr.length; i++) { const j = i * 2; const h = hex.slice(j, j + 2); // hexByte. slice is faster than substr const b = Number.parseInt(h, 16); // byte, created from string part if (Number.isNaN(b) || b < 0) - err('hex invalid'); // byte must be valid 0 <= byte < 256 + err('hex invalid 2'); // byte must be valid 0 <= byte < 256 arr[i] = b; } return arr; @@ -203,13 +178,38 @@ const slcNum = (b, from, to) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num) => { return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; -const n2h = (num) => b2h(n2b(num)); // number to hex +const n2h = (num) => b2h(n2b(num)); // number to 32b hex const concatB = (...arrs) => { const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length let pad = 0; // walk through each array, ensure arrs.forEach(a => { r.set(au8(a), pad); pad += a.length; }); // they have proper type return r; }; +const inv = (num, md = P) => { + if (num === 0n || md <= 0n) + err(`no inverse n=${num} mod=${md}`); // no negative exponent for now + let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; + while (a !== 0n) { // uses euclidean gcd algorithm + const q = b / a, r = b % a; // not constant-time + const m = x - u * q, n = y - v * q; + b = a, a = r, x = u, y = v, u = m, v = n; + } + return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point +}; +const sqrt = (n) => { + let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". + for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. + if (e & 1n) + r = (r * num) % P; // Uses exponentiation by squaring. + num = (num * num) % P; // Not constant-time. + } + return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid +}; +const toPriv = (p) => { + if (!big(p)) + p = b2n(toU8(p, fLen)); // convert to bigint when bytes + return ge(p) ? p : err('private key out of range'); // check if bigint is in range +}; const moreThanHalfN = (n) => n > (N >> 1n); // if a number is bigger than CURVE.n/2 export function getPublicKey(privKey, isCompressed = true) { return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output @@ -449,13 +449,13 @@ export const etc = { }; export const utils = { normPrivateKeyToScalar: toPriv, - randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 8)), isValidPrivateKey: (key) => { try { return !!toPriv(key); } catch (e) { return false; } }, + randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 8)), precompute(w = 8, p = G) { p.multiply(3n); return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { @@ -507,4 +507,3 @@ const wNAF = (n) => { } return { p, f }; // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() -export const ProjectivePoint = Point; diff --git a/index.ts b/index.ts index e30cad4..7e14aca 100644 --- a/index.ts +++ b/index.ts @@ -2,14 +2,12 @@ const B256 = 2n ** 256n; // secp256k1 is short weierstrass curve const P = B256 - 0x1000003d1n; // curve's field prime const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order -const _a = 0n; // a equation's param -const _b = 7n; // b equation's param const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = {p: P, n: N, a: _a, b: _b, Gx, Gy};// exported variables +export const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy};// exported variables incl. a, b const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; -const crv = (x: bigint) => mod(mod(x * x) * x + _b); // x³ + ax + b weierstrass formula; no a +const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; no a const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: unknown): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: unknown): s is string => typeof s === 'string'; // is string @@ -19,19 +17,16 @@ const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of spe !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array -const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : a, len); // normalize (hex/u8a) to u8a -const toPriv = (p: PrivKey): bigint => { // normalize private key to bigint - if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes - return ge(p) ? p : err('private key out of range'); // check if bigint is in range -}; -let Gpows: Point[] | undefined = undefined; // precomputes for base point G -interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coords +const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : u8n(a), len); // norm(hex/u8a) to u8a +const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point -class Point { // Point in 3d xyz projective coords +let Gpows: Point[] | undefined = undefined; // precomputes for base point G +interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coordinates +class Point { // Point in 3d xyz projective coordinates constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} // z is optional static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point static readonly ZERO = new Point(0n, 1n, 0n); // Identity / zero point - static fromPrivateKey(k: PrivKey) { return G.mul(toPriv(k)); } // Create point from a private key. + static fromAffine(p: AffinePoint) { return new Point(p.x, p.y, 1n); } static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // convert hex string to Uint8Array let p: Point | undefined = undefined; @@ -48,6 +43,7 @@ class Point { // Point in 3d xyz proje if (len === 65 && head === 0x04) p = new Point(x, slcNum(tail, fLen, 2 * fLen), 1n); return p ? p.ok() : err('Point is not on curve'); // Verify the result } + static fromPrivateKey(k: PrivKey) { return G.mul(toPriv(k)); } // Create point from a private key. get x() { return this.aff().x; } // .x, .y will call expensive toAffine: get y() { return this.aff().y; } // should be used with care. equals(other: Point): boolean { // Equality check: compare points @@ -124,52 +120,56 @@ class Point { // Point in 3d xyz proje } } const { BASE: G, ZERO: I } = Point; // Generator, identity points -const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division -const inv = (num: bigint, md = P): bigint => { // modular inversion - if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // no negative exponent for now - let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; - while (a !== 0n) { // uses euclidean gcd algorithm - const q = b / a, r = b % a; // not constant-time - const m = x - u * q, n = y - v * q; - b = a, a = r, x = u, y = v, u = m, v = n; - } - return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point -}; -const sqrt = (n: bigint) => { // √n = n^((p+1)/4) for fields p = 3 mod 4 - let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". - for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. - if (e & 1n) r = (r * num) % P; // Uses exponentiation by squaring. - num = (num * num) % P; // Not constant-time. - } - return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid -}; +export const ProjectivePoint = Point; const padh = (n: number | bigint, pad: number) => n.toString(16).padStart(pad, '0'); const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2b = (hex: string): Bytes => { // hex to bytes const l = hex.length; // error if not string, - if (!str(hex) || l % 2) err('hex invalid'); // or has odd length like 3, 5. + if (!str(hex) || l % 2) err('hex invalid 1'); // or has odd length like 3, 5. const arr = u8n(l / 2); // create result array for (let i = 0; i < arr.length; i++) { const j = i * 2; const h = hex.slice(j, j + 2); // hexByte. slice is faster than substr const b = Number.parseInt(h, 16); // byte, created from string part - if (Number.isNaN(b) || b < 0) err('hex invalid'); // byte must be valid 0 <= byte < 256 + if (Number.isNaN(b) || b < 0) err('hex invalid 2'); // byte must be valid 0 <= byte < 256 arr[i] = b; } return arr; }; const b2n = (b: Bytes): bigint => BigInt(`0x${b2h(b)||'0'}`); // bytes to number const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes num -const n2b = (num: bigint): Bytes => { // number to bytes. must be 0 <= num < B256 +const n2b = (num: bigint): Bytes => { // number to 32bytes. mustbe 0 <= num < B256 return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; -const n2h = (num: bigint): string => b2h(n2b(num)); // number to hex +const n2h = (num: bigint): string => b2h(n2b(num)); // number to 32b hex const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Array-s const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length let pad = 0; // walk through each array, ensure arrs.forEach(a => { r.set(au8(a), pad); pad += a.length }); // they have proper type return r; }; +const inv = (num: bigint, md = P): bigint => { // modular inversion + if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // no negative exponent for now + let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; + while (a !== 0n) { // uses euclidean gcd algorithm + const q = b / a, r = b % a; // not constant-time + const m = x - u * q, n = y - v * q; + b = a, a = r, x = u, y = v, u = m, v = n; + } + return b === 1n ? mod(x, md) : err('no inverse'); // b is gcd at this point +}; +const sqrt = (n: bigint) => { // √n = n^((p+1)/4) for fields p = 3 mod 4 + let r = 1n; // So, a special, fast case. Paper: "Square Roots from 1;24,51,10 to Dan Shanks". + for (let num = n, e = (P + 1n) / 4n; e > 0n; e >>= 1n) { // powMod: modular exponentiation. + if (e & 1n) r = (r * num) % P; // Uses exponentiation by squaring. + num = (num * num) % P; // Not constant-time. + } + return mod(r * r) === n ? r : err('sqrt invalid'); // check if result is valid +}; +const toPriv = (p: PrivKey): bigint => { // normalize private key to bigint + if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes + return ge(p) ? p : err('private key out of range'); // check if bigint is in range +}; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 export function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output @@ -383,8 +383,8 @@ export const etc = { // Not placed in `utils` } export const utils = { // utilities normPrivateKeyToScalar: toPriv, - randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, + randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. precompute(w=8, p: Point = G) { p.multiply(3n); return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { // Allow setting it once, ignore then @@ -428,4 +428,3 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo } return { p, f } // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() -export const ProjectivePoint = Point; From 90dfc0a5891e4c894df7f82ad51142cdcdc78053 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 21 Mar 2023 06:01:57 +0000 Subject: [PATCH 067/145] readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 989f7d7..a14b201 100644 --- a/README.md +++ b/README.md @@ -313,6 +313,7 @@ Other changes for upgrading from @noble/secp256k1 1.7 to 2.0: - to use old behavior, which produced 65-byte uncompressed keys, set argument `isCompressed` to `false`: `getSharedSecret(a, b, false)` - `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)` +- `number` type for private keys have been removed: use `bigint` instead - `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz) - `utils` were split into `utils` (same api as in noble-curves) and `etc` (`hmacSha256Sync` and others) From cef4e071ca5ae6222891ab9fc26698c104f7add0 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 21 Mar 2023 06:04:21 +0000 Subject: [PATCH 068/145] Docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a14b201..7a4ff50 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, - All releases are signed with PGP keys - Check out [homepage](https://paulmillr.com/noble/) & all libraries: [curves](https://github.com/paulmillr/noble-curves) - ([secp256k1](https://github.com/paulmillr/noble-secp256k1), + (4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519)), [hashes](https://github.com/paulmillr/noble-hashes) From 82e5d6d9c817b4d6a65de723a942f2bd050ace57 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 21 Mar 2023 06:08:21 +0000 Subject: [PATCH 069/145] docs --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7a4ff50..bdbde9d 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and deterministic **ECDSA** signatures from RFC6979. -The library does not use dependencies and is as minimal as possible. -[noble-curves](https://github.com/paulmillr/noble-curves) is advanced drop-in -replacement for noble-secp256k1 with more features such as Schnorr signatures, -DER encoding and support for different hash functions. +The library is a tiny single-feature version of +[noble-curves](https://github.com/paulmillr/noble-curves), with some features +removed. Check out curves as a drop-in replacement with +Schnorr signatures, DER encoding and support for different hash functions. Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, [the online demo](https://paulmillr.com/ecc) and blog post From 883a3941cfe4366772d61b81a6fb334ca92f6ce8 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 21 Mar 2023 06:27:51 +0000 Subject: [PATCH 070/145] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bdbde9d..a6e8cbc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# noble-secp256k1 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) +# noble-secp256k1 [Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, @@ -17,7 +17,7 @@ Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools. -- No dependencies, one small file +- No dependencies, protection against supply chain attacks - Easily auditable TypeScript/JS code - Supported in all major browsers and stable node.js versions - All releases are signed with PGP keys From e5abbd5f407a07a1927c2b941475366e7ea097c6 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 22 Mar 2023 01:35:19 +0000 Subject: [PATCH 071/145] remove backticks --- README.md | 4 ++-- index.js | 20 ++++++++++---------- index.ts | 26 +++++++++++++------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a6e8cbc..4b9302d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, -ECDH key agreement protocol and deterministic **ECDSA** signatures from RFC6979. +ECDH key agreement protocol and deterministic ECDSA signatures from RFC6979. The library is a tiny single-feature version of [noble-curves](https://github.com/paulmillr/noble-curves), with some features @@ -43,7 +43,7 @@ import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js const privKey = secp.utils.randomPrivateKey(); // Secure random private key // sha256 of 'hello world' const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; - const pubKey = secp.getPublicKey(privKey); // Make pubkey from the private key + const pubKey = secp.getPublicKey(privKey); // Make pubkey from the private key const signature = await secp.signAsync(msgHash, privKey); // sign const isValid = secp.verify(signature, msgHash, pubKey); // verify diff --git a/index.js b/index.js index 14459e9..c62b3be 100644 --- a/index.js +++ b/index.js @@ -25,7 +25,7 @@ class Point { this.px = px; this.py = py; this.pz = pz; - } // z is optional + } //3d=less inversions static fromAffine(p) { return new Point(p.x, p.y, 1n); } static fromHex(hex) { hex = toU8(hex); // convert hex string to Uint8Array @@ -146,7 +146,7 @@ class Point { toHex(isCompressed = true) { const { x, y } = this.aff(); // convert to 2d xy affine point const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; // 0x02, 0x03, 0x04 prefix - return `${head}${n2h(x)}${isCompressed ? '' : n2h(y)}`; // prefix||x and ||y + return head + n2h(x) + (isCompressed ? '' : n2h(y)); // prefix||x and ||y } toRawBytes(isCompressed = true) { return h2b(this.toHex(isCompressed)); // re-use toHex(), convert hex to bytes @@ -173,21 +173,21 @@ const h2b = (hex) => { } return arr; }; -const b2n = (b) => BigInt(`0x${b2h(b) || '0'}`); // bytes to number +const b2n = (b) => BigInt('0x' + (b2h(b) || '0')); // bytes to number const slcNum = (b, from, to) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num) => { return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; const n2h = (num) => b2h(n2b(num)); // number to 32b hex const concatB = (...arrs) => { - const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length - let pad = 0; // walk through each array, ensure - arrs.forEach(a => { r.set(au8(a), pad); pad += a.length; }); // they have proper type + const r = u8n(arrs.reduce((sum, a) => sum + au8(a).length, 0)); // create u8a of summed length + let pad = 0; // walk through each array, + arrs.forEach(a => { r.set(a, pad); pad += a.length; }); // ensure they have proper type return r; }; const inv = (num, md = P) => { if (num === 0n || md <= 0n) - err(`no inverse n=${num} mod=${md}`); // no negative exponent for now + err('no inverse n=' + num + ' mod=' + md); // no neg exponent for now let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { // uses euclidean gcd algorithm const q = b / a, r = b % a; // not constant-time @@ -236,8 +236,8 @@ export class Signature { const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element - const prefix = (rec & 1) === 0 ? '02' : '03'; // prefix is 0x02 or 0x03 - const R = Point.fromHex(`${prefix}${n2h(radj)}`); // concat prefix + hex repr of r + const head = (rec & 1) === 0 ? '02' : '03'; // head is 0x02 or 0x03 + const R = Point.fromHex(head + n2h(radj)); // concat head + hex repr of r const ir = inv(radj, N); // r^-1 const u1 = mod(-h * ir, N); // -hr^-1 const u2 = mod(s * ir, N); // sr^-1 @@ -255,7 +255,7 @@ const bits2int_modN = (bytes) => { return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; const i2o = (num) => n2b(num); // int to octets -const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with `crypto` +const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with crypto typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; let _hmacSync; // Can be redefined by use in utils; built-ins don't provide it const optS = { lowS: true }; // opts for sign() diff --git a/index.ts b/index.ts index 7e14aca..7e115db 100644 --- a/index.ts +++ b/index.ts @@ -13,17 +13,17 @@ const big = (n: unknown): n is bigint => typeof n === 'bigint'; // is big intege const str = (s: unknown): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const au8 = (a: any, l?: number): Bytes => // is Uint8Array (of specific length) +const au8 = (a: unknown, l?: number): Bytes => // is Uint8Array (of specific length) !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : u8n(a), len); // norm(hex/u8a) to u8a const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division -const isPoint = (p: any) => (p instanceof Point ? p : err('Point expected')); // is 3d point +const isPoint = (p: unknown) => (p instanceof Point ? p : err('Point expected')); // is 3d point let Gpows: Point[] | undefined = undefined; // precomputes for base point G interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coordinates class Point { // Point in 3d xyz projective coordinates - constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} // z is optional + constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} //3d=less inversions static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point static readonly ZERO = new Point(0n, 1n, 0n); // Identity / zero point static fromAffine(p: AffinePoint) { return new Point(p.x, p.y, 1n); } @@ -113,7 +113,7 @@ class Point { // Point in 3d xyz proje toHex(isCompressed = true) { // Encode point to hex string. const { x, y } = this.aff(); // convert to 2d xy affine point const head = isCompressed ? ((y & 1n) === 0n ? '02' : '03') : '04'; // 0x02, 0x03, 0x04 prefix - return `${head}${n2h(x)}${isCompressed ? '' : n2h(y)}`; // prefix||x and ||y + return head + n2h(x) + (isCompressed ? '' : n2h(y));// prefix||x and ||y } toRawBytes(isCompressed = true) { // Encode point to Uint8Array. return h2b(this.toHex(isCompressed)); // re-use toHex(), convert hex to bytes @@ -136,20 +136,20 @@ const h2b = (hex: string): Bytes => { // hex to bytes } return arr; }; -const b2n = (b: Bytes): bigint => BigInt(`0x${b2h(b)||'0'}`); // bytes to number +const b2n = (b: Bytes): bigint => BigInt('0x' + (b2h(b) || '0')); // bytes to number const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes num const n2b = (num: bigint): Bytes => { // number to 32bytes. mustbe 0 <= num < B256 return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; const n2h = (num: bigint): string => b2h(n2b(num)); // number to 32b hex const concatB = (...arrs: Bytes[]) => { // concatenate Uint8Array-s - const r = u8n(arrs.reduce((sum, a) => sum + a.length, 0)); // create u8a of summed length - let pad = 0; // walk through each array, ensure - arrs.forEach(a => { r.set(au8(a), pad); pad += a.length }); // they have proper type + const r = u8n(arrs.reduce((sum, a) => sum + au8(a).length, 0)); // create u8a of summed length + let pad = 0; // walk through each array, + arrs.forEach(a => {r.set(a, pad); pad += a.length}); // ensure they have proper type return r; }; const inv = (num: bigint, md = P): bigint => { // modular inversion - if (num === 0n || md <= 0n) err(`no inverse n=${num} mod=${md}`); // no negative exponent for now + if (num === 0n || md <= 0n) err('no inverse n=' + num + ' mod=' + md); // no neg exponent for now let a = mod(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n; while (a !== 0n) { // uses euclidean gcd algorithm const q = b / a, r = b % a; // not constant-time @@ -191,8 +191,8 @@ export class Signature { // ECDSA Signature class const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element - const prefix = (rec! & 1) === 0 ? '02' : '03'; // prefix is 0x02 or 0x03 - const R = Point.fromHex(`${prefix}${n2h(radj)}`); // concat prefix + hex repr of r + const head = (rec! & 1) === 0 ? '02' : '03'; // head is 0x02 or 0x03 + const R = Point.fromHex(head + n2h(radj)); // concat head + hex repr of r const ir = inv(radj, N); // r^-1 const u1 = mod(-h * ir, N); // -hr^-1 const u2 = mod(s * ir, N); // sr^-1 @@ -211,7 +211,7 @@ const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be us }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets declare const globalThis: Record | undefined; // Typescript symbol present in browsers -const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with `crypto` +const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with crypto typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it @@ -360,7 +360,7 @@ function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compli const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); } -export const etc = { // Not placed in `utils` because utils +export const etc = { // Not placed in utils because they hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, // math utilities From e566be84b5ce1c05087f2a363f737b8472d479be Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:00:03 +0000 Subject: [PATCH 072/145] 8918, 431loc, 3984b. Move exports below --- index.d.ts | 26 +++++++++++++------------- index.js | 37 +++++++++++++++++++------------------ index.ts | 37 +++++++++++++++++++------------------ 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/index.d.ts b/index.d.ts index ba834d3..d5ce689 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,4 +1,4 @@ -export declare const CURVE: { +declare const CURVE: { p: bigint; n: bigint; a: bigint; @@ -29,19 +29,18 @@ declare class Point { negate(): Point; double(): Point; add(other: Point): Point; - multiply(n: bigint, safe?: boolean): Point; + mul(n: bigint, safe?: boolean): Point; mulAddQUns(R: Point, u1: bigint, u2: bigint): Point; toAffine(): AffinePoint; assertValidity(): Point; - mul(n: bigint, safe?: boolean): Point; + multiply(n: bigint): Point; aff(): AffinePoint; ok(): Point; toHex(isCompressed?: boolean): string; toRawBytes(isCompressed?: boolean): Uint8Array; } -export declare const ProjectivePoint: typeof Point; -export declare function getPublicKey(privKey: PrivKey, isCompressed?: boolean): Uint8Array; -export declare class Signature { +declare function getPublicKey(privKey: PrivKey, isCompressed?: boolean): Uint8Array; +declare class Signature { readonly r: bigint; readonly s: bigint; readonly recovery?: number | undefined; @@ -55,11 +54,11 @@ export declare class Signature { toCompactHex(): string; } type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); -export declare function signAsync(msgh: Hex, priv: Hex, opts?: { +declare function signAsync(msgh: Hex, priv: Hex, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; }): Promise; -export declare function sign(msgh: Hex, priv: Hex, opts?: { +declare function sign(msgh: Hex, priv: Hex, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; }): Signature; @@ -67,12 +66,12 @@ type SigLike = { r: bigint; s: bigint; }; -export declare function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts?: { +declare function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts?: { lowS?: boolean | undefined; }): boolean; -export declare function getSharedSecret(privA: Hex, pubB: Hex, isCompressed?: boolean): Bytes; +declare function getSharedSecret(privA: Hex, pubB: Hex, isCompressed?: boolean): Bytes; declare function hashToPrivateKey(hash: Hex): Bytes; -export declare const etc: { +declare const etc: { hexToBytes: (hex: string) => Bytes; bytesToHex: (b: Bytes) => string; concatBytes: (...arrs: Bytes[]) => Uint8Array; @@ -85,10 +84,11 @@ export declare const etc: { hashToPrivateKey: typeof hashToPrivateKey; randomBytes: (len: number) => Bytes; }; -export declare const utils: { +declare const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; isValidPrivateKey: (key: Hex) => boolean; randomPrivateKey: () => Bytes; precompute(w?: number, p?: Point): Point; }; -export {}; +export { getPublicKey, sign, signAsync, verify, CURVE, // Remove the export to easily use in REPL +getSharedSecret, etc, utils, Point as ProjectivePoint, Signature }; diff --git a/index.js b/index.js index c62b3be..60b4464 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ const P = B256 - 0x1000003d1n; // curve's field prime const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy }; // exported variables incl. a, b +const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy }; // exported variables incl. a, b const fLen = 32; // field / group byte length const crv = (x) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; no a const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace @@ -103,7 +103,7 @@ class Point { Z3 = mod(Z3 + t0); // step 40 return new Point(X3, Y3, Z3); } - multiply(n, safe = true) { + mul(n, safe = true) { if (!safe && n === 0n) return I; // in unsafe mode, allow zero if (!ge(n)) @@ -140,7 +140,7 @@ class Point { return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal this : err('Point invalid: not on curve'); } - mul(n, safe) { return this.multiply(n, safe); } // Aliases to compress code + multiply(n) { return this.mul(n); } // Aliases to compress code aff() { return this.toAffine(); } ok() { return this.assertValidity(); } toHex(isCompressed = true) { @@ -155,7 +155,6 @@ class Point { Point.BASE = new Point(Gx, Gy, 1n); // Generator / base point Point.ZERO = new Point(0n, 1n, 0n); // Identity / zero point const { BASE: G, ZERO: I } = Point; // Generator, identity points -export const ProjectivePoint = Point; const padh = (n, pad) => n.toString(16).padStart(pad, '0'); const b2h = (b) => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2b = (hex) => { @@ -211,10 +210,10 @@ const toPriv = (p) => { return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; const moreThanHalfN = (n) => n > (N >> 1n); // if a number is bigger than CURVE.n/2 -export function getPublicKey(privKey, isCompressed = true) { +function getPublicKey(privKey, isCompressed = true) { return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output } -export class Signature { +class Signature { constructor(r, s, recovery) { this.r = r; this.s = s; @@ -292,7 +291,7 @@ function prepSig(msgh, priv, opts = optS) { const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1(m + rd) mod n if (s === 0n) return; // s=0 invalid - let normS = s; + let normS = s; // normalized S let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always normS = mod(-s, N); // in the bottom half of CURVE.n @@ -366,16 +365,16 @@ function hmacDrbg(asynchronous) { }; } } -// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k -export async function signAsync(msgh, priv, opts = optS) { - const { seed, k2sig } = prepSig(msgh, priv, opts); - return hmacDrbg(true)(seed, k2sig); +// ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k +async function signAsync(msgh, priv, opts = optS) { + const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg + return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } -export function sign(msgh, priv, opts = optS) { - const { seed, k2sig } = prepSig(msgh, priv, opts); - return hmacDrbg(false)(seed, k2sig); +function sign(msgh, priv, opts = optS) { + const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg + return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } -export function verify(sig, msgh, pub, opts = optV) { +function verify(sig, msgh, pub, opts = optV) { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true @@ -413,7 +412,7 @@ export function verify(sig, msgh, pub, opts = optV) { const v = mod(R.x, N); // <== The weird ECDSA part. R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r } -export function getSharedSecret(privA, pubB, isCompressed = true) { +function getSharedSecret(privA, pubB, isCompressed = true) { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH } function hashToPrivateKey(hash) { @@ -424,7 +423,7 @@ function hashToPrivateKey(hash) { const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); } -export const etc = { +const etc = { hexToBytes: h2b, bytesToHex: b2h, concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, @@ -447,7 +446,7 @@ export const etc = { return crypto.getRandomValues(u8n(len)); }, }; -export const utils = { +const utils = { normPrivateKeyToScalar: toPriv, isValidPrivateKey: (key) => { try { return !!toPriv(key); @@ -507,3 +506,5 @@ const wNAF = (n) => { } return { p, f }; // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() +export { getPublicKey, sign, signAsync, verify, CURVE, // Remove the export to easily use in REPL +getSharedSecret, etc, utils, Point as ProjectivePoint, Signature }; // envs like browser console diff --git a/index.ts b/index.ts index 7e115db..3f8288b 100644 --- a/index.ts +++ b/index.ts @@ -4,7 +4,7 @@ const P = B256 - 0x1000003d1n; // curve's field prime const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -export const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy};// exported variables incl. a, b +const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy};// exported variables incl. a, b const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; no a @@ -79,7 +79,7 @@ class Point { // Point in 3d xyz proje Z3 = mod(Z3 + t0); // step 40 return new Point(X3, Y3, Z3); } - multiply(n: bigint, safe = true) { // Point scalar multiplication. + mul(n: bigint, safe = true) { // Point scalar multiplication. if (!safe && n === 0n) return I; // in unsafe mode, allow zero if (!ge(n)) err('invalid scalar'); // must be 0 < n < CURVE.n if (this.equals(G)) return wNAF(n).p; // use precomputes for base point @@ -107,7 +107,7 @@ class Point { // Point in 3d xyz proje return mod(y * y) === crv(x) ? // y² = x³ + ax + b, must be equal this : err('Point invalid: not on curve'); } - mul(n: bigint, safe?: boolean) { return this.multiply(n, safe); } // Aliases to compress code + multiply(n: bigint) { return this.mul(n); } // Aliases to compress code aff() { return this.toAffine(); } ok() { return this.assertValidity(); } toHex(isCompressed = true) { // Encode point to hex string. @@ -120,7 +120,6 @@ class Point { // Point in 3d xyz proje } } const { BASE: G, ZERO: I } = Point; // Generator, identity points -export const ProjectivePoint = Point; const padh = (n: number | bigint, pad: number) => n.toString(16).padStart(pad, '0'); const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join(''); // bytes to hex const h2b = (hex: string): Bytes => { // hex to bytes @@ -171,10 +170,10 @@ const toPriv = (p: PrivKey): bigint => { // normalize private key return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 -export function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv +function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output } -export class Signature { // ECDSA Signature class +class Signature { // ECDSA Signature class constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { this.assertValidity(); // recovery bit is optional when } // constructed outside. @@ -244,7 +243,7 @@ function prepSig(msgh: Hex, priv: Hex, opts = optS): BC { // prepare for RFC6979 if (r === 0n) return; // r=0 invalid const s = mod(ik * mod(m + mod(d * r, N), N), N); // s = k^-1(m + rd) mod n if (s === 0n) return; // s=0 invalid - let normS = s; + let normS = s; // normalized S let rec = (q.x === r ? 0 : 2) | Number(q.y & 1n); // recovery bit if (lowS && moreThanHalfN(s)) { // if lowS was passed, ensure s is always normS = mod(-s, N); // in the bottom half of CURVE.n @@ -313,17 +312,17 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async }; } } -// ECDSA sig generation via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k -export async function signAsync(msgh: Hex, priv: Hex, opts = optS): Promise { - const { seed, k2sig } = prepSig(msgh, priv, opts); - return hmacDrbg(true)(seed, k2sig); +// ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k +async function signAsync(msgh: Hex, priv: Hex, opts = optS): Promise { + const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg + return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } -export function sign(msgh: Hex, priv: Hex, opts = optS): Signature { - const { seed, k2sig } = prepSig(msgh, priv, opts); - return hmacDrbg(false)(seed, k2sig); +function sign(msgh: Hex, priv: Hex, opts = optS): Signature { + const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg + return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } type SigLike = { r: bigint, s: bigint }; -export function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { +function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true if ('strict' in opts) err('verify() legacy options not supported'); // legacy param @@ -350,7 +349,7 @@ export function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): bo const v = mod(R.x, N); // <== The weird ECDSA part. R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r } -export function getSharedSecret(privA: Hex, pubB: Hex, isCompressed = true): Bytes { +function getSharedSecret(privA: Hex, pubB: Hex, isCompressed = true): Bytes { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH } function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compliant key generation @@ -360,7 +359,7 @@ function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compli const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); } -export const etc = { // Not placed in utils because they +const etc = { // Not placed in utils because they hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, // math utilities @@ -381,7 +380,7 @@ export const etc = { // Not placed in utils b return crypto.getRandomValues(u8n(len)); }, } -export const utils = { // utilities +const utils = { // utilities normPrivateKeyToScalar: toPriv, isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. @@ -428,3 +427,5 @@ const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent fo } return { p, f } // return both real and fake points for JIT }; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul() +export { getPublicKey, sign, signAsync, verify, CURVE, // Remove the export to easily use in REPL + getSharedSecret, etc, utils, Point as ProjectivePoint, Signature } // envs like browser console From b1995ebddcd24c121848a68309096d99e409b3fc Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:22:23 +0000 Subject: [PATCH 073/145] README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b9302d..8aef9fe 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ removed. Check out curves as a drop-in replacement with Schnorr signatures, DER encoding and support for different hash functions. Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, -[the online demo](https://paulmillr.com/ecc) and blog post +[the online demo](https://paulmillr.com/noble/) and blog post [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). ### This library belongs to _noble_ crypto @@ -18,7 +18,7 @@ Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools. - No dependencies, protection against supply chain attacks -- Easily auditable TypeScript/JS code +- Auditable TypeScript / JS code - Supported in all major browsers and stable node.js versions - All releases are signed with PGP keys - Check out [homepage](https://paulmillr.com/noble/) & all libraries: From 745cb34ef1b67dfda434942524ece4b3910a75ec Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:30:50 +0000 Subject: [PATCH 074/145] Wording --- README.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8aef9fe..9bba7f8 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ [Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, -ECDH key agreement protocol and deterministic ECDSA signatures from RFC6979. +ECDH key agreement protocol and deterministic ECDSA signatures matching RFC6979. The library is a tiny single-feature version of [noble-curves](https://github.com/paulmillr/noble-curves), with some features removed. Check out curves as a drop-in replacement with Schnorr signatures, DER encoding and support for different hash functions. -Check out: [Upgrading](#upgrading) section for v1 to v2 transition instructions, +Take a look at: [Upgrading](#upgrading) section for v1 to v2 transition instructions, [the online demo](https://paulmillr.com/noble/) and blog post [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). diff --git a/package.json b/package.json index 32d41a7..ab2ed3f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", "version": "2.0.0-pre", - "description": "Fastest 4KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures compliant with RFC6979", + "description": "Fastest 4KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures matching RFC6979", "files": [ "index.js", "index.d.ts", From 6deef87b71015243d4b26f37c25ebade75528b2f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:42:27 +0000 Subject: [PATCH 075/145] wording --- README.md | 5 ++--- package-lock.json | 8 ++++---- package.json | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9bba7f8..4a01c29 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # noble-secp256k1 -[Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf), -an elliptic curve that could be used for asymmetric encryption, -ECDH key agreement protocol and deterministic ECDSA signatures matching RFC6979. +[Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf) +elliptic curve. Auditable, high-security, 0-dependency ECDH & ECDSA signatures compliant with RFC6979. The library is a tiny single-feature version of [noble-curves](https://github.com/paulmillr/noble-curves), with some features diff --git a/package-lock.json b/package-lock.json index 4497db8..4cd2d55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ ], "license": "MIT", "devDependencies": { - "@noble/hashes": "1.2.0", + "@noble/hashes": "1.3.0", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", @@ -23,9 +23,9 @@ } }, "node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index ab2ed3f..00c5dc7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", "version": "2.0.0-pre", - "description": "Fastest 4KB JS implementation of secp256k1. Auditable, high-security, 0-dependency ECDSA signatures matching RFC6979", + "description": "Fastest 4KB JS implementation of secp256k1 elliptic curve. Auditable, high-security, 0-dependency ECDH & ECDSA signatures compliant with RFC6979", "files": [ "index.js", "index.d.ts", @@ -28,7 +28,7 @@ }, "license": "MIT", "devDependencies": { - "@noble/hashes": "1.2.0", + "@noble/hashes": "1.3.0", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", From c54803ccfa3f66220277a6f20f749323ee14b0ec Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:50:10 +0000 Subject: [PATCH 076/145] tags --- package.json | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 00c5dc7..b01f7b9 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "build": "tsc", "build:release": "rollup -c rollup.config.js", "test": "node test/secp256k1.test.mjs", - "coverage": "jest --coverage", "bench": "node test/benchmark.js", "min": "cd test/build; npm install; npm run terser", "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts` LOC, `npm run --silent min | gzip -c8 | wc -c`B gzipped\"" @@ -36,21 +35,17 @@ }, "keywords": [ "secp256k1", - "secp", - "secp256", - "elliptic", - "elliptic curve", - "curve", - "signature", - "ecc", "rfc6979", - "sig", - "bip0340", - "bip340", + "signature", "ecdsa", + "noble", + "cryptography", + "elliptic curve", + "ecc", + "curve", "cryptography", - "security", - "noble" + "bitcoin", + "ethereum" ], "exports": { ".": { From fe33a30ee9f79f10090537fab2e42a7c1efa890c Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:53:26 +0000 Subject: [PATCH 077/145] tags --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b01f7b9..017a800 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "elliptic curve", "ecc", "curve", - "cryptography", + "schnorr", "bitcoin", "ethereum" ], From d38ed222f1a6d5d296a9e4f815a1c174e46c335f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 24 Mar 2023 09:58:25 +0000 Subject: [PATCH 078/145] Release 2.0.0. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 017a800..56584ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@noble/secp256k1", - "version": "2.0.0-pre", + "version": "2.0.0", "description": "Fastest 4KB JS implementation of secp256k1 elliptic curve. Auditable, high-security, 0-dependency ECDH & ECDSA signatures compliant with RFC6979", "files": [ "index.js", From 6b5e888b7017326575718321e885ac09a723b304 Mon Sep 17 00:00:00 2001 From: Joel Walker Date: Fri, 7 Apr 2023 18:11:29 -0700 Subject: [PATCH 079/145] Export etc for deno --- mod.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod.ts b/mod.ts index 900edd0..dfce175 100644 --- a/mod.ts +++ b/mod.ts @@ -2,7 +2,7 @@ import { CURVE, ProjectivePoint, Signature, getPublicKey, sign, signAsync, verify, getSharedSecret, - utils, + utils, etc, } from './index.ts'; import { hmac } from 'npm:@noble/hashes@1.2.0/hmac'; import { sha256 } from 'npm:@noble/hashes@1.2.0/sha256'; @@ -23,5 +23,5 @@ utils.hmacSha256Sync = function hmac(key: Uint8Array, ...messages: Uint8Array[]) export { CURVE, ProjectivePoint, Signature, getPublicKey, sign, signAsync, verify, getSharedSecret, - utils, + utils, etc, }; From 4c477748ac40e3b726821645cdc2d0b68928166f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 10 Apr 2023 03:22:54 +0000 Subject: [PATCH 080/145] Update test vectors and wycheproof --- package-lock.json | 4 +- test/secp256k1.test.mjs | 26 +- test/vectors/ecdh.json | 4545 --------- test/vectors/schnorr.csv | 16 - test/vectors/{ => secp256k1}/ecdsa.json | 0 test/vectors/{ => secp256k1}/points.json | 0 test/vectors/{ => secp256k1}/privates-2.txt | 0 test/vectors/{ => secp256k1}/privates.json | 0 test/vectors/wychenproof.json | 4474 --------- test/wycheproof/ecdh_secp256k1_test.json | 8441 +++++++++++++++++ .../ecdsa_secp256k1_sha256_test.json | 6356 +++++++++++++ 11 files changed, 14817 insertions(+), 9045 deletions(-) delete mode 100644 test/vectors/ecdh.json delete mode 100644 test/vectors/schnorr.csv rename test/vectors/{ => secp256k1}/ecdsa.json (100%) rename test/vectors/{ => secp256k1}/points.json (100%) rename test/vectors/{ => secp256k1}/privates-2.txt (100%) rename test/vectors/{ => secp256k1}/privates.json (100%) delete mode 100644 test/vectors/wychenproof.json create mode 100644 test/wycheproof/ecdh_secp256k1_test.json create mode 100644 test/wycheproof/ecdsa_secp256k1_sha256_test.json diff --git a/package-lock.json b/package-lock.json index 4cd2d55..dd76064 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@noble/secp256k1", - "version": "2.0.0-pre", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@noble/secp256k1", - "version": "2.0.0-pre", + "version": "2.0.0", "funding": [ { "type": "individual", diff --git a/test/secp256k1.test.mjs b/test/secp256k1.test.mjs index 87a8fb3..618488f 100644 --- a/test/secp256k1.test.mjs +++ b/test/secp256k1.test.mjs @@ -8,14 +8,14 @@ import { secp, sigFromDER, sigToDER, selectHash, normVerifySig, mod, bytesToNumberBE, numberToBytesBE } from './secp256k1.helpers.mjs'; -import { default as ecdsa } from './vectors/ecdsa.json' assert { type: 'json' }; -import { default as ecdh } from './vectors/ecdh.json' assert { type: 'json' }; -import { default as privates } from './vectors/privates.json' assert { type: 'json' }; -import { default as points } from './vectors/points.json' assert { type: 'json' }; -import { default as wp } from './vectors/wychenproof.json' assert { type: 'json' }; +import { default as ecdsa } from './vectors/secp256k1/ecdsa.json' assert { type: 'json' }; +import { default as ecdh } from './wycheproof/ecdh_secp256k1_test.json' assert { type: 'json' }; +import { default as privates } from './vectors/secp256k1/privates.json' assert { type: 'json' }; +import { default as points } from './vectors/secp256k1/points.json' assert { type: 'json' }; +import { default as wp } from './wycheproof/ecdsa_secp256k1_sha256_test.json' assert { type: 'json' }; const Point = secp.ProjectivePoint; -const privatesTxt = readFileSync('./test/vectors/privates-2.txt', 'utf-8'); +const privatesTxt = readFileSync('./test/vectors/secp256k1/privates-2.txt', 'utf-8'); const FC_BIGINT = fc.bigInt(1n + 1n, secp.CURVE.n - 1n); // prettier-ignore @@ -500,14 +500,24 @@ describe('secp256k1', () => { should('wycheproof vectors', () => { for (let group of wp.testGroups) { // const pubKey = Point.fromHex().toRawBytes(); - const pubKey = group.key.uncompressed; + const key = group.publicKey; + const pubKey = key.uncompressed; + for (let test of group.tests) { const h = selectHash(secp); const m = h(hexToBytes(test.msg)); if (test.result === 'valid' || test.result === 'acceptable') { + let sig; + try { + sig = sigFromDER(test.sig); + } catch (e) { + // These old Wycheproof vectors which allows invalid behaviour of DER parser + if (e.message === 'Invalid signature integer: negative') continue; + throw e; + } const verified = secp.verify(normVerifySig(test.sig), m, pubKey); - if (sigFromDER(test.sig).hasHighS()) { + if (sig.hasHighS()) { deepStrictEqual(verified, false); } else { deepStrictEqual(verified, true); diff --git a/test/vectors/ecdh.json b/test/vectors/ecdh.json deleted file mode 100644 index e6609cf..0000000 --- a/test/vectors/ecdh.json +++ /dev/null @@ -1,4545 +0,0 @@ -{ - "algorithm" : "ECDH", - "generatorVersion" : "0.8r12", - "numberOfTests" : 446, - "header" : [ - "Test vectors of type EcdhTest are intended for", - "testing an ECDH implementations using X509 encoded", - "public keys and integers for private keys.", - "Test vectors of this format are useful for testing", - "Java providers." - ], - "notes" : { - "AddSubChain" : "The private key has a special value. Implementations using addition subtraction chains for the point multiplication may get the point at infinity as an intermediate result. See CVE_2017_10176", - "CompressedPoint" : "The point in the public key is compressed. Not every library supports points in compressed format.", - "InvalidAsn" : "The public key in this test uses an invalid ASN encoding. Some cases where the ASN parser is not strictly checking the ASN format are benign as long as the ECDH computation still returns the correct shared value.", - "InvalidPublic" : "The public key has been modified and is invalid. An implementation should always check whether the public key is valid and on the same curve as the private key. The test vector includes the shared secret computed with the original public key if the public point is on the curve of the private key. Generating a shared secret other than the one with the original key likely indicates that the bug is exploitable.", - "ModifiedPrime" : "The modulus of the public key has been modified. The public point of the public key has been chosen so that it is both a point on both the curve of the modified public key and the private key.", - "UnnamedCurve" : "The public key does not use a named curve. RFC 3279 allows to encode such curves by explicitly encoding, the parameters of the curve equation, modulus, generator, order and cofactor. However, many crypto libraries only support named curves. Modifying some of the EC parameters and encoding the corresponding public key as an unnamed curve is a potential attack vector.", - "UnusedParam" : "A parameter that is typically not used for ECDH has been modified. Sometimes libraries ignore small differences between public and private key. For example, a library might ignore an incorrect cofactor in the public key. We consider ignoring such changes as acceptable as long as these differences do not change the outcome of the ECDH computation, i.e. as long as the computation is done on the curve from the private key.", - "WeakPublicKey" : "The vector contains a weak public key. The curve is not a named curve, the public key point has order 3 and has been chosen to be on the same curve as the private key. This test vector is used to check ECC implementations for missing steps in the verification of the public key.", - "WrongOrder" : "The order of the public key has been modified. If this order is used in a cryptographic primitive instead of the correct order then private keys may leak. E.g. ECDHC in BC 1.52 suffered from this." - }, - "schema" : "ecdh_test_schema.json", - "testGroups" : [ - { - "curve" : "secp256k1", - "encoding" : "asn", - "type" : "EcdhTest", - "tests" : [ - { - "tcId" : 1, - "comment" : "normal case", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b396812ea1686e7472e9692eaf3e958e50e9500d3b4c77243db1f2acd67ba9cc4", - "private" : "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", - "shared" : "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 2, - "comment" : "compressed public key", - "public" : "3036301006072a8648ce3d020106052b8104000a03220002d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b", - "private" : "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", - "shared" : "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", - "result" : "acceptable", - "flags" : [ - "CompressedPoint" - ] - }, - { - "tcId" : 3, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004965ff42d654e058ee7317cced7caf093fbb180d8d3a74b0dcd9d8cd47a39d5cb9c2aa4daac01a4be37c20467ede964662f12983e0b5272a47a5f2785685d8087", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "0000000000000000000000000000000000000000000000000000000000000001", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 4, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000406c4b87ba76c6dcb101f54a050a086aa2cb0722f03137df5a922472f1bdc11b982e3c735c4b6c481d09269559f080ad08632f370a054af12c1fd1eced2ea9211", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "0000000000000000000000000000000000000000000000000000000000000002", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 5, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bba30eef7967a2f2f08a2ffadac0e41fd4db12a93cef0b045b5706f2853821e6d50b2bf8cbf530e619869e07c021ef16f693cfc0a4b0d4ed5a8f464692bf3d6e", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "0000000000000000000000000000000000000000000000000000000000000003", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 6, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004166aed3bc281705444f933913f670957a118f8da2c71bd301a90929743e2ca583514a7972e33d6fea1e377ef4184937f67b37e41ef3099c228a88f5bfb67e5b9", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "00000000000000000000000000000000ffffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 7, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000436e1e76ffdbe8577520b0716eb88c18ea72a49e5a4e5680a7d290093f841cb6e7310728b59c7572c4b35fb6c29c36ebabfc53553c06ecf747fcfbefcf6114e1c", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 8, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004728e15d578212bc42287c0118c82c84b126f97d549223c10ad07f4e98af912385d23b1a6e716925855a247b16effe92773315241ac951cdfefdfac0ed16467f6", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 9, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ca03ff8e99e269576cf7564545c89268eb415ff45778732529fa5997cc2b230950d6b84b729bc07f9b2d92754281cdc0d289d2453385aef77e4bdc69bf155c5f", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "000003ffffff0000003ffffff0000003ffffff0000003ffffff0000004000000", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 10, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000451be66137e39bbf35a91c6db5ba6919ff471d885ca94462eaaa65b1eac366baa5910de70b6e09e97aa00621ef18f2801719b199b3e7769fdab2bd909b2f340d7", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00010002", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 11, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000423556564850c50fba51f1e64ef98378ef5c22feafa29499ca27600c473cace889d5679e917daa7f4c7899517d37826284f031de01a60bc813696414d04531a21", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 12, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ddbf807e22c56a19cf6c472829150350781034a5eddec365694d4bd5c865ead14e674127028c91d3394cac37293a866055d10f0f40a3706ad16b64fc9d5998bd", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 13, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004595e46ee7c2d7183ff2ea760ffd8472fb834ec89c08b6ef48ff92b44a13a6e1ae563e23953c97c26441323d2500c84e8cee04c15d4d5d2cc458703d1f2d02d31", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "7fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 14, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e426e2f5108333117587975f18d8cc078d41e56b7d6b82f585d75b0d73479ffd75800fd41236a56034bed9abc55d82cf059a14d63c07cd0750931714731a1ca1", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "8000000000000000000000000000000000000000000000000000000000000000", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 15, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e1c7076caf26010b1767f1a9c4156b5b4236368d5d90dece3441b734e8684ee6b3534c3c54e614e594dce6ca438b87c424c8e80f8fae226bbdf50e4906c13f6b", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "8000003ffffff0000007fffffe000000ffffffc000001ffffff8000004000001", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 16, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004663cea1063c9916b75e85fc815d8a2370ec0a02aceef3db022e395db8b03bf3f188787f4047dc106807526502c7ae880e471c929b92e2384489c8070b5bcc109", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "ff00000001fffffffc00000007fffffff00000001fffffffc000000080000000", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 17, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000424175c078e305d3139e5dab727a6ab8587b26daa470a529a23c10585cb56c038bf1f2b937ae074ff94b15f5cb5e60eb5d32afba2077539db794294bcaab71a81", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 18, - "comment" : "edge case for shared secret", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004008d71c712dd95881cd1400dbe7683acbd8e269d25261b08f1f491b45e3b5621778182a24198b0f23502d06e24c45122e1f420af48dc1e17b1ea923386a33062", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "ffffffff00000000000000ffffffffffffff0000000000000100000000000000", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 19, - "comment" : "y-coordinate of the public key has many trailing 1's", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000456baf1d72606c7af5a5fa108620b0839e2c7dd40b832ef847e5b64c86efe1aa563e586a667a65bbb5692500df1ff8403736838b30ea9791d9d390e3dc6689e2c", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 20, - "comment" : "y-coordinate of the public key is small", - "public" : "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa05a5e4af11cf63ceaaa42a6dc9e4ccb394852cf84284e8d2627572fbf22c0ba88", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 21, - "comment" : "y-coordinate of the public key is small", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a48307eb78d38770fea1a44f4da72c26f85b17f3501a4f9394fe29856ccbf15fd284", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 22, - "comment" : "y-coordinate of the public key is large", - "public" : "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa0a5a1b50ee309c31555bd592361b334c6b7ad307bd7b172d9d8a8d03fdd3f41a7", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 23, - "comment" : "y-coordinate of the public key is large", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a483f814872c788f015e5bb0b258d3d907a4e80cafe5b06c6b01d67a93330ea029ab", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 24, - "comment" : "y-coordinate of the public key has many trailing 0's", - "public" : "3056301006072a8648ce3d020106052b8104000a034200045450cace04386adc54a14350793e83bdc5f265d6c29287ecd07f791ad2784c4cebd3c24451322334d8d51033e9d34b6bb592b1995d07867863d1044bd59d7501", - "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", - "shared" : "80000000000000000000000001126b54ffffffffffffffffffffffffffffffff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 25, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "12c2ad36a59fda5ac4f7e97ff611728d0748ac359fca9b12f6d4f43519516487", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 26, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "45aa9666757815e9974140d1b57191c92c588f6e5681131e0df9b3d241831ad4", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 27, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "b90964c05e464c23acb747a4c83511e93007f7499b065c8e8eccec955d8731f4", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 28, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000ffffffffffffffffffffffffffffffff3db772ad92db8699ceac1a3c30e126b866c4fefe292cf0c1790e55cee8414f18", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "8163c9dce8356f1df72b698f2f04a14db0263a8402905eee87941b00d8d677f5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 29, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000ffffffffffffffff0000000000000000ffffffffffffffff31cf13671b574e313c35217566f18bd2c5f758c140d24e94e6a4fda7f4c7b12b", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "1a32749dcf047a7e06194ccb34d7c9538a16ddabeeede74bea5f7ef04979f7f7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 30, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff73b0886496aed70db371e2e49db640abba547e5e0c2763b73a0a42f84348a6b1", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "ab43917a64c1b010159643c18e2eb06d25eedae5b78d02fa9b3debacbf31b777", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 31, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004000003ffffff0000003ffffff0000003ffffff0000003ffffff00000040000000f4d81575c8e328285633ccfd8623f04dd4ed61e187b3a6d7eac553aede7f850", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "1648321c706651adf06643fc4ae06041dce64a82632ad44128061216cc9827ff", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 32, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0001000242217b7059b3ddebc68e95443f6c109369e1f9323dd24852ac7612996b6e5601", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "fb866b2e4b1f9ed6b37847fc80a19a52e1e91b75d713b0d4f6b995d2d3c75cfe", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 33, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f75f450dbbf718a4f6582d7af83953170b3037fb81a450a5ca5acbec74ad6cac89", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "1908ae936f53b9a8a2d09707ae414084090b175365401425479b10b8c3e8d1ba", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 34, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200044218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee37269a64bbcf3a3f227631c7a8ce532c77245a1c0db4343f16aa1d339fd2591a", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "5e13b3dc04e33f18d1286c606cb0191785f694e82e17796145c9e7b49bc2af58", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 35, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200047fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff4b66003c7482d0f2fd7b1cb2b0b7078cd199f2208fc37eb2ef286ccb2f1224e7", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "3135a6283b97e7537a8bc208a355c2a854b8ee6e4227206730e6d725da044dee", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 36, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004800000000000000000000000000000000000000000000000000000000000000069d3cd0c70f1484d4b3bbbd680679ef477a22a07df085634f117c41c08bf1230", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "62959089a7ed477c22cb4f1c7787327318fccca25e5aa3e44688a282931ab049", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 37, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048000003ffffff0000007fffffe000000ffffffc000001ffffff800000400000130f69b6e95a3303214a73ad982a1f3ee169d7ecf958de7b0bca8a9ffa3b8e8b3", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "04fda5c00a396fad6b809a8843de573e86b0403d644995c83313da51fb1f5880", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 38, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff00000001fffffffc00000007fffffff00000001fffffffc00000008000000056951ead861aa8ec7a314fcd54f905bd92c910786375eb7ee5f3a55f8aa87884", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "bbd9937bb51d27f94ecaea29717df789afeac4414e3ef27bb2e6fa7259182e59", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 39, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff63a88b2e0c8987c6310cf81d0c935f00213f98a3dad2f43c8128fa313a90d55b", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "bbd9d305b99ff3db56f77fea9e89f32260ee7326040067ce05dd15e0dcc13ed8", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 40, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000000000ffffffffffffff000000000000010000000000000066a4456ca6d4054d13b209f6d262e6057ad712566f46e9e238e894deebe3d3aa", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "4ffb2c7962e32d5365f98f66be6286724d40d5f0333ba4fc943c0f0f06cdbb1f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 41, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff07ed353c9f1039edcc9cc5336c034dc131a4087692c2e56bc1dd1904e3ffffff", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "7c07b199b6a62e7ac646c7e1dee94aca55de1a97251ddf92fcd4fe0145b40f12", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 42, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037effffffffffffffffffffffffffffffff0000031a6bf344b86730ac5c54a7751aefdba135759b9d535ca64111f298a38d", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 43, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037efffffffffffffffffffffffffffffffffffffce5940cbb4798cf53a3ab588ae510245eca8a6462aca359beed0d6758a2", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 44, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000001126b54ffffffffffffffffffffffffffffffff4106a369068d454ea4b9c3ac6177f87fc8fd3aa240b2ccb4882bdccbd4000000", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "e59ddc7646e4aef0623c71c486f24d5d32f7257ef3dab8fa524b394eae19ebe1", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 45, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff0000013bc6f08431e729ed2863f2f4ac8a30279695c8109c340a39fa86f451cd", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 46, - "comment" : "edge cases for ephemeral key", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0fffffffffffffffffffffffffffffffffffffec4390f7bce18d612d79c0d0b5375cfd8696a37ef63cbf5c604790baa62", - "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", - "shared" : "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 47, - "comment" : "point with coordinate x = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "f362289d3a803d568a0a42767070d793bd70891fb5e03b01413b6d3f1eb52ff8", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 48, - "comment" : "point with coordinate x = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000422b961ed14f6368903feeb42d63d37bd11302893e8ff64c1a8e7fd0731439bb6981a712063bfba34d177412bb284c4361953decf29bbde0185a58bd02f3be430", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "bae229e6d001fd47741aeee860048a855432076fe270f632f46d1301022b6452", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 49, - "comment" : "point with coordinate x = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042f9245bac6fa959b4f02773e21411f48b74f9806fe4d32e36bdf9ab02814f3535745da334d06bafe2d83c235f0c7a29f8f042722ec34e53aa96d97a331a733ef", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "e90b9e81bd013d349f70fde1b51bad04c581011c68f0c2053ac91dc8187abb9a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 50, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200041e396a2525bc3fb00af898b06bb87c1d674fc0662b867ffac08eb0dba2146c21a8b8429f11803649be34ae515c173a43ba74f13ebbd0e261011c162e573599b4", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "de7cde6b5806a325da845e9a191e18377868636e5ef1f5fa08e756c02d6fd4de", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 51, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004452158303b37ff9bebca720ea1085efaa4f859db950a99fccd9d2d179273abb108a9083f8075005943bd68c566ec1f2f067664da9212ec1833799bba881d8e8b", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "96328fa84038a63c817ef7cd13b79794a2db467dd3bd8769df782adace3c82eb", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 52, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200045a2a401666e0f1978c6f30aec53fee58b4c4f75e7c1a00156a36ad27c0a5a295658577e657223b8c20c826243b5ae2ca0f6148c2529ec6d60ec260916641d8fa", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "b6699fe9a18c2d0d14e95405133e000b167dc2e5451dcdf09ade49ba0db213eb", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 53, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004b2cd039500bcf460e24fd80383b60eb81a56f467077e768231553a0fa0dafcc81d4a1b8fd88b3b23f2d503285c9d72bba448c15bc016c620f707599a129546ae", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "7a23aee5b0fed16638f0e2eb05fba1fd44167d496ebeb274db218593b4ea201c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 54, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000403cf500d838c9fcb97d8ddba2466ec6e474498315d6c2a43110308f22459d49b07875aaed2edabed842fb1608ca706bd39d6021a60bc270947c12053c9dbafa1", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "d8aef4c5c8b60886d7f33cdd2390c21311e69f606dc777dc41c43a461995c315", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 55, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040b6f2cb62954f994564e1419cf9d5982ec6511e7fa7e17f9685e019949906df2fb429b0554a25a4a0c510270d3cc73e6cfec9bc2e63cbd2b7aa0db98e1f330cd", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "4c0892bacd983ec0013f477d94d8fb850585eff2197b53d566a9926bd898d948", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 56, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200043025b046f4a70e06330f3b14c4fa3ec1e04fe19ed8c90352dc6ff5627ca7b3b3a264d5ad9f06d8487430f654f7dd8f6735fc836ef48d6d4d4996a9c20af320ee", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "6e2119935a5c2521182a701d5a13215a7dfb8a1f001b3887e8ae51bf259b180b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 57, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200047d3b8428c80299a4ff1d96ed75a5a44629fd0313c097c478e55f2fa0ae45b691bb4963b5cc095abe5dcfe98399317fd5ad59f3674c07063a9123a2aa24814585", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "2b8b0d4eee83d1c4b1f2a67144fef78e7faa86e6d5d6a8b72b359c4f373adb71", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 58, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fb77841884d30fa5b73ad21d0a5ae40c53a9faa5d325699436338cee4ba213697bd732d47c86dcd63691097b1999c9f0a660a9c3d613671039cf1763467d8140", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "58dbf6ad5e791956e8635427252cf5e518bd10ed2a936a1f3747ba4ea7983274", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 59, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200049aef51383a556cf317fe68bea6a85a254825ec5b3f1358aea209a43ca38c66351aee1a91aeb2a4dcad739722f44c437dfd32731f0862dd751b80bd88d0969bd6", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "123b494058dec32fb74fdeb1aa9a4d52bfddf2d90b9b46edbcf4cc95ea736251", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 60, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042769df335132f2025e64104804678737860ee66e07e675f720e7d4ef5c38a2c281f80c3b6d47db0a412e6edd3c5bf48accac1497b59e13b15dfc2cd15e6ae47a", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "af4b79efc450630b8c027697e2376f14842babad81bd68592c37279a9fc41ab6", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 61, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000461b8c48750735a6b5cc45b691906e5cc292d5969bb1d6ff90ff446d94811ce7c2853977419cba2b92cc574abce030473eb008350566d7eaa24cb9daad70710ed", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "08b4326b42d817e2f8bc09f26f49b720afcede10236d0a25e7e9518eac96e3bd", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 62, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000416eeabc802e3409b7c7b3e7607b7166243fc1746294948fc8123b399cfb89962fcbf0bf8a5191ce958dd5ea3ab633c090d1259fbd9a977fde0cc212d5b3b9858", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "52505bfea9d066f0aa9008e8382382c7d48460d76f2962e509482b6eb56e0ac5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 63, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000463b1d99491b46cee7e186a243bce1cc386297571850a10d9a2962d769a411c616345e28532cac39960a2f12bbd03205b77464a80a0416446e6ff85851a009f64", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "1e6464f78fbedecd821a4fa04d7e8f1364d324be24d12212994683fc2b6bb1a2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 64, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000475c78ae9c94613dd051eed7dd7df66a081cd0ac27cf65e4ef0ea826276c5efcfa92ed1c4ffbb84301f5bb1c6bc9e14c6e6dad1e04a287826528478f9ae1609c2", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "b4fcb72d1f81db211dd94039a1368c2c4effd1efe832f1a1db2dae5253c27303", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 65, - "comment" : "point with coordinate x = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004072838e4f972d4a65d258dbc32a530fde2e873537b5a4aa707cf81cecc0f7ff12e4b608b9e321c9db72cf4d9ba4b3c2c13756040d77af6bd251bc24cf18676f1", - "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", - "shared" : "f4f4926b6f64e47abeadbdc5a8a67706a42e00774e1cc5afda7d57ced6423b39", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 66, - "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200044301f54b3592d1ea2a40989c94261d2b1d1fe297ed6ed64125ee241de05d004bc79014f156e9b7bfb36b8ad2d66d55f3a753829a9ddb86055bb9166dd3aff457", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "fdc15a26abbade3416e1201a6d737128a2f897f0d88108645453a1b3ddd05688", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 67, - "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000436b0f66bf5f9fd4b2df9cdae2af873a075c55497d7fec4737a7c9643c2c76fe5da9f7287b3cd4e5f05b9a1a4f64e8a8d96c316e452594d02a4592a2107ece90b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "e36348e3a464bc518384806c548e156edd994cb6946473c265a24914d5559f1c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 68, - "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000482abb58afb62d261878bdee12664df1499b824f1d60fb02811642cb02f4aff5d30719835d96f32dc03c49d815ffa21285733137f507ce316cec65ca562ce2ad0", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "7d65684bdce4ac95db002fba350dc89d0d0fc9e12260d01868543f2a6c8c5b8d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 69, - "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200047de7b7cf5c5ff4240daf31a50ac6cf6b169aad07d2c5936c73b83ee3987e22a1940c1bd78e4be6692585c99dc92b47671e2ccbcf12a9a9854c6607f98213c108", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "6ec6ba2374ab0a9ae663f3f73671158aaabac3ac689d6c2702ebdf4186597a85", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 70, - "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000406fa93527294c8533aa401ce4e6c8aeb05a6921bc48798a8e20a0f84a5085af4ec4828f8394d22de43043117b8595fb113245f7285cb35439389e8547a105039", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "6d6e87787d0a947ecfbf7962142fde8ff9b590e472c0c46bbc5d39020e4f78a7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 71, - "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048a4f625210b448dc846ad2399b31cd1bc3f1788c7bed69cc1cb7aac8ab28d5393007c6f11f3e248de651c6622de308ee5576be84ef1ed8ed91fd244f14fc2053", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "56ea4382f8e1abfcb211989f500676449abcebfe2cd2204dd8923deb530a6c7b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 72, - "comment" : "point with coordinate x = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004885e452cbb0e4b2a9768b7596c153198a922dabbb8d0ca1dc3faf4f097f09113be9aaa630918d5056053ecf7388f448b912d9ccfbed80d7ca23c0e7991a34901", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "2c362c27b3107ea8a042c05cc50c4a8ddaae8cdc33d058492951a03f8d8f8194", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 73, - "comment" : "point with coordinate x = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e226df1fcf7c137a41c920ff74d6204faa2093eeffc4a9ee0a23fb2e994041c3457107442cc4b3af631c4dfb5f53e2c5608bed04ff6653b771f7cd4670f81034", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "0188da289ce8974a4f44520960fae8b353750aca789272e9f90d1215bacdd870", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 74, - "comment" : "point with coordinate x = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004f53ead9575eebba3b0eb0d033acb7e99388e8590b4ad2db5ea4f6bd9bde16995b5f3ab15f973ca9e3aa9dfe2914eebbd2e11010b455513907908800396fb9d1a", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "f78bd7ff899c81b866be17c0a94bec592838d78d1f0c0cf532829b6c464c28ac", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 75, - "comment" : "point with coordinate x = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004882773ec7e10605c8f9e2e3b8700943be26bcc4c9d1fedf2bdcfb36994f23c7f8e5d05b2fdd2954b6188736ebe3f5646602a58d978b716b5304ea56777691db3", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "99f6151fba28067eac73354920fcc1fa17fea63225a583323cb6c3d4054ecaca", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 76, - "comment" : "point with coordinate x = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004a60b6458256b38d4644451b490bd357feade7bb6b8453c1fc89794d5a45f768d81eee90548a59e5d2cecd72d4b0b5e6574d65a9d837c7c590d1d125ee37c4d51", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "68ca39de0cec2297529f56876bc3de7be370f300e87c2b09cdbb5120382d6977", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 77, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "af306c993dee0dcfc441ebe53360b569e21f186052db8197f4a124fa77b98148", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 78, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000424800deac3fe4c765b6dec80ea299d771ada4f30e4e156b3acb720dba37394715fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "aa7fc9fe60445eac2451ec24c1a44909842fa14025f2a1d3dd7f31019f962be5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 79, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048f33652f5bda2c32953ebf2d2eca95e05b17c8ab7d99601bee445df844d46a369cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "082a43a8417782a795c8d4c70f43edcabbc245a8820ac01be90c1acf0343ba91", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 80, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004146d3b65add9f54ccca28533c88e2cbc63f7443e1658783ab41f8ef97c2a10b50000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "70810b4780a63c860427d3a0269f6c9d3c2ea33494c50e58a20b9480034bc7a0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 81, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004b0344418a4504c07e7921ed9f00714b5d390e5cb5e793bb1465f73174f6c26fe5fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "a7d34ee25fbb354f8638d31850dab41e4b086886f7ed3f2d6e035bceb8cab8a0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 82, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048a98c1bc6be75c5796be4b29dd885c3485e75e37b4ccac9b37251e67175ff0d69cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "3f09cbc12ed1701f59dd5aa83daef5e6676adf7fd235c53f69aeb5d5b67799e0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 83, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a034200041fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff5070000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "e04e881f416bb5aa3796407aa5ffddf8e1b2446b185f700f6953468384faaf76", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 84, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042b4badfc97b16781bcfff4a525cf4dd31194cb03bca56d9b0ce96c0c0d2040c05fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "adace71f40006c04557540c2ed8102d830c7f638e2201efeb47d732da79f13d9", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 85, - "comment" : "point with coordinate y = 1", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e633d914383e7775d402f5a8f3ad0deb1f00d91ccd99f348da96839ea3cb9d529cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "b8cbf0968fb70d391059d090b30d1c4edcd2dad7abbf7aa4ad452f5a4644a7be", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 86, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1c1b509c9ddb76221a066a22a3c333fee5e1d2d1a4babde4a1d33ec247a7ea30162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "07257245da4bc26696e245531c7a97c2b529f1ca2d8c051626520e6b83d7faf2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 87, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004755d8845e7b4fd270353f6999e97242224015527bf3f94cc2c693d1b6ba12298604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "d6aa401b9ce17ecf7dd7b0861dfeb36bb1749d12533991e66c0d942281ae13ab", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 88, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004c6f9fc8644ba5c9ea9beb12ce2cb911c5487e8b1be91d5a168318f4ae44d66807bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "f43bfe4eccc24ebf6e36c5bcaca47b770c17bcb59ea788b15c74ae6c9dd055a1", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 89, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004d3179fce5781d0c49ce8480a811f6f08e3f123d9f6010fbf619b5d868a8ea833ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "009bc3abb3cf0aca214f0e8db5088d520b3d4aadb1d44c4a2be7f031461c9420", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 90, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200049e098095463c91ac7107a920ccb276d45e1f7240ef2b93b957ee09393d32e001503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "8bcb07a3d0fa82af60c88a8d67810ebca0ea27548384e96d3483310212219312", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 91, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf3034a9935182da362570315011544ac2ce8a9c22777c2fc767ac9c5c0daeebcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "a09ddc7cfe023acd9571ef0754010289c804678c043f900f2691dd801b942ed4", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 92, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004709c7179c2bb27ce3985ba42feb870f069dacead9294c80557be882fb57790481e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "da98054d51ac9615e9d4f5ceda1f1bad40302ac11603431efec13ab50e32fcf2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 93, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004264c00a2d92514a6dbe655de3c71a5740cec4fcb251aa48ca6745dbea6f5f7cfc1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "d60795d8f310b155726534b8be3d0b8a7bc2ced468c6e64c8b9ae087b33ee00b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 94, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004a12124606bcbbb33cecec7fc8d78b3897192ca851560c539e47dd276c63bd3c2f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "675fef8f5680bf76220e91362613944099046b0ba07e5824e93f3e3cc2cc2758", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 95, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004244b7afe7f31289f9d6aaeb7f70d29a7b49a228c7bb202764aba94daaaa3332270c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "76b439f8ea7b42f11cd59e6d91b2d2a72577c185386b6af6639be8e3864a7f27", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 96, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042ac29db2ebc4fa9473b42bd335a60226579cc186b2c676a3b01bc60e589616165aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "56e63fa788121d5efa0ce3caf4605af18d48c631496cdfa862c43ecf5e5fc127", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 97, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e62aee5205a8063e3ae401d53e9343001e55eb5f4e4d6b70e2b84159cf3157e64ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "cff3b5e19ed67e5111dd76e310a1f11d7f99a93fbe9cc5c6f3384086cacd1142", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 98, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000431dce6de741f10267f2e8f3d572a4f49be5fe52ff7bff3c3b4646f38076c06752702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "e29483884a74fb84f4601654885a0f574691394f064ea6937a846175ef081fc5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 99, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200046518cd66b1d841e689d5dc6674c7cc7d964574d1490fff7906bd373494791599104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9c6a4bcb2fc086aca8726d850fa79920214af4c151acea0fcf12a769ad1f3574", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 100, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004952a88ce31ad4cb086978e6c5621c3d8023b2c11418d6fd0dcef8de72123efc15d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "34b7abc3f3e36e37e2d5728a870a293a16403146ca67ff91cbabeee2bb2e038b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 101, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042a43f33573b619719099cf54f6cccb28d16df3992239fadf79c7acb9c64f7af0f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9bd1284f1bcb1934d483834cae41a77db28cd9553869384755b6983f4f3848a0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 102, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200041b1b0c75408785e84727b0e55e4ba20d0f2599c4ed08482dc1f3b5df545691380162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "167e3db6a912ac6117644525911fc8872ed33b8e0bbd50073dd3c17a744e61e0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 103, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200044dd1283bccd36cc3402f3a81e2e9b0d6a2b2b1debbbd44ffc1f179bd49cf0a7e604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "7c3020e279cb5af14184b4653cc87c1ddd7f49cd31cd371ae813681dd6617d0e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 104, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004a499dbf732e438be0eb084b9e6ad879dd7a2904bbb004b40027969a171f2d4267bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "acfdff566b8b55318869fa646f789f8036d40b90f0fc520ae2a5a27544f962c0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 105, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004adcf0ffba9cb6ef0c8031c4291a434b18d78f42e45e62ba01fbe91f9273f0ad1ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "5c6b01cff4e6ce81a630238b5db3662e77fb88bffdde61443a7d8554ba001ef2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 106, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000421712725d9806acf54d3a6c82bf93c0fe249268ca9f42eceac19e93a5eab8056503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "e7281d12b74b06eecb273ec3e0d8fe663e9ec1d5a50c2b6c68ec8b3693f23c4c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 107, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200041e02176824bd31eabdce03a9403c7d3c2ac631f9b0e88d9a924701c1b2f29b85cf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "80643ed8b9052a2e746a26d9178fe2ccff35edbb81f60cd78004fb8d5f143aae", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 108, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000463e7a1af36d6b540a49276aac3fec9cb45ed6bab167c06b0419a77b91399f6181e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "75873ac544ad69d3ddc5c9cffe384d275e9da2949d6982da4b990f8bf2b76474", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 109, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200041e265ab5b7f7199470e532653d2a7b9a8b728970b838137c9692ed0692897b2ac1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "355c9faca29cf7cc968853ee29ffe62d1127fcc1dc57e9ddaf0e0f447146064e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 110, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000454d2a4394c109fcbd3cb9886fec3add51ba4d2e44e1d5676e4b98f0c13655fc5f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "fc175a5ef18595b69e45be2cda8ae00d9c8bdbefbcf7f692f91cefdc560e4722", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 111, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000493f1459207fb09c6f0a88c398ac80d1052a4cd33e7eef5687da99ab97c6024b770c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "46559146a93aae904dbcaaaa07e6cd1bb450f1b37c83929a994b45792333d5f6", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 112, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200041fa049a1892b679857c6dff08af19db70cbc99b6f2d7bc51a341fe79d1647f4a5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "c64b07119054a37961c0a177158256081b38b0087b307e0cad7e30d790ceb0ce", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 113, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000484e0b192d60abf531e828e887d366d869e1033a16e9c7f1167458c8134c10fba4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "bea8cfc0bee8571ccf0c525654ef26d1fc782bb22deccf67ea4ea0803dc15daf", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 114, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042f9707c67118724111efbbbbf06b623ab2ffd9259ddc354fcaaf81ba01f6fa7b2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "60451da4adfe5bb393109069efdc84415ec8a2c429955cbf22a4340f8fc48936", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 115, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ac1fbbe42293a9f9ae104ee2da0b0a9b3464d5d8b1e854df19d3c4456af8f9a6104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "d68e746f3d43feac5fd4898de943dc38205af7e2631ed732079bbfc8ab52511c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 116, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bae10cf93ff7b72d6ed98519602e9f03aa40303fa0674fb3ddee7d2db1c92bb25d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "28daeaadc609386d770dff4c7120b2a87cab3e21fdb8a6e4dc1240a51d12e55c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 117, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004edb4288cf5567673d50a1cd9e6bea45317823f30383f60d9bc3b9ee42ac29871f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "bb4110b734c8ef8a08bb6011acb35cbda9ae8e2ef6c4d0862576a68792667bb9", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 118, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000413233e80f59ac2b59737e87877782ab3027c490df8ac0bf3f3ef1633872eec540162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "e25c50037ca1913851b9758752659fb61c02d2a7c6b6aae29bda301907d99f5d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 119, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200043cd14f7e4b779615bc7ccee47e7f2b07394bf8f98503263411a549264a8fcf19604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "ad259f01e953263f40a39b14a538d076710c19207af936feabdf03bda7f067a5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 120, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004946c278288616aa34790ca193686e745d3d58702866ddf1e95550711a9bfbdb87bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "5ec6025ac7b25c0f095f3fdee3e2e508bd1437b9705c2543c0e5af1c1d363ffd", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 121, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200047f195035feb2c04a9b149bb2ed3c5c458e95e7f7c418c4a07ea6107e4e32455addf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "a2f93a84574a26b43880cde6ed440c7f7cc72c92504d5271999a8a78ffe3491d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 122, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000440855844e04303843a24b01707544d1bbf97673266e03d77fbf80d8b64219bd8503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "8d0cdb4977ba7661d41036aeb7a5f2dd207716d5d76eeb26629043c559ec2900", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 123, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000422cdb3ee47f14b3b0c0c8c256fb22e79126b436a2c9ff635a65151a0f0ffb1bfcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "defde4aa48f89b03f623ea1f946f1aa938c5aab879ca6319596926f085578edc", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 124, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042b7becd7066e22f121e7cf123d48c5445037c5a756ef314a66a7001636ee75cf1e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "afe0bfed69a600163865406127a8972b613232aa4c933a06b5a5b5bcff1596f8", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 125, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bb8da4a76ee3d1c4b33477bc8663def167a126c422ad47f6c2f8b539c6808936c1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "f49bca7a6a5256ddf712775917c30e4873153469bae12fd5c5571031db7b1205", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 126, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040a0c37664823a5005d659f7c73c39ea172c862969c81e44f36c89e7c265ec8a8f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9c88b611b7f9aad33fabb09cff618bb1ca6fb904a289b1481da3d1e4e72589e4", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 127, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000447c33f6f78d3cd9971ecc50e7e2ac947f8c1103f9c5f0821379bd06ad8fca45670c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "42f634c06c4a0e7e956db6e86666603d26374cc74b11026f0318d1a25681a712", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 128, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004b59d18ab8b0f9dd33484f43c3f6860229ba6a4c25a61cd0aaca23b76d60566cf5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "e2ceb946e7993f27a4327abdf61d4f06577e89c63b62a24aefbd905710d18669", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 129, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000494f4601b244d3a6ea6996fa244364f794399e0ff4316157db6023222fc0d90be4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "71637a5da2412a921f1636c69a6ee81083ee2b0e13766ad122791ef6f771896d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 130, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200049e8c115b1ac87d986ee1b506b86a4e7b8ea041aa6a63d6ec80ec0f0cf69cfb3f2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "bd265ed3078ca8c7788f594187c96c675aa623ecd01bfcad62d76a7881334f63", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 131, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004eec776b52b94141fc819d4b6b12d28e73555b5560507aba7df6f0484008de91f104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "8d073fc592fb7aa6f7b908ed07148aa7be5a135c4b343ebe295198cba78e71ce", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 132, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004aff46a388e5afc220a8eec7a49af9d245384a3af1e0b407b4521f4e92d12dceb5d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "a26d698e4613595aa61c8e2907d5241d6d14909737df59895841d07727bf1348", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 133, - "comment" : "point with coordinate y = 1 in left to right addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e807e43d96f3701a9a5c13d122749084170fcd36a586a446c9fcb4600eede4fdf4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "a8edc6f9af6bf74122c11ca1a50afbc4a3c4987bd0d1f73284d2c1371e613405", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 134, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004798868a56916d341e7d6f96359ae3658836e221459f4f7b7b63694de18a5e9247713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "17963de078996eb8503c7cc3e1a2d5147d7f0bfb251a020b4392033063587c8d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 135, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff419909d8a8ce0a9416051f4e256208c1dc035581a53312d566137e22104e9877421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "062799a19545d31b3ed72253bcde59762aa6104a88ac5e2fb68926b0f7146698", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 136, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200048b48119d7089d3b95cd2eaf8c85584fa8f5e56c4c4ccee7037d74cdbf88e571714c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9f42dd8fce13f8103b3b2bc15e61242e6820fe1325a20ef460fe64d9eb12b231", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 137, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e2888119379b5b2151bd788505def1d6bd786329431caf39705d9cbf96a42ea43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "d1b204e52d1fac6d504132c76ca233c87e377dcc79c893c970ddbb9f87b27fa0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 138, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200046dcc3971bd20913d59a91f20d912f56d07e7f014206bef4a653ddfe5d12842c39b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "c8d6bd28c1e65ae7c7a5debe67a7dfaf92b429ede368efc9da7d578a539b7054", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 139, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200047ebea45854569a1f7ea6b95b82d6befefbf6296ebc87c810b6cba93c0c1220b23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "0d1f905cc74720bde67ae84f582728588c75444c273dae4106fa20d1d6946430", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 140, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ceab5937900d34fa88378d371f4acaa7c6a2028b6143213413f16ba2dc7147877713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "3f014e309192588fa83e47d4ac9685d2041204e2eaf633a1312812e51ae74cbd", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 141, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004a4ffea5e25f75e4f689c81084a35c1220e8e6b914c482f4a2e8f93cffca6964777421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "68b404d556c82004c6c4bba4518ec00b1d4f1161cafe6c89aeb8494a9ba09db5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 142, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004de8809ea0ecce1d24a0431429510383a6f6e5a1c51cea32d830c6c353042603e14c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "c331ade7a457df7f12a2f5c43d7ea9486c1563b81cd8a0f23f923c1a9fa612e3", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 143, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004566209f174d6bf79720b70edb27e51350beeb2b0bcd083bbae7214f71cf824d43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "17b5c7a311eea9d2ab7571f8b9f848d4705997cf3eaf9bdcbe0e34a670f81f45", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 144, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004cc3181c0127137536ceec94fd45996657df72e0f97c44b9dad14763ce506e9dc9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "2f0e4eccbc4518ace558e06604f9bff4787f5b019437b52195ecb6b82191a6ae", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 145, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004d7052a1eeafc0e78d79e7f26003aa0a409287cf476007df28d281b142be1a0e23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "7494d864cb6ea9c5d982d40a5f103700d02dc982637753cfc7d8afe1beafff70", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 146, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004b7cc3e2306dbf7c38ff179658706feffb5efdb6044c7e71435d7ff7d0ae8c7b37713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "a96873eef5d438b807853b6771c6a5197e6eef21efefca538b45e9e981c032e5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 147, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200045bbe7c98015fd3a6034d79d867a4dcd52f95911932129da2fc0a58afe149137f77421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9124618913f20cdffa642207f192e67eb80ade53ac5535469abe90036d4af7e2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 148, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004962fe47880a94a745928e3c4a29a42cb01334f1ee9646e62451c46ecd72f410914c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9d8b74888d942870b221de7a642032892bc99e34bd8550195f6f5f097547334a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 149, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004c71574f5538de5653c37168d47a2bcf43698ea260012cd0ae1304e474c63a4e63bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "16983377c0f1a9c004495b3fd9658363116eea644787d059d1140fb907555d4a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 150, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004c60244ce306e376f3968178f5293742d7a20e1dc47cfc517edada9db49d0cbbf9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "081af40a81d48c6b530140db935e605bf4cc7b10885f5b148f95f1bc8ad2e52d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 151, - "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004aa3c3188c0ad5767a9bac77e7ceea05cfae1599ccd77b9fcbc0c3badc80c36ca3f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "7e4b973e6d4a357c400243a648c8a0a6a35cf231754afdef312d2f4b6abb988f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 152, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200042cce8ddfe4827dc030ddf38f998b3f2ed5e0621d0b3805666daf48c8c31e75e5198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "0f0235da2a06c8d408c27151f3f15342ed8c1945aaf84ed14993786d6ac5f570", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 153, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000414bfc3e5a46b69881a9a346d95894418614ed91476a1ddce48676b7cbab9ba02f334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "5622c2fbe8af5ad6cef72a01be186e554847576106f8979772fa56114d1160ab", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 154, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd442fa5a2a8d72e13e44fd2222c85a006f03375e0211b272f555052b03db750be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "bb95e0d0fbaad86c5bd87b95946c77ff1d65322a175ccf16419102c0a17f5a72", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 155, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040d7a3ff49bda6a587ed07691450425aa02d253ba573a16ad86c61af412dd3c770b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "4510683c7bfa251f0cb56bba7e0ab74d90f5e2ca01e91e7ca99312ccff2d90b6", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 156, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bdea5d2a3adde7df2e839ff63f62534b3f27cb191bb54dfa1d39cbff713ba9ed307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "025485142ca1ced752289f772130fc10c75a4508c46bffdef9290ad3e7baf9ca", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 157, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004d4c063e3c036f47c92f6f5470a26a835e1a24505b14d1b29279062a16cf6f489198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "9067932150724965aa479c1ef1be55544bed9fa94500a3b67887ed91ae3b81e5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 158, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a034200043cb9f07997756859e9b9a85b681fa50ee20357f535c1b311c4637d16b76b9ebff334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "f8084a89adccdc3aef89e5091a0f07d6160a66cb9575241100c1d39bf0549ae2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 159, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004793412ff636c08a2d0f6d60cc608e9a9098349a2501f91c95f692010bc1238b2be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "4462558c89902117051cb2c599ad66f00887b54cae3da9c04d317a5b2afb463b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 160, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd1eb0849e2e6a13d54b76518f11ba8775c2d7634d85152534bc7c3af4161efa0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "30b4741a64f87d28ec0029bd196b5a74555f2c9a976a46d628572474466a631d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 161, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004624b3b4ba993a8b938125689f6cf757392ee390d14a90fea6db944b5a8deb8d0307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "3afc04ac92117e50b0913b09dbbb4e6c780c051500201fad512b79080bff39e2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 162, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fe710e3c5b468dc33c2b17295c4e189b487d58dd437adf706ac05493cfea8df0198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "609637048586edc64cf5f28f1a505768c686471110070d783de499ffe6fe84da", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 163, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004ae864ba0c41f2e1dfbac2337025716d8bcadcef6539c6f1ff335176b8ddaa36ef334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "b1d4f27a6983c8ee417ef0f527d889d4a1ae41d3639244578c43d650c299fcd1", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 164, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004c987bd5af9eb202f1b24da2117ca90b6ef8c82e7cfbf530f71418f9a93b0085cbe345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "0007c9a27ac5067c9f0ad1a4d1e62110da1318893a658729713d82e333855b82", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 165, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000435670f86c5f72b93abe4131d2bea1fce876ad4e25b40d42d447d68cff90ca0be0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "8a3b23a91f0d5db8074a6a886889ee3e19aaf09b66ac9aad2e15c8bdba68085c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 166, - "comment" : "point with coordinate y = 1 in right to left addition chain", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004dfca678a1b8e6f67996a097fc9ce37412de9fbd9cfa1a21b750cef48e5e595a1307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", - "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", - "shared" : "c2af763f414cb2d7fd46257f0313b582c099b5e23b73e073b5ab7c230c45c883", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 167, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "03", - "shared" : "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 168, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "shared" : "5841acd3cff2d62861bbe11084738006d68ccf35acae615ee9524726e93d0da5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 169, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "0100000000000000000000000000000000000000000000000000000000000000", - "shared" : "4348e4cba371ead03982018abc9aacecaebfd636dda82e609fd298947f907de8", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 170, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "shared" : "e56221c2b0dc33b98b90dfd3239a2c0cb1e4ad0399a3aaef3f9d47fb103daef0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 171, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "008000000000000000000000000000000000000000000000000000000000000000", - "shared" : "5b34a29b1c4ddcb2101162d34bed9f0702361fe5af505df315eff7befd0e4719", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 172, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03abfd25e8cd0364141", - "shared" : "cece521b8b5a32bbee38936ba7d645824f238e561701a386fb888e010db54b2f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 173, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfc25e8cd0364141", - "shared" : "829521b79d71f5011e079756b851a0d5c83557866189a6258c1e78a1700c6904", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 174, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfca5e8cd0364141", - "shared" : "8c5934793505a6a1f84d41283341680c4923f1f4d562989a11cc626fea5eda5a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 175, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8bd0364141", - "shared" : "356caee7e7eee031a15e54c3a5c4e72f9c74bb287ce601619ef85eb96c289452", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 176, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c3", - "shared" : "09c7337df6c2b35edf3a21382511cc5add1a71a84cbf8d3396a5be548d92fa67", - "result" : "valid", - "flags" : [ - "AddSubChain" - ] - }, - { - "tcId" : 177, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364103", - "shared" : "d16caedd25793666f9e26f5331382106f54095b3d20d40c745b68ca76c0e6983", - "result" : "valid", - "flags" : [ - "AddSubChain" - ] - }, - { - "tcId" : 178, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364123", - "shared" : "b8ae1e21d8b34ce4caffed7167a26868ec80a7d4a6a98b639d4d05cd226504de", - "result" : "valid", - "flags" : [ - "AddSubChain" - ] - }, - { - "tcId" : 179, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133", - "shared" : "02776315fe147a36a4b0987492b6503acdea60f926450e5eddb9f88fc82178d3", - "result" : "valid", - "flags" : [ - "AddSubChain" - ] - }, - { - "tcId" : 180, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b", - "shared" : "3988c9c7050a28794934e5bd67629b556d97a4858d22812835f4a37dca351943", - "result" : "valid", - "flags" : [ - "AddSubChain" - ] - }, - { - "tcId" : 181, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", - "shared" : "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 182, - "comment" : "edge case private key", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", - "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f", - "shared" : "4b52257d8b3ba387797fdf7a752f195ddc4f7d76263de61d0d52a5ec14a36cbf", - "result" : "valid", - "flags" : [ - "AddSubChain" - ] - }, - { - "tcId" : 183, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 184, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 185, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 186, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 187, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 188, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 189, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 190, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 191, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000000", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 192, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 193, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 194, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 195, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 196, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 197, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 198, - "comment" : "point is not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 199, - "comment" : "", - "public" : "3015301006072a8648ce3d020106052b8104000a030100", - "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 200, - "comment" : "public point not on curve", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e4", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "", - "result" : "invalid", - "flags" : [ - "InvalidPublic" - ] - }, - { - "tcId" : 201, - "comment" : "public point = (0,0)", - "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "", - "result" : "invalid", - "flags" : [ - "InvalidPublic" - ] - }, - { - "tcId" : 202, - "comment" : "order = -115792089237316195423570985008687907852837564279074904382605163141518161494337", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80221ff000000000000000000000000000000014551231950b75fc4402da1732fc9bebf0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "invalid", - "flags" : [ - "WrongOrder", - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 203, - "comment" : "order = 0", - "public" : "3081d530818e06072a8648ce3d0201308182020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201000201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "invalid", - "flags" : [ - "WrongOrder", - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 204, - "comment" : "order = 1", - "public" : "3081d530818e06072a8648ce3d0201308182020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201010201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "WrongOrder", - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 205, - "comment" : "order = 26959946667150639794667015087019630673536463705607434823784316690060", - "public" : "3081f13081aa06072a8648ce3d020130819e020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8021d00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8c0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "WrongOrder", - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 206, - "comment" : "generator = (0,0)", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 207, - "comment" : "generator not on curve", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4ba022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 208, - "comment" : "cofactor = -1", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "invalid", - "flags" : [ - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 209, - "comment" : "cofactor = 0", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201000342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "invalid", - "flags" : [ - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 210, - "comment" : "cofactor = 2", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201020342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 211, - "comment" : "cofactor = 115792089237316195423570985008687907852837564279074904382605163141518161494337", - "public" : "308201153081ce06072a8648ce3d02013081c2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "invalid", - "flags" : [ - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 212, - "comment" : "cofactor = None", - "public" : "3081f23081ab06072a8648ce3d020130819f020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 213, - "comment" : "modified prime", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fb524ac7055bebf603a4e216abaa6a9ef8eb2bbea2cd820e59d46d8501f6268b30060401000401070441040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101034200040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "c5956b8cf7244e3c0457658a214210b358205cab12374d523ecf57895cecfeb0", - "result" : "invalid", - "flags" : [ - "ModifiedPrime", - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 214, - "comment" : "using secp224r1", - "public" : "304e301006072a8648ce3d020106052b81040021033a0004074f56dc2ea648ef89c3b72e23bbd2da36f60243e4d2067b70604af1c2165cec2f86603d60c8a611d5b84ba3d91dfe1a480825bcc4af3bcf", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "", - "result" : "invalid", - "flags" : [ - "InvalidPublic" - ] - }, - { - "tcId" : 215, - "comment" : "using secp256r1", - "public" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cbf6606595a3ee50f9fceaa2798c2740c82540516b4e5a7d361ff24e9dd15364e5408b2e679f9d5310d1f6893b36ce16b4a507509175fcb52aea53b781556b39", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "", - "result" : "invalid", - "flags" : [ - "InvalidPublic" - ] - }, - { - "tcId" : 216, - "comment" : "a = 0", - "public" : "3081f53081ae06072a8648ce3d02013081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", - "result" : "acceptable", - "flags" : [ - "UnusedParam", - "UnnamedCurve" - ] - }, - { - "tcId" : 217, - "comment" : "public key of order 3", - "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f30440420f7bbd87af04c58ea1f6716859e3c507bc72ad3a93d57faffe9aff7cdc465f2870420b04eafdeca79b407d9d8a0903b30b034f731b418c05103c458a8d66c028da80d0441043efb1f310572e6d5c1da03435af47290e3089ad6456d43ad89c8900ff5b8f43d1d476388e64341d8b269541478bac42c11d000c1f6ce82c0d363043b06c323de022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101034200043efb1f310572e6d5c1da03435af47290e3089ad6456d43ad89c8900ff5b8f43de2b89c7719bcbe274d96abeb87453bd3ee2fff3e09317d3f2c9cfbc3f93cd851", - "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", - "shared" : "", - "result" : "invalid", - "flags" : [ - "WeakPublicKey", - "InvalidPublic", - "UnnamedCurve" - ] - }, - { - "tcId" : 218, - "comment" : "Public key uses wrong curve: secp224r1", - "public" : "304e301006072a8648ce3d020106052b81040021033a000450eb062b54940a455719d523e1ec106525dda34c2fd95ace62b9b16d315d323f089173d10c45dceff155942431750c00ca36f463828e9fab", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 219, - "comment" : "Public key uses wrong curve: secp256r1", - "public" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000406372852584037722a7f9bfaad5661acb623162d45f70a552c617f4080e873aa43609275dff6dcaaa122a745d0f154681f9c7726867b43e7523b7f5ab5ea963e", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 220, - "comment" : "Public key uses wrong curve: secp384r1", - "public" : "3076301006072a8648ce3d020106052b81040022036200040ef5804731d918f037506ee00b8602b877c7d509ffa2c0847a86e7a2d358ba7c981c2a74b22401ac615307a6deb275402fa6c8218c3374f8a91752d2eff6bd14ad8cae596d2f37dae8aeec085760edf4fda9a7cf70253898a54183469072a561", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 221, - "comment" : "Public key uses wrong curve: secp521r1", - "public" : "30819b301006072a8648ce3d020106052b81040023038186000400921da57110db26c7838a69d574fc98588c5c07a792cb379f46664cc773c1e1f6fa16148667748ede232d1a1f1cea7f152c5d586172acbeaa48416bcbd70bb27f0f01b4477e1ae74bf4f093184a9f26f103712ccf6ceb45a0505b191606d897edaf872b37f0f90a933000a80fc3207048323c16883a3d67a90aa78bcc9c5e58d784b9b9", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 222, - "comment" : "Public key uses wrong curve: secp224k1", - "public" : "304e301006072a8648ce3d020106052b81040020033a000456dd09f8a8c19039286b6aa79d099ff3e35ff74400437d2072fd9faa7f2901db79d793f55268980f7d395055330a91b46bf4a62c3a528230", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 223, - "comment" : "Public key uses wrong curve: brainpoolP224r1", - "public" : "3052301406072a8648ce3d020106092b2403030208010105033a00042c9fdd1914cacdb28e39e6fc24b4c3c666cc0d438acc4529a6cc297a2d0fdecb3028d9e4d84c711db352379c080c78659969bdc5d3218901", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 224, - "comment" : "Public key uses wrong curve: brainpoolP256r1", - "public" : "305a301406072a8648ce3d020106092b240303020801010703420004120e4db849e5d960741c7d221aa80fe6e4fcd578191b7f845a68a6fcb8647719a6fffb6165d8ec39389eecc530839c321b2e9040027fba5d9cb9311df7cd3d4d", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 225, - "comment" : "Public key uses wrong curve: brainpoolP320r1", - "public" : "306a301406072a8648ce3d020106092b2403030208010109035200040efb1c104938f59a931fe6bf69f7ead4036d2336075a708e66b020e1bc5bb6d9cdc86d4e8fa181d7c7ea1af28353044e8cec12eec75a6dd87a5dc902024d93f8c8d9bf43b453fd919151f9bd7bb955c7", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 226, - "comment" : "Public key uses wrong curve: brainpoolP384r1", - "public" : "307a301406072a8648ce3d020106092b240303020801010b036200043e96d75b79214e69a4550e25375478bdc9c2a9d0178a77b5700bd5f12e3ce142f50c93dc1ee7268456d7eae2d44b718d6f159e896ae14fbe3aba397801a95e2bb6a9a761e865b289dd9db64aa07c794cedf77328543b94c9b54ce0cf04c60ac8", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 227, - "comment" : "Public key uses wrong curve: brainpoolP512r1", - "public" : "30819b301406072a8648ce3d020106092b240303020801010d03818200044f191130740f1b75ae13402960eb22ea801db80ed51a461e06a7b3ba60c9bddd132a6465bbee8afd70cfb4495efbda4f1567b958e6e305bfcb4ac8f05172688e0f2f175aa12425be3ab7271b42f258639e868677d1163c12e641229f1e6427761c9e294de51db564151b21a051d2f7a13661852799557a556a5f3c51d36d083a", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 228, - "comment" : "Public key uses wrong curve: brainpoolP224t1", - "public" : "3052301406072a8648ce3d020106092b2403030208010106033a00044964b948cefa39cd769e3480d4840a3c58e966161be80df02d9aab33b4a318a32f30130224edcefe0dd64342404e594aa334995b179f641f", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 229, - "comment" : "Public key uses wrong curve: brainpoolP256t1", - "public" : "305a301406072a8648ce3d020106092b24030302080101080342000411157979c08bcd175d34572209a85f3f5d602e35bdc3b553b0f19307672b31ba69d0556bce48c43e2e7e6177055221a4c4b7eb17ee9708f49216de76d6e92ab8", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 230, - "comment" : "Public key uses wrong curve: brainpoolP320t1", - "public" : "306a301406072a8648ce3d020106092b240303020801010a035200048bb517e198930eba57293419876a8793f711de37c27f200e6fb2c2b13e9fabd4fbc42ad61751ca583031ba76cbc6d745d115addc74eab63bf415c4fa20dbbecae98ac3c3da1a041705cf8959e2ccf453", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 231, - "comment" : "Public key uses wrong curve: brainpoolP384t1", - "public" : "307a301406072a8648ce3d020106092b240303020801010c036200045eb38d0261b744b03abef4ae7c17bc886b5b426bd910958f8a49ef62053048f869541b7a05d244315fc9cd74271ec3d518d94114b6006017f4ed5e3c06322baa1c75809a1057ba6fa46d1e1a9927a262e627940d5da538b5a3d1d794d9c866a4", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 232, - "comment" : "Public key uses wrong curve: brainpoolP512t1", - "public" : "30819b301406072a8648ce3d020106092b240303020801010e0381820004035fc238e57d980beae0215fb89108f9c6c4afda5d920f9d0583ee7d65f8778ecfff24a31d4f32deb6ea5f7e3adb6affb9327a5e62e09cba07c88b119fd104a83b7811e958e393971a5c9417412070b9f18b03be37e81e0bca5d3ff0873ed1f3113ed0fc57a0344321fb4d6c43f2f6e630a3d3883efe4c21df3e0f0b1208226b", - "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", - "shared" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 233, - "comment" : "invalid public key", - "public" : "3036301006072a8648ce3d020106052b8104000a03220002977cb7fb9a0ec5b208e811d6a0795eb78d7642e3cac42a801bcc8fc0f06472d4", - "private" : "00d09182a4d0c94ba85f82eff9fc1bddb0b07d3f2af8632fc1c73a3604e8f0b335", - "shared" : "", - "result" : "invalid", - "flags" : [ - "CompressedPoint" - ] - }, - { - "tcId" : 234, - "comment" : "public key is a low order point on twist", - "public" : "3036301006072a8648ce3d020106052b8104000a032200020000000000000000000000000000000000000000000000000000000000000000", - "private" : "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb300", - "shared" : "", - "result" : "invalid", - "flags" : [ - "CompressedPoint" - ] - }, - { - "tcId" : 235, - "comment" : "public key is a low order point on twist", - "public" : "3036301006072a8648ce3d020106052b8104000a032200030000000000000000000000000000000000000000000000000000000000000000", - "private" : "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb2ff", - "shared" : "", - "result" : "invalid", - "flags" : [ - "CompressedPoint" - ] - }, - { - "tcId" : 236, - "comment" : "long form encoding of length of sequence", - "public" : "308156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 237, - "comment" : "long form encoding of length of sequence", - "public" : "305730811006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 238, - "comment" : "length of sequence contains leading 0", - "public" : "30820056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 239, - "comment" : "length of sequence contains leading 0", - "public" : "30583082001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 240, - "comment" : "wrong length of sequence", - "public" : "3057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 241, - "comment" : "wrong length of sequence", - "public" : "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 242, - "comment" : "wrong length of sequence", - "public" : "3056301106072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 243, - "comment" : "wrong length of sequence", - "public" : "3056300f06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 244, - "comment" : "uint32 overflow in length of sequence", - "public" : "30850100000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 245, - "comment" : "uint32 overflow in length of sequence", - "public" : "305b3085010000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 246, - "comment" : "uint64 overflow in length of sequence", - "public" : "3089010000000000000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 247, - "comment" : "uint64 overflow in length of sequence", - "public" : "305f308901000000000000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 248, - "comment" : "length of sequence = 2**31 - 1", - "public" : "30847fffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 249, - "comment" : "length of sequence = 2**31 - 1", - "public" : "305a30847fffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 250, - "comment" : "length of sequence = 2**32 - 1", - "public" : "3084ffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 251, - "comment" : "length of sequence = 2**32 - 1", - "public" : "305a3084ffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 252, - "comment" : "length of sequence = 2**40 - 1", - "public" : "3085ffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 253, - "comment" : "length of sequence = 2**40 - 1", - "public" : "305b3085ffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 254, - "comment" : "length of sequence = 2**64 - 1", - "public" : "3088ffffffffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 255, - "comment" : "length of sequence = 2**64 - 1", - "public" : "305e3088ffffffffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 256, - "comment" : "incorrect length of sequence", - "public" : "30ff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 257, - "comment" : "incorrect length of sequence", - "public" : "305630ff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 258, - "comment" : "indefinite length without termination", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 259, - "comment" : "indefinite length without termination", - "public" : "3056308006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 260, - "comment" : "indefinite length without termination", - "public" : "3056301006802a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 261, - "comment" : "indefinite length without termination", - "public" : "3056301006072a8648ce3d020106802b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 262, - "comment" : "indefinite length without termination", - "public" : "3056301006072a8648ce3d020106052b8104000a03800004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 263, - "comment" : "removing sequence", - "public" : "", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 264, - "comment" : "removing sequence", - "public" : "304403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 265, - "comment" : "lonely sequence tag", - "public" : "30", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 266, - "comment" : "lonely sequence tag", - "public" : "30453003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 267, - "comment" : "appending 0's to sequence", - "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 268, - "comment" : "appending 0's to sequence", - "public" : "3058301206072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 269, - "comment" : "prepending 0's to sequence", - "public" : "30580000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 270, - "comment" : "prepending 0's to sequence", - "public" : "30583012000006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 271, - "comment" : "appending unused 0's to sequence", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 272, - "comment" : "appending unused 0's to sequence", - "public" : "3058301006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 273, - "comment" : "appending null value to sequence", - "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 274, - "comment" : "appending null value to sequence", - "public" : "3058301206072a8648ce3d020106052b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 275, - "comment" : "including garbage", - "public" : "305b4981773056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 276, - "comment" : "including garbage", - "public" : "305a25003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 277, - "comment" : "including garbage", - "public" : "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 278, - "comment" : "including garbage", - "public" : "305b3015498177301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 279, - "comment" : "including garbage", - "public" : "305a30142500301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 280, - "comment" : "including garbage", - "public" : "305e3012301006072a8648ce3d020106052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 281, - "comment" : "including garbage", - "public" : "305b3015260c49817706072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 282, - "comment" : "including garbage", - "public" : "305a3014260b250006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 283, - "comment" : "including garbage", - "public" : "305e3018260906072a8648ce3d02010004deadbeef06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 284, - "comment" : "including garbage", - "public" : "305b301506072a8648ce3d0201260a49817706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 285, - "comment" : "including garbage", - "public" : "305a301406072a8648ce3d02012609250006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 286, - "comment" : "including garbage", - "public" : "305e301806072a8648ce3d0201260706052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 287, - "comment" : "including garbage", - "public" : "305b301006072a8648ce3d020106052b8104000a234749817703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 288, - "comment" : "including garbage", - "public" : "305a301006072a8648ce3d020106052b8104000a2346250003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 289, - "comment" : "including garbage", - "public" : "305e301006072a8648ce3d020106052b8104000a234403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 290, - "comment" : "including undefined tags", - "public" : "305eaa00bb00cd003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 291, - "comment" : "including undefined tags", - "public" : "305caa02aabb3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 292, - "comment" : "including undefined tags", - "public" : "305e3018aa00bb00cd00301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 293, - "comment" : "including undefined tags", - "public" : "305c3016aa02aabb301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 294, - "comment" : "including undefined tags", - "public" : "305e3018260faa00bb00cd0006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 295, - "comment" : "including undefined tags", - "public" : "305c3016260daa02aabb06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 296, - "comment" : "including undefined tags", - "public" : "305e301806072a8648ce3d0201260daa00bb00cd0006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 297, - "comment" : "including undefined tags", - "public" : "305c301606072a8648ce3d0201260baa02aabb06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 298, - "comment" : "including undefined tags", - "public" : "305e301006072a8648ce3d020106052b8104000a234aaa00bb00cd0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 299, - "comment" : "including undefined tags", - "public" : "305c301006072a8648ce3d020106052b8104000a2348aa02aabb03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 300, - "comment" : "truncated length of sequence", - "public" : "3081", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 301, - "comment" : "truncated length of sequence", - "public" : "3046308103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 302, - "comment" : "Replacing sequence with NULL", - "public" : "0500", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 303, - "comment" : "Replacing sequence with NULL", - "public" : "3046050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 304, - "comment" : "changing tag value of sequence", - "public" : "2e56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 305, - "comment" : "changing tag value of sequence", - "public" : "2f56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 306, - "comment" : "changing tag value of sequence", - "public" : "3156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 307, - "comment" : "changing tag value of sequence", - "public" : "3256301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 308, - "comment" : "changing tag value of sequence", - "public" : "ff56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 309, - "comment" : "changing tag value of sequence", - "public" : "30562e1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 310, - "comment" : "changing tag value of sequence", - "public" : "30562f1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 311, - "comment" : "changing tag value of sequence", - "public" : "3056311006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 312, - "comment" : "changing tag value of sequence", - "public" : "3056321006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 313, - "comment" : "changing tag value of sequence", - "public" : "3056ff1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 314, - "comment" : "dropping value of sequence", - "public" : "3000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 315, - "comment" : "dropping value of sequence", - "public" : "3046300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 316, - "comment" : "truncated sequence", - "public" : "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 317, - "comment" : "truncated sequence", - "public" : "30551006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 318, - "comment" : "truncated sequence", - "public" : "3055300f06072a8648ce3d020106052b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 319, - "comment" : "truncated sequence", - "public" : "3055300f072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 320, - "comment" : "indefinite length", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 321, - "comment" : "indefinite length", - "public" : "3058308006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 322, - "comment" : "indefinite length with truncated delimiter", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326700", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 323, - "comment" : "indefinite length with truncated delimiter", - "public" : "3057308006072a8648ce3d020106052b8104000a0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 324, - "comment" : "indefinite length with additional element", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326705000000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 325, - "comment" : "indefinite length with additional element", - "public" : "305a308006072a8648ce3d020106052b8104000a0500000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 326, - "comment" : "indefinite length with truncated element", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267060811220000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 327, - "comment" : "indefinite length with truncated element", - "public" : "305c308006072a8648ce3d020106052b8104000a06081122000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 328, - "comment" : "indefinite length with garbage", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000fe02beef", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 329, - "comment" : "indefinite length with garbage", - "public" : "305c308006072a8648ce3d020106052b8104000a0000fe02beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 330, - "comment" : "indefinite length with nonempty EOC", - "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670002beef", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 331, - "comment" : "indefinite length with nonempty EOC", - "public" : "305a308006072a8648ce3d020106052b8104000a0002beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 332, - "comment" : "prepend empty sequence", - "public" : "30583000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 333, - "comment" : "prepend empty sequence", - "public" : "30583012300006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 334, - "comment" : "append empty sequence", - "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32673000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 335, - "comment" : "append empty sequence", - "public" : "3058301206072a8648ce3d020106052b8104000a300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 336, - "comment" : "append garbage with high tag number", - "public" : "3059301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267bf7f00", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 337, - "comment" : "append garbage with high tag number", - "public" : "3059301306072a8648ce3d020106052b8104000abf7f0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 338, - "comment" : "sequence of sequence", - "public" : "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 339, - "comment" : "sequence of sequence", - "public" : "30583012301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 340, - "comment" : "truncated sequence: removed last 1 elements", - "public" : "3012301006072a8648ce3d020106052b8104000a", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 341, - "comment" : "truncated sequence: removed last 1 elements", - "public" : "304f300906072a8648ce3d020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 342, - "comment" : "repeating element in sequence", - "public" : "30819a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 343, - "comment" : "repeating element in sequence", - "public" : "305d301706072a8648ce3d020106052b8104000a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 344, - "comment" : "long form encoding of length of oid", - "public" : "305730110681072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 345, - "comment" : "long form encoding of length of oid", - "public" : "3057301106072a8648ce3d02010681052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 346, - "comment" : "length of oid contains leading 0", - "public" : "30583012068200072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 347, - "comment" : "length of oid contains leading 0", - "public" : "3058301206072a8648ce3d0201068200052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 348, - "comment" : "wrong length of oid", - "public" : "3056301006082a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 349, - "comment" : "wrong length of oid", - "public" : "3056301006062a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 350, - "comment" : "wrong length of oid", - "public" : "3056301006072a8648ce3d020106062b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 351, - "comment" : "wrong length of oid", - "public" : "3056301006072a8648ce3d020106042b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 352, - "comment" : "uint32 overflow in length of oid", - "public" : "305b3015068501000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 353, - "comment" : "uint32 overflow in length of oid", - "public" : "305b301506072a8648ce3d0201068501000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 354, - "comment" : "uint64 overflow in length of oid", - "public" : "305f301906890100000000000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 355, - "comment" : "uint64 overflow in length of oid", - "public" : "305f301906072a8648ce3d020106890100000000000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 356, - "comment" : "length of oid = 2**31 - 1", - "public" : "305a301406847fffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 357, - "comment" : "length of oid = 2**31 - 1", - "public" : "305a301406072a8648ce3d020106847fffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 358, - "comment" : "length of oid = 2**32 - 1", - "public" : "305a30140684ffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 359, - "comment" : "length of oid = 2**32 - 1", - "public" : "305a301406072a8648ce3d02010684ffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 360, - "comment" : "length of oid = 2**40 - 1", - "public" : "305b30150685ffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 361, - "comment" : "length of oid = 2**40 - 1", - "public" : "305b301506072a8648ce3d02010685ffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 362, - "comment" : "length of oid = 2**64 - 1", - "public" : "305e30180688ffffffffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 363, - "comment" : "length of oid = 2**64 - 1", - "public" : "305e301806072a8648ce3d02010688ffffffffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 364, - "comment" : "incorrect length of oid", - "public" : "3056301006ff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 365, - "comment" : "incorrect length of oid", - "public" : "3056301006072a8648ce3d020106ff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 366, - "comment" : "removing oid", - "public" : "304d300706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 367, - "comment" : "lonely oid tag", - "public" : "304e30080606052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 368, - "comment" : "lonely oid tag", - "public" : "3050300a06072a8648ce3d02010603420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 369, - "comment" : "appending 0's to oid", - "public" : "3058301206092a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 370, - "comment" : "appending 0's to oid", - "public" : "3058301206072a8648ce3d020106072b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 371, - "comment" : "prepending 0's to oid", - "public" : "30583012060900002a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 372, - "comment" : "prepending 0's to oid", - "public" : "3058301206072a8648ce3d0201060700002b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 373, - "comment" : "appending unused 0's to oid", - "public" : "3058301206072a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 374, - "comment" : "appending null value to oid", - "public" : "3058301206092a8648ce3d0201050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 375, - "comment" : "appending null value to oid", - "public" : "3058301206072a8648ce3d020106072b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 376, - "comment" : "truncated length of oid", - "public" : "304f3009068106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 377, - "comment" : "truncated length of oid", - "public" : "3051300b06072a8648ce3d0201068103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 378, - "comment" : "Replacing oid with NULL", - "public" : "304f3009050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 379, - "comment" : "Replacing oid with NULL", - "public" : "3051300b06072a8648ce3d0201050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 380, - "comment" : "changing tag value of oid", - "public" : "3056301004072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 381, - "comment" : "changing tag value of oid", - "public" : "3056301005072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 382, - "comment" : "changing tag value of oid", - "public" : "3056301007072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 383, - "comment" : "changing tag value of oid", - "public" : "3056301008072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 384, - "comment" : "changing tag value of oid", - "public" : "30563010ff072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 385, - "comment" : "changing tag value of oid", - "public" : "3056301006072a8648ce3d020104052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 386, - "comment" : "changing tag value of oid", - "public" : "3056301006072a8648ce3d020105052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 387, - "comment" : "changing tag value of oid", - "public" : "3056301006072a8648ce3d020107052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 388, - "comment" : "changing tag value of oid", - "public" : "3056301006072a8648ce3d020108052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 389, - "comment" : "changing tag value of oid", - "public" : "3056301006072a8648ce3d0201ff052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 390, - "comment" : "dropping value of oid", - "public" : "304f3009060006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 391, - "comment" : "dropping value of oid", - "public" : "3051300b06072a8648ce3d0201060003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 392, - "comment" : "modify first byte of oid", - "public" : "305630100607288648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 393, - "comment" : "modify first byte of oid", - "public" : "3056301006072a8648ce3d02010605298104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 394, - "comment" : "modify last byte of oid", - "public" : "3056301006072a8648ce3d028106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 395, - "comment" : "modify last byte of oid", - "public" : "3056301006072a8648ce3d020106052b8104008a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 396, - "comment" : "truncated oid", - "public" : "3055300f06062a8648ce3d0206052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 397, - "comment" : "truncated oid", - "public" : "3055300f06068648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 398, - "comment" : "truncated oid", - "public" : "3055300f06072a8648ce3d020106042b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 399, - "comment" : "truncated oid", - "public" : "3055300f06072a8648ce3d020106048104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 400, - "comment" : "wrong oid", - "public" : "3054300e06052b0e03021a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 401, - "comment" : "wrong oid", - "public" : "30583012060960864801650304020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 402, - "comment" : "wrong oid", - "public" : "3056301006072a8648ce3d020106052b0e03021a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 403, - "comment" : "wrong oid", - "public" : "305a301406072a8648ce3d0201060960864801650304020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 404, - "comment" : "longer oid", - "public" : "3057301106082a8648ce3d02010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 405, - "comment" : "longer oid", - "public" : "3057301106072a8648ce3d020106062b8104000a0103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 406, - "comment" : "oid with modified node", - "public" : "3056301006072a8648ce3d021106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 407, - "comment" : "oid with modified node", - "public" : "305a3014060b2a8648ce3d02888080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 408, - "comment" : "oid with modified node", - "public" : "3056301006072a8648ce3d020106052b8104001a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 409, - "comment" : "oid with modified node", - "public" : "305a301406072a8648ce3d020106092b810400888080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 410, - "comment" : "large integer in oid", - "public" : "305f301906102a8648ce3d028280808080808080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 411, - "comment" : "large integer in oid", - "public" : "305f301906072a8648ce3d0201060e2b8104008280808080808080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 412, - "comment" : "oid with invalid node", - "public" : "3057301106082a8648ce3d0201e006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 413, - "comment" : "oid with invalid node", - "public" : "3057301106082a808648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 414, - "comment" : "oid with invalid node", - "public" : "3057301106072a8648ce3d020106062b8104000ae003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 415, - "comment" : "oid with invalid node", - "public" : "3057301106072a8648ce3d020106062b808104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 416, - "comment" : "long form encoding of length of bit string", - "public" : "3057301006072a8648ce3d020106052b8104000a0381420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 417, - "comment" : "length of bit string contains leading 0", - "public" : "3058301006072a8648ce3d020106052b8104000a038200420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 418, - "comment" : "wrong length of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a03430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 419, - "comment" : "wrong length of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 420, - "comment" : "uint32 overflow in length of bit string", - "public" : "305b301006072a8648ce3d020106052b8104000a038501000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 421, - "comment" : "uint64 overflow in length of bit string", - "public" : "305f301006072a8648ce3d020106052b8104000a03890100000000000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 422, - "comment" : "length of bit string = 2**31 - 1", - "public" : "305a301006072a8648ce3d020106052b8104000a03847fffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 423, - "comment" : "length of bit string = 2**32 - 1", - "public" : "305a301006072a8648ce3d020106052b8104000a0384ffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 424, - "comment" : "length of bit string = 2**40 - 1", - "public" : "305b301006072a8648ce3d020106052b8104000a0385ffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 425, - "comment" : "length of bit string = 2**64 - 1", - "public" : "305e301006072a8648ce3d020106052b8104000a0388ffffffffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 426, - "comment" : "incorrect length of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a03ff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 427, - "comment" : "lonely bit string tag", - "public" : "3013301006072a8648ce3d020106052b8104000a03", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 428, - "comment" : "appending 0's to bit string", - "public" : "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 429, - "comment" : "prepending 0's to bit string", - "public" : "3058301006072a8648ce3d020106052b8104000a034400000004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 430, - "comment" : "appending null value to bit string", - "public" : "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 431, - "comment" : "truncated length of bit string", - "public" : "3014301006072a8648ce3d020106052b8104000a0381", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 432, - "comment" : "Replacing bit string with NULL", - "public" : "3014301006072a8648ce3d020106052b8104000a0500", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 433, - "comment" : "changing tag value of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a01420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 434, - "comment" : "changing tag value of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a02420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 435, - "comment" : "changing tag value of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a04420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 436, - "comment" : "changing tag value of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a05420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 437, - "comment" : "changing tag value of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000aff420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 438, - "comment" : "dropping value of bit string", - "public" : "3014301006072a8648ce3d020106052b8104000a0300", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 439, - "comment" : "modify first byte of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a03420204e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 440, - "comment" : "modify last byte of bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32e7", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 441, - "comment" : "truncated bit string", - "public" : "3055301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 442, - "comment" : "truncated bit string", - "public" : "3055301006072a8648ce3d020106052b8104000a034104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 443, - "comment" : "declaring bits as unused in bit string", - "public" : "3056301006072a8648ce3d020106052b8104000a03420104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 444, - "comment" : "unused bits in bit string", - "public" : "305a301006072a8648ce3d020106052b8104000a03462004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326701020304", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 445, - "comment" : "unused bits in empty bit-string", - "public" : "3015301006072a8648ce3d020106052b8104000a030103", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - }, - { - "tcId" : 446, - "comment" : "128 unused bits", - "public" : "3056301006072a8648ce3d020106052b8104000a03428004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", - "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", - "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", - "result" : "acceptable", - "flags" : [ - "InvalidAsn" - ] - } - ] - } - ] -} diff --git a/test/vectors/schnorr.csv b/test/vectors/schnorr.csv deleted file mode 100644 index e068322..0000000 --- a/test/vectors/schnorr.csv +++ /dev/null @@ -1,16 +0,0 @@ -index,secret key,public key,aux_rand,message,signature,verification result,comment -0,0000000000000000000000000000000000000000000000000000000000000003,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9,0000000000000000000000000000000000000000000000000000000000000000,0000000000000000000000000000000000000000000000000000000000000000,E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0,TRUE, -1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,0000000000000000000000000000000000000000000000000000000000000001,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A,TRUE, -2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906,7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7,TRUE, -3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3,TRUE,test fails if msg is reduced modulo p or n -4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4,TRUE, -5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key not on the curve -6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2,FALSE,has_even_y(R) is false -7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD,FALSE,negated message -8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6,FALSE,negated s value -9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051,FALSE,sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 0 -10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197,FALSE,sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 1 -11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is not an X coordinate on the curve -12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is equal to field size -13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order -14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key is not a valid X coordinate because it exceeds the field size diff --git a/test/vectors/ecdsa.json b/test/vectors/secp256k1/ecdsa.json similarity index 100% rename from test/vectors/ecdsa.json rename to test/vectors/secp256k1/ecdsa.json diff --git a/test/vectors/points.json b/test/vectors/secp256k1/points.json similarity index 100% rename from test/vectors/points.json rename to test/vectors/secp256k1/points.json diff --git a/test/vectors/privates-2.txt b/test/vectors/secp256k1/privates-2.txt similarity index 100% rename from test/vectors/privates-2.txt rename to test/vectors/secp256k1/privates-2.txt diff --git a/test/vectors/privates.json b/test/vectors/secp256k1/privates.json similarity index 100% rename from test/vectors/privates.json rename to test/vectors/secp256k1/privates.json diff --git a/test/vectors/wychenproof.json b/test/vectors/wychenproof.json deleted file mode 100644 index dce3048..0000000 --- a/test/vectors/wychenproof.json +++ /dev/null @@ -1,4474 +0,0 @@ -{ - "algorithm" : "ECDSA", - "generatorVersion" : "0.8r12", - "numberOfTests" : 380, - "header" : [ - "Test vectors of type EcdsaVerify are meant for the verification", - "of ASN encoded ECDSA signatures." - ], - "notes" : { - "BER" : "This is a signature with correct values for (r, s) but using some alternative BER encoding instead of DER encoding. Implementations should not accept such signatures to limit signature malleability.", - "EdgeCase" : "Edge case values such as r=1 and s=0 can lead to forgeries if the ECDSA implementation does not check boundaries and computes s^(-1)==0.", - "MissingZero" : "Some implementations of ECDSA and DSA incorrectly encode r and s by not including leading zeros in the ASN encoding of integers when necessary. Hence, some implementations (e.g. jdk) allow signatures with incorrect ASN encodings assuming that the signature is otherwise valid.", - "PointDuplication" : "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission." - }, - "schema" : "ecdsa_verify_schema.json", - "testGroups" : [ - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", - "wx" : "00b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6f", - "wy" : "00f0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 1, - "comment" : "signature malleability", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647db37c21f4afd3203ae8dc4ae7794b0f87", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 2, - "comment" : "Legacy:ASN encoding of r misses leading 0", - "msg" : "313233343030", - "sig" : "30440220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "acceptable", - "flags" : [ - "MissingZero" - ] - }, - { - "tcId" : 3, - "comment" : "valid", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 4, - "comment" : "long form encoding of length of sequence", - "msg" : "313233343030", - "sig" : "308145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 5, - "comment" : "length of sequence contains leading 0", - "msg" : "313233343030", - "sig" : "30820045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 6, - "comment" : "wrong length of sequence", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 7, - "comment" : "wrong length of sequence", - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 8, - "comment" : "uint32 overflow in length of sequence", - "msg" : "313233343030", - "sig" : "30850100000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 9, - "comment" : "uint64 overflow in length of sequence", - "msg" : "313233343030", - "sig" : "3089010000000000000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 10, - "comment" : "length of sequence = 2**31 - 1", - "msg" : "313233343030", - "sig" : "30847fffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 11, - "comment" : "length of sequence = 2**32 - 1", - "msg" : "313233343030", - "sig" : "3084ffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 12, - "comment" : "length of sequence = 2**40 - 1", - "msg" : "313233343030", - "sig" : "3085ffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 13, - "comment" : "length of sequence = 2**64 - 1", - "msg" : "313233343030", - "sig" : "3088ffffffffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 14, - "comment" : "incorrect length of sequence", - "msg" : "313233343030", - "sig" : "30ff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 15, - "comment" : "indefinite length without termination", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 16, - "comment" : "indefinite length without termination", - "msg" : "313233343030", - "sig" : "3045028000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 17, - "comment" : "indefinite length without termination", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502806ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 18, - "comment" : "removing sequence", - "msg" : "313233343030", - "sig" : "", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 19, - "comment" : "lonely sequence tag", - "msg" : "313233343030", - "sig" : "30", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 20, - "comment" : "appending 0's to sequence", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 21, - "comment" : "prepending 0's to sequence", - "msg" : "313233343030", - "sig" : "30470000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 22, - "comment" : "appending unused 0's to sequence", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 23, - "comment" : "appending null value to sequence", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 24, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304a4981773045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 25, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304925003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 26, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 27, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304a2226498177022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 28, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304922252500022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 29, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304d2223022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650004deadbeef02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 30, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222549817702206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 31, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652224250002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 32, - "comment" : "including garbage", - "msg" : "313233343030", - "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 33, - "comment" : "including undefined tags", - "msg" : "313233343030", - "sig" : "304daa00bb00cd003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 34, - "comment" : "including undefined tags", - "msg" : "313233343030", - "sig" : "304baa02aabb3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 35, - "comment" : "including undefined tags", - "msg" : "313233343030", - "sig" : "304d2229aa00bb00cd00022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 36, - "comment" : "including undefined tags", - "msg" : "313233343030", - "sig" : "304b2227aa02aabb022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 37, - "comment" : "including undefined tags", - "msg" : "313233343030", - "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652228aa00bb00cd0002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 38, - "comment" : "including undefined tags", - "msg" : "313233343030", - "sig" : "304b022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652226aa02aabb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 39, - "comment" : "truncated length of sequence", - "msg" : "313233343030", - "sig" : "3081", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 40, - "comment" : "using composition with indefinite length", - "msg" : "313233343030", - "sig" : "30803045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 41, - "comment" : "using composition with indefinite length", - "msg" : "313233343030", - "sig" : "30492280022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 42, - "comment" : "using composition with indefinite length", - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 43, - "comment" : "using composition with wrong tag", - "msg" : "313233343030", - "sig" : "30803145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 44, - "comment" : "using composition with wrong tag", - "msg" : "313233343030", - "sig" : "30492280032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 45, - "comment" : "using composition with wrong tag", - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228003206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 46, - "comment" : "Replacing sequence with NULL", - "msg" : "313233343030", - "sig" : "0500", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 47, - "comment" : "changing tag value of sequence", - "msg" : "313233343030", - "sig" : "2e45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 48, - "comment" : "changing tag value of sequence", - "msg" : "313233343030", - "sig" : "2f45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 49, - "comment" : "changing tag value of sequence", - "msg" : "313233343030", - "sig" : "3145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 50, - "comment" : "changing tag value of sequence", - "msg" : "313233343030", - "sig" : "3245022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 51, - "comment" : "changing tag value of sequence", - "msg" : "313233343030", - "sig" : "ff45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 52, - "comment" : "dropping value of sequence", - "msg" : "313233343030", - "sig" : "3000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 53, - "comment" : "using composition for sequence", - "msg" : "313233343030", - "sig" : "304930010230442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 54, - "comment" : "truncated sequence", - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 55, - "comment" : "truncated sequence", - "msg" : "313233343030", - "sig" : "30442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 56, - "comment" : "indefinite length", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 57, - "comment" : "indefinite length with truncated delimiter", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba00", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 58, - "comment" : "indefinite length with additional element", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba05000000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 59, - "comment" : "indefinite length with truncated element", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba060811220000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 60, - "comment" : "indefinite length with garbage", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000fe02beef", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 61, - "comment" : "indefinite length with nonempty EOC", - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0002beef", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 62, - "comment" : "prepend empty sequence", - "msg" : "313233343030", - "sig" : "30473000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 63, - "comment" : "append empty sequence", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba3000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 64, - "comment" : "append garbage with high tag number", - "msg" : "313233343030", - "sig" : "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31babf7f00", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 65, - "comment" : "sequence of sequence", - "msg" : "313233343030", - "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 66, - "comment" : "truncated sequence: removed last 1 elements", - "msg" : "313233343030", - "sig" : "3023022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 67, - "comment" : "repeating element in sequence", - "msg" : "313233343030", - "sig" : "3067022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 68, - "comment" : "long form encoding of length of integer", - "msg" : "313233343030", - "sig" : "304602812100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 69, - "comment" : "long form encoding of length of integer", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 70, - "comment" : "length of integer contains leading 0", - "msg" : "313233343030", - "sig" : "30470282002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 71, - "comment" : "length of integer contains leading 0", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028200206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 72, - "comment" : "wrong length of integer", - "msg" : "313233343030", - "sig" : "3045022200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 73, - "comment" : "wrong length of integer", - "msg" : "313233343030", - "sig" : "3045022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 74, - "comment" : "wrong length of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 75, - "comment" : "wrong length of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 76, - "comment" : "uint32 overflow in length of integer", - "msg" : "313233343030", - "sig" : "304a0285010000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 77, - "comment" : "uint32 overflow in length of integer", - "msg" : "313233343030", - "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028501000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 78, - "comment" : "uint64 overflow in length of integer", - "msg" : "313233343030", - "sig" : "304e028901000000000000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 79, - "comment" : "uint64 overflow in length of integer", - "msg" : "313233343030", - "sig" : "304e022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502890100000000000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 80, - "comment" : "length of integer = 2**31 - 1", - "msg" : "313233343030", - "sig" : "304902847fffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 81, - "comment" : "length of integer = 2**31 - 1", - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502847fffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 82, - "comment" : "length of integer = 2**32 - 1", - "msg" : "313233343030", - "sig" : "30490284ffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 83, - "comment" : "length of integer = 2**32 - 1", - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284ffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 84, - "comment" : "length of integer = 2**40 - 1", - "msg" : "313233343030", - "sig" : "304a0285ffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 85, - "comment" : "length of integer = 2**40 - 1", - "msg" : "313233343030", - "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650285ffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 86, - "comment" : "length of integer = 2**64 - 1", - "msg" : "313233343030", - "sig" : "304d0288ffffffffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 87, - "comment" : "length of integer = 2**64 - 1", - "msg" : "313233343030", - "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650288ffffffffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 88, - "comment" : "incorrect length of integer", - "msg" : "313233343030", - "sig" : "304502ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 89, - "comment" : "incorrect length of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 90, - "comment" : "removing integer", - "msg" : "313233343030", - "sig" : "302202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 91, - "comment" : "lonely integer tag", - "msg" : "313233343030", - "sig" : "30230202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 92, - "comment" : "lonely integer tag", - "msg" : "313233343030", - "sig" : "3024022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 93, - "comment" : "appending 0's to integer", - "msg" : "313233343030", - "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 94, - "comment" : "appending 0's to integer", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 95, - "comment" : "prepending 0's to integer", - "msg" : "313233343030", - "sig" : "30470223000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 96, - "comment" : "prepending 0's to integer", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022200006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [ - "BER" - ] - }, - { - "tcId" : 97, - "comment" : "appending unused 0's to integer", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 98, - "comment" : "appending null value to integer", - "msg" : "313233343030", - "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 99, - "comment" : "appending null value to integer", - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 100, - "comment" : "truncated length of integer", - "msg" : "313233343030", - "sig" : "3024028102206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 101, - "comment" : "truncated length of integer", - "msg" : "313233343030", - "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 102, - "comment" : "Replacing integer with NULL", - "msg" : "313233343030", - "sig" : "3024050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 103, - "comment" : "Replacing integer with NULL", - "msg" : "313233343030", - "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650500", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 104, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 105, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045012100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 106, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 107, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045042100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 108, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045ff2100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 109, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236500206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 110, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236501206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 111, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236503206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 112, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236504206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 113, - "comment" : "changing tag value of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365ff206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 114, - "comment" : "dropping value of integer", - "msg" : "313233343030", - "sig" : "3024020002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 115, - "comment" : "dropping value of integer", - "msg" : "313233343030", - "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650200", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 116, - "comment" : "using composition for integer", - "msg" : "313233343030", - "sig" : "304922250201000220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 117, - "comment" : "using composition for integer", - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222402016f021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 118, - "comment" : "modify first byte of integer", - "msg" : "313233343030", - "sig" : "3045022102813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 119, - "comment" : "modify first byte of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206df18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 120, - "comment" : "modify last byte of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323e502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 121, - "comment" : "modify last byte of integer", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb313a", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 122, - "comment" : "truncated integer", - "msg" : "313233343030", - "sig" : "3044022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832302206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 123, - "comment" : "truncated integer", - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 124, - "comment" : "truncated integer", - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 125, - "comment" : "leading ff in integer", - "msg" : "313233343030", - "sig" : "30460222ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 126, - "comment" : "leading ff in integer", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 127, - "comment" : "replaced integer by infinity", - "msg" : "313233343030", - "sig" : "302509018002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 128, - "comment" : "replaced integer by infinity", - "msg" : "313233343030", - "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365090180", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 129, - "comment" : "replacing integer with zero", - "msg" : "313233343030", - "sig" : "302502010002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 130, - "comment" : "replacing integer with zero", - "msg" : "313233343030", - "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365020100", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 131, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478583b90deabca4b05c4574e49b5899b964a602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 132, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "30440220813ef79ccefa9a56f7ba805f0e47858643b030ef461f1bcdf53fde3ef94ce22402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 133, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "30450221ff7ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 134, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "304402207ec10863310565a908457fa0f1b87a79bc4fcf10b9e0e4320ac021c106b31ddc02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 135, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "30450221fe7ec10863310565a908457fa0f1b87a7c46f215435b4fa3ba8b1b64a766469b5a02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 136, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 137, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "304402207ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 138, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221016ff18a52dcc0336f7af62400a6dd9b7fc1e197d8aebe203c96c87232272172fb", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 139, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b824c83de0b502cdfc51723b51886b4f079", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 140, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650220900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce46", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 141, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221fe900e75ad233fcc908509dbff592264803e1e68275141dfc369378dcdd8de8d05", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 142, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221016ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 143, - "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce46", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 144, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3006020100020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 145, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3006020100020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 146, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30060201000201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 147, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 148, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 149, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 150, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 151, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 152, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3008020100090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 153, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3006020100090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 154, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3006020101020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 155, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3006020101020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 156, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30060201010201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 157, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 158, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 159, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 160, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 161, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 162, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3008020101090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 163, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3006020101090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 164, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30060201ff020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 165, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30060201ff020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 166, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30060201ff0201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 167, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 168, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 169, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 170, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 171, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 172, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30080201ff090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 173, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "30060201ff090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 174, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 175, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 176, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 177, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 178, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 179, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 180, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 181, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 182, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 183, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 184, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 185, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 186, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 187, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 188, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 189, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 190, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 191, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 192, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 193, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 194, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 195, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 196, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 197, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 198, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 199, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 200, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 201, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 202, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 203, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 204, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 205, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 206, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 207, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 208, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 209, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 210, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 211, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 212, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 213, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 214, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020100", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 215, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020101", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 216, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300201ff", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 217, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 218, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 219, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 220, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 221, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 222, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30090380fe01", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 223, - "comment" : "Signature with special case values for r and s", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30090142", - "result" : "invalid", - "flags" : [ - "EdgeCase" - ] - }, - { - "tcId" : 224, - "comment" : "Signature encoding contains wrong types.", - "msg" : "313233343030", - "sig" : "30060201010c0130", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 225, - "comment" : "Signature encoding contains wrong types.", - "msg" : "313233343030", - "sig" : "30050201010c00", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 226, - "comment" : "Signature encoding contains wrong types.", - "msg" : "313233343030", - "sig" : "30090c0225730c03732573", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 227, - "comment" : "Signature encoding contains wrong types.", - "msg" : "313233343030", - "sig" : "30080201013003020100", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 228, - "comment" : "Signature encoding contains wrong types.", - "msg" : "313233343030", - "sig" : "3003020101", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 229, - "comment" : "Signature encoding contains wrong types.", - "msg" : "313233343030", - "sig" : "3006020101010100", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 230, - "comment" : "Edge case for Shamir multiplication", - "msg" : "3235353835", - "sig" : "3045022100dd1b7d09a7bd8218961034a39a87fecf5314f00c4d25eb58a07ac85e85eab516022035138c401ef8d3493d65c9002fe62b43aee568731b744548358996d9cc427e06", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 231, - "comment" : "special case hash", - "msg" : "343236343739373234", - "sig" : "304502210095c29267d972a043d955224546222bba343fc1d4db0fec262a33ac61305696ae02206edfe96713aed56f8a28a6653f57e0b829712e5eddc67f34682b24f0676b2640", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 232, - "comment" : "special case hash", - "msg" : "37313338363834383931", - "sig" : "3045022028f94a894e92024699e345fe66971e3edcd050023386135ab3939d550898fb25022100cd69c1a42be05a6ee1270c821479251e134c21858d800bda6f4e98b37196238e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 233, - "comment" : "special case hash", - "msg" : "3130333539333331363638", - "sig" : "3046022100be26b18f9549f89f411a9b52536b15aa270b84548d0e859a1952a27af1a77ac60221008f3e2b05632fc33715572af9124681113f2b84325b80154c044a544dc1a8fa12", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 234, - "comment" : "special case hash", - "msg" : "33393439343031323135", - "sig" : "3046022100b1a4b1478e65cc3eafdf225d1298b43f2da19e4bcff7eacc0a2e98cd4b74b114022100e8655ce1cfb33ebd30af8ce8e8ae4d6f7b50cd3e22af51bf69e0a2851760d52b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 235, - "comment" : "special case hash", - "msg" : "31333434323933303739", - "sig" : "30440220325332021261f1bd18f2712aa1e2252da23796da8a4b1ff6ea18cafec7e171f2022040b4f5e287ee61fc3c804186982360891eaa35c75f05a43ecd48b35d984a6648", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 236, - "comment" : "special case hash", - "msg" : "33373036323131373132", - "sig" : "3046022100a23ad18d8fc66d81af0903890cbd453a554cb04cdc1a8ca7f7f78e5367ed88a0022100dc1c14d31e3fb158b73c764268c8b55579734a7e2a2c9b5ee5d9d0144ef652eb", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 237, - "comment" : "special case hash", - "msg" : "333433363838373132", - "sig" : "304502202bdea41cda63a2d14bf47353bd20880a690901de7cd6e3cc6d8ed5ba0cdb1091022100c31599433036064073835b1e3eba8335a650c8fd786f94fe235ad7d41dc94c7a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 238, - "comment" : "special case hash", - "msg" : "31333531353330333730", - "sig" : "3046022100d7cd76ec01c1b1079eba9e2aa2a397243c4758c98a1ba0b7404a340b9b00ced6022100ca8affe1e626dd192174c2937b15bc48f77b5bdfe01f073a8aeaf7f24dc6c85b", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 239, - "comment" : "special case hash", - "msg" : "36353533323033313236", - "sig" : "3045022100a872c744d936db21a10c361dd5c9063355f84902219652f6fc56dc95a7139d960220400df7575d9756210e9ccc77162c6b593c7746cfb48ac263c42750b421ef4bb9", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 240, - "comment" : "special case hash", - "msg" : "31353634333436363033", - "sig" : "30460221009fa9afe07752da10b36d3afcd0fe44bfc40244d75203599cf8f5047fa3453854022100af1f583fec4040ae7e68c968d2bb4b494eec3a33edc7c0ccf95f7f75bc2569c7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 241, - "comment" : "special case hash", - "msg" : "34343239353339313137", - "sig" : "3045022100885640384d0d910efb177b46be6c3dc5cac81f0b88c3190bb6b5f99c2641f2050220738ed9bff116306d9caa0f8fc608be243e0b567779d8dab03e8e19d553f1dc8e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 242, - "comment" : "special case hash", - "msg" : "3130393533323631333531", - "sig" : "304502202d051f91c5a9d440c5676985710483bc4f1a6c611b10c95a2ff0363d90c2a45802210092206b19045a41a797cc2f3ac30de9518165e96d5b86341ecb3bcff231b3fd65", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 243, - "comment" : "special case hash", - "msg" : "35393837333530303431", - "sig" : "3045022100f3ac2523967482f53d508522712d583f4379cd824101ff635ea0935117baa54f022027f10812227397e02cea96fb0e680761636dab2b080d1fc5d11685cbe8500cfe", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 244, - "comment" : "special case hash", - "msg" : "33343633303036383738", - "sig" : "304602210096447cf68c3ab7266ed7447de3ac52fed7cc08cbdfea391c18a9b8ab370bc913022100f0a1878b2c53f16e70fe377a5e9c6e86f18ae480a22bb499f5b32e7109c07385", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 245, - "comment" : "special case hash", - "msg" : "39383137333230323837", - "sig" : "30450220530a0832b691da0b5619a0b11de6877f3c0971baaa68ed122758c29caaf46b7202210093761bb0a14ccf9f15b4b9ce73c6ec700bd015b8cb1cfac56837f4463f53074e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 246, - "comment" : "special case hash", - "msg" : "33323232303431303436", - "sig" : "30460221009c54c25500bde0b92d72d6ec483dc2482f3654294ca74de796b681255ed58a77022100988bac394a90ad89ce360984c0c149dcbd2684bb64498ace90bcf6b6af1c170e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 247, - "comment" : "special case hash", - "msg" : "36363636333037313034", - "sig" : "3045022100e7909d41439e2f6af29136c7348ca2641a2b070d5b64f91ea9da7070c7a2618b022042d782f132fa1d36c2c88ba27c3d678d80184a5d1eccac7501f0b47e3d205008", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 248, - "comment" : "special case hash", - "msg" : "31303335393531383938", - "sig" : "304502205924873209593135a4c3da7bb381227f8a4b6aa9f34fe5bb7f8fbc131a039ffe022100e0e44ee4bbe370155bf0bbdec265bf9fe31c0746faab446de62e3631eacd111f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 249, - "comment" : "special case hash", - "msg" : "31383436353937313935", - "sig" : "3045022100eeb692c9b262969b231c38b5a7f60649e0c875cd64df88f33aa571fa3d29ab0e0220218b3a1eb06379c2c18cf51b06430786d1c64cd2d24c9b232b23e5bac7989acd", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 250, - "comment" : "special case hash", - "msg" : "33313336303436313839", - "sig" : "3045022100a40034177f36091c2b653684a0e3eb5d4bff18e4d09f664c2800e7cafda1daf802203a3ec29853704e52031c58927a800a968353adc3d973beba9172cbbeab4dd149", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 251, - "comment" : "special case hash", - "msg" : "32363633373834323534", - "sig" : "3046022100b5d795cc75cea5c434fa4185180cd6bd21223f3d5a86da6670d71d95680dadbf022100ab1b277ef5ffe134460835e3d1402461ba104cb50b16f397fdc7a9abfefef280", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 252, - "comment" : "special case hash", - "msg" : "31363532313030353234", - "sig" : "3044022007dc2478d43c1232a4595608c64426c35510051a631ae6a5a6eb1161e57e42e102204a59ea0fdb72d12165cea3bf1ca86ba97517bd188db3dbd21a5a157850021984", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 253, - "comment" : "special case hash", - "msg" : "35373438303831363936", - "sig" : "3046022100ddd20c4a05596ca868b558839fce9f6511ddd83d1ccb53f82e5269d559a01552022100a46e8cb8d626cf6c00ddedc3b5da7e613ac376445ee260743f06f79054c7d42a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 254, - "comment" : "special case hash", - "msg" : "36333433393133343638", - "sig" : "30450221009cde6e0ede0a003f02fda0a01b59facfe5dec063318f279ce2de7a9b1062f7b702202886a5b8c679bdf8224c66f908fd6205492cb70b0068d46ae4f33a4149b12a52", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 255, - "comment" : "special case hash", - "msg" : "31353431313033353938", - "sig" : "3046022100c5771016d0dd6357143c89f684cd740423502554c0c59aa8c99584f1ff38f609022100ab4bfa0bb88ab99791b9b3ab9c4b02bd2a57ae8dde50b9064063fcf85315cfe5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 256, - "comment" : "special case hash", - "msg" : "3130343738353830313238", - "sig" : "3045022100a24ebc0ec224bd67ae397cbe6fa37b3125adbd34891abe2d7c7356921916dfe6022034f6eb6374731bbbafc4924fb8b0bdcdda49456d724cdae6178d87014cb53d8c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 257, - "comment" : "special case hash", - "msg" : "3130353336323835353638", - "sig" : "304502202557d64a7aee2e0931c012e4fea1cd3a2c334edae68cdeb7158caf21b68e5a2402210080f93244956ffdc568c77d12684f7f004fa92da7e60ae94a1b98c422e23eda34", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 258, - "comment" : "special case hash", - "msg" : "393533393034313035", - "sig" : "3046022100c4f2eccbb6a24350c8466450b9d61b207ee359e037b3dcedb42a3f2e6dd6aeb5022100cd9c394a65d0aa322e391eb76b2a1a687f8620a88adef3a01eb8e4fb05b6477a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 259, - "comment" : "special case hash", - "msg" : "393738383438303339", - "sig" : "3046022100eff04781c9cbcd162d0a25a6e2ebcca43506c523385cb515d49ea38a1b12fcad022100ea5328ce6b36e56ab87acb0dcfea498bcec1bba86a065268f6eff3c41c4b0c9c", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 260, - "comment" : "special case hash", - "msg" : "33363130363732343432", - "sig" : "3046022100f58b4e3110a64bf1b5db97639ee0e5a9c8dfa49dc59b679891f520fdf0584c87022100d32701ae777511624c1f8abbf02b248b04e7a9eb27938f524f3e8828ba40164a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 261, - "comment" : "special case hash", - "msg" : "31303534323430373035", - "sig" : "3045022100f8abecaa4f0c502de4bf5903d48417f786bf92e8ad72fec0bd7fcb7800c0bbe302204c7f9e231076a30b7ae36b0cebe69ccef1cd194f7cce93a5588fd6814f437c0e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 262, - "comment" : "special case hash", - "msg" : "35313734343438313937", - "sig" : "304402205d5b38bd37ad498b2227a633268a8cca879a5c7c94a4e416bd0a614d09e606d2022012b8d664ea9991062ecbb834e58400e25c46007af84f6007d7f1685443269afe", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 263, - "comment" : "special case hash", - "msg" : "31393637353631323531", - "sig" : "304402200c1cd9fe4034f086a2b52d65b9d3834d72aebe7f33dfe8f976da82648177d8e3022013105782e3d0cfe85c2778dec1a848b27ac0ae071aa6da341a9553a946b41e59", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 264, - "comment" : "special case hash", - "msg" : "33343437323533333433", - "sig" : "3045022100ae7935fb96ff246b7b5d5662870d1ba587b03d6e1360baf47988b5c02ccc1a5b02205f00c323272083782d4a59f2dfd65e49de0693627016900ef7e61428056664b3", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 265, - "comment" : "special case hash", - "msg" : "333638323634333138", - "sig" : "3045022000a134b5c6ccbcefd4c882b945baeb4933444172795fa6796aae149067547098022100a991b9efa2db276feae1c115c140770901839d87e60e7ec45a2b81cf3b437be6", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 266, - "comment" : "special case hash", - "msg" : "33323631313938363038", - "sig" : "304502202e4721363ad3992c139e5a1c26395d2c2d777824aa24fde075e0d7381171309d0221008bf083b6bbe71ecff22baed087d5a77eaeaf726bf14ace2c03fd6e37ba6c26f2", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 267, - "comment" : "special case hash", - "msg" : "39363738373831303934", - "sig" : "304502206852e9d3cd9fe373c2d504877967d365ab1456707b6817a042864694e1960ccf022100f9b4d815ebd4cf77847b37952334d05b2045cb398d4c21ba207922a7a4714d84", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 268, - "comment" : "special case hash", - "msg" : "34393538383233383233", - "sig" : "30440220188a8c5648dc79eace158cf886c62b5468f05fd95f03a7635c5b4c31f09af4c5022036361a0b571a00c6cd5e686ccbfcfa703c4f97e48938346d0c103fdc76dc5867", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 269, - "comment" : "special case hash", - "msg" : "383234363337383337", - "sig" : "3045022100a74f1fb9a8263f62fc4416a5b7d584f4206f3996bb91f6fc8e73b9e92bad0e1302206815032e8c7d76c3ab06a86f33249ce9940148cb36d1f417c2e992e801afa3fa", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 270, - "comment" : "special case hash", - "msg" : "3131303230383333373736", - "sig" : "3045022007244865b72ff37e62e3146f0dc14682badd7197799135f0b00ade7671742bfe022100f27f3ddc7124b1b58579573a835650e7a8bad5eeb96e9da215cd7bf9a2a039ed", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 271, - "comment" : "special case hash", - "msg" : "313333383731363438", - "sig" : "3045022100da7fdd05b5badabd619d805c4ee7d9a84f84ddd5cf9c5bf4d4338140d689ef08022028f1cf4fa1c3c5862cfa149c0013cf5fe6cf5076cae000511063e7de25bb38e5", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 272, - "comment" : "special case hash", - "msg" : "333232313434313632", - "sig" : "3046022100d3027c656f6d4fdfd8ede22093e3c303b0133c340d615e7756f6253aea927238022100f6510f9f371b31068d68bfeeaa720eb9bbdc8040145fcf88d4e0b58de0777d2a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 273, - "comment" : "special case hash", - "msg" : "3130363836363535353436", - "sig" : "304402200bf6c0188dc9571cd0e21eecac5fbb19d2434988e9cc10244593ef3a98099f6902204864a562661f9221ec88e3dd0bc2f6e27ac128c30cc1a80f79ec670a22b042ee", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 274, - "comment" : "special case hash", - "msg" : "3632313535323436", - "sig" : "3045022100ae459640d5d1179be47a47fa538e16d94ddea5585e7a244804a51742c686443a02206c8e30e530a634fae80b3ceb062978b39edbe19777e0a24553b68886181fd897", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 275, - "comment" : "special case hash", - "msg" : "37303330383138373734", - "sig" : "304402201cf3517ba3bf2ab8b9ead4ebb6e866cb88a1deacb6a785d3b63b483ca02ac4950220249a798b73606f55f5f1c70de67cb1a0cff95d7dc50b3a617df861bad3c6b1c9", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 276, - "comment" : "special case hash", - "msg" : "35393234353233373434", - "sig" : "3045022100e69b5238265ea35d77e4dd172288d8cea19810a10292617d5976519dc5757cb802204b03c5bc47e826bdb27328abd38d3056d77476b2130f3df6ec4891af08ba1e29", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 277, - "comment" : "special case hash", - "msg" : "31343935353836363231", - "sig" : "304402205f9d7d7c870d085fc1d49fff69e4a275812800d2cf8973e7325866cb40fa2b6f02206d1f5491d9f717a597a15fd540406486d76a44697b3f0d9d6dcef6669f8a0a56", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 278, - "comment" : "special case hash", - "msg" : "34303035333134343036", - "sig" : "304402200a7d5b1959f71df9f817146ee49bd5c89b431e7993e2fdecab6858957da685ae02200f8aad2d254690bdc13f34a4fec44a02fd745a422df05ccbb54635a8b86b9609", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 279, - "comment" : "special case hash", - "msg" : "33303936343537353132", - "sig" : "3044022079e88bf576b74bc07ca142395fda28f03d3d5e640b0b4ff0752c6d94cd553408022032cea05bd2d706c8f6036a507e2ab7766004f0904e2e5c5862749c0073245d6a", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 280, - "comment" : "special case hash", - "msg" : "32373834303235363230", - "sig" : "30450221009d54e037a00212b377bc8874798b8da080564bbdf7e07591b861285809d01488022018b4e557667a82bd95965f0706f81a29243fbdd86968a7ebeb43069db3b18c7f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 281, - "comment" : "special case hash", - "msg" : "32363138373837343138", - "sig" : "304402202664f1ffa982fedbcc7cab1b8bc6e2cb420218d2a6077ad08e591ba9feab33bd022049f5c7cb515e83872a3d41b4cdb85f242ad9d61a5bfc01debfbb52c6c84ba728", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 282, - "comment" : "special case hash", - "msg" : "31363432363235323632", - "sig" : "304502205827518344844fd6a7de73cbb0a6befdea7b13d2dee4475317f0f18ffc81524b022100b0a334b1f4b774a5a289f553224d286d239ef8a90929ed2d91423e024eb7fa66", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 283, - "comment" : "special case hash", - "msg" : "36383234313839343336", - "sig" : "304602210097ab19bd139cac319325869218b1bce111875d63fb12098a04b0cd59b6fdd3a3022100bce26315c5dbc7b8cfc31425a9b89bccea7aa9477d711a4d377f833dcc28f820", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 284, - "comment" : "special case hash", - "msg" : "343834323435343235", - "sig" : "3044022052c683144e44119ae2013749d4964ef67509278f6d38ba869adcfa69970e123d02203479910167408f45bda420a626ec9c4ec711c1274be092198b4187c018b562ca", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", - "wx" : "07310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc362", - "wy" : "26a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEBzEPkKnq4UmghAL1QZSg97SsQnv42b1s\ndoEHHcR9w2ImptN6xG1h/WAMC/G/+HaJ7RF92msOWTGK4BChl6JsoA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 285, - "comment" : "k*G has a large x-coordinate", - "msg" : "313233343030", - "sig" : "30360211014551231950b75fc4402da1722fc9baeb022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 286, - "comment" : "r too large", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", - "wx" : "00bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22", - "wy" : "705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvJfnWF7srUjhZoO8QJFwjhqTDGg/xHAB\n1LODWU8sTiJwWYnPadrq3U5OS4FR7YiN/sIPsBco2J1Ws/OPKunIxQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 287, - "comment" : "r,s are large", - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", - "wx" : "44ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252", - "wy" : "00b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERK0zmvvCHpq/e2AqXKU16jeBNbbRDYEx\nC92Ck9HfMlK2P/fQd0dw+P4dFyL6g6zQL0NOT8EQoMyPbd3TfVbEYw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 288, - "comment" : "r and s^-1 have a large Hamming weight", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203e9a7582886089c62fb840cf3b83061cd1cff3ae4341808bb5bdee6191174177", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", - "wx" : "1260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c", - "wy" : "5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT\n7rrSHzfdh4xcmgwamt52c3qIEb1qf5KHyXjuOWqonBHkcinSzLVS8A==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 289, - "comment" : "r and s^-1 have a large Hamming weight", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022024238e70b431b1a64efdf9032669939d4b77f249503fc6905feb7540dea3e6d2", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", - "wx" : "1877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce", - "wy" : "00821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGHcEW+JdNKHQYA+dXADQZFoqVDebbO76\n0ua/XCozUs6CGlMswXUe4dNtQcPWq06bFD5E7EbXNHjqanmlwOVBWQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 290, - "comment" : "small r and s", - "msg" : "313233343030", - "sig" : "3006020101020101", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", - "wx" : "455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50", - "wy" : "00aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERVQ5/MPS3uzt3q7OYOe9FzBPNuu2Aq31\noi4Ljx20alCuw4+yuvIh6ajRiHx79iIt0YNGNOdyYzFa9tI2CdBPdw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 291, - "comment" : "small r and s", - "msg" : "313233343030", - "sig" : "3006020101020102", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", - "wx" : "2e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece718", - "wy" : "0449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELh9GawJMDDrOJDfeCRJ/7QS3BvlLGaIb\nscKs81zs5xgESa41I9clNOlklyz9OzivC93ZYZ5a8iPk0aQPNM+fHQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 292, - "comment" : "small r and s", - "msg" : "313233343030", - "sig" : "3006020101020103", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 293, - "comment" : "r is larger than n", - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020103", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04dda95d7b0698de5d2d0b4f0034dbe35b50f978fcc518a84abf9c99efd96a25305adc08d6a63dbe831ab99cd9146e3c4c45492ad19521612542256d6af60e7888", - "wx" : "00dda95d7b0698de5d2d0b4f0034dbe35b50f978fcc518a84abf9c99efd96a2530", - "wy" : "5adc08d6a63dbe831ab99cd9146e3c4c45492ad19521612542256d6af60e7888" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004dda95d7b0698de5d2d0b4f0034dbe35b50f978fcc518a84abf9c99efd96a25305adc08d6a63dbe831ab99cd9146e3c4c45492ad19521612542256d6af60e7888", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE3aldewaY3l0tC08ANNvjW1D5ePzFGKhK\nv5yZ79lqJTBa3AjWpj2+gxq5nNkUbjxMRUkq0ZUhYSVCJW1q9g54iA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 294, - "comment" : "s is larger than n", - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd04917c8", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", - "wx" : "02ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee77", - "wy" : "7eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAu9NbWz9WpTx13hCJuPipsCkNsVYOWGf\nOPtEcrX57nd+tKzU7r2lzXKHX/0qLyYinC3GtGUAkZpDLIZznzroZg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 295, - "comment" : "small r and s^-1", - "msg" : "313233343030", - "sig" : "302702020101022100c58b162c58b162c58b162c58b162c58a1b242973853e16db75c8a1a71da4d39d", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", - "wx" : "464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584", - "wy" : "00b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERk9P9xVynK5Qcso72AHTGVtnrsZemwGq\n0gopQ9y8tYSxr9KdMaOaEdVwqhWXQ5s7LRlxvy8avxVDLQIHsQ0dCA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 296, - "comment" : "smallish r and s^-1", - "msg" : "313233343030", - "sig" : "302c02072d9b4d347952cc022100fcbc5103d0da267477d1791461cf2aa44bf9d43198f79507bd8779d69a13108e", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", - "wx" : "157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4c", - "wy" : "00deadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFX+P3fNz619Jz88Q2LhTz5HLzX1mXDUi\nun3XON23mkzerfGlxEjqPJ9BkaiZmr/MdXrG1kVn7wcsR/7GE0Q7jw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 297, - "comment" : "100-bit r and small s^-1", - "msg" : "313233343030", - "sig" : "3032020d1033e67e37b32b445580bf4efc022100906f906f906f906f906f906f906f906ed8e426f7b1968c35a204236a579723d2", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", - "wx" : "0934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0", - "wy" : "00d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECTSlN0ZsB0MOLEj+uZC7Gft4zsyc7kJO\npNEwKRqiN/DU+S0jtGKAS1toxSVYwByZltv3J/zKu+7bliGkAFNa+g==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 298, - "comment" : "small r and 100 bit s^-1", - "msg" : "313233343030", - "sig" : "3026020201010220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", - "wx" : "00d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c65", - "wy" : "4a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1u8gvmbIk/dBqb+Q2bdGddHCoxKWOXrL\nPvF0/QswDGVKDJVHjKADmRYtfw8tyJ79wrKKMPur4oWFcpWksMTiZQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 299, - "comment" : "100-bit r and s^-1", - "msg" : "313233343030", - "sig" : "3031020d062522bbd3ecbe7c39e93e7c260220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", - "wx" : "00b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee06", - "wy" : "29c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEtykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5U\nTZUUVFup7gYpyaY9XjCHacww7CdqQQ5kZKJ+6v2eWZ2xDwU6T+SoKQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 300, - "comment" : "r and s^-1 are close to n", - "msg" : "313233343030", - "sig" : "3045022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c1022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", - "wx" : "00bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c", - "wy" : "1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEu3n2GFf3Q7+htucRHOQJQ3claWnk4VFZ\nEj2VSKzDvmwfnZ+IYNz/0+s23Wwx/y5yJsIAnEyU2NfStWhr96vWdw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 301, - "comment" : "s == 1", - "msg" : "313233343030", - "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020101", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 302, - "comment" : "s == 0", - "msg" : "313233343030", - "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020100", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", - "wx" : "00d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b4150874", - "wy" : "01b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1TO3iaSviQ+nqCofrljEBPmmKlC0mtr6\ns0nFE7QVCHQBtBcbgD52s0qYYeEPe8KJoGb9Ab0p+EyYehCl+xjC1A==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 303, - "comment" : "point at infinity during verify", - "msg" : "313233343030", - "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", - "wx" : "3a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4", - "wy" : "221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOjFQeYyK9p0ebpgfOkVAK6HXMvS+gzDF\nFk9J4Q7FVbQiG9hCvF5Nl+/zcWX2DjmYpCTXKkUM+V6kd8eCh9A0Og==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 304, - "comment" : "edge case for signature malleability", - "msg" : "313233343030", - "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", - "wx" : "3b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e80", - "wy" : "0de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9\nD8/IEB6FHoAN48CQtsohulQ1FzMMBLEvlIxrrfFKY6v/3074x1NwJg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 305, - "comment" : "edge case for signature malleability", - "msg" : "313233343030", - "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", - "wx" : "00feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82c", - "wy" : "00e87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/rUWOw7OMP8+A8fVXEOA+i+oHuLANUlC\n/28IyZ0M2CzofeBe4b2gidPk4kj6D3IRAqz//fUOZUvigUM5md+Jfg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 306, - "comment" : "u1 == 1", - "msg" : "313233343030", - "sig" : "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", - "wx" : "238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd4149228976", - "wy" : "40683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEI4ztABzyK4hT4C7cicvspQULp+BCp6d/\nk4LNQUkiiXZAaD0wlGQ4QPKViQqkwYqjm0HXfdD7O7JwDk+ewoT/wg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 307, - "comment" : "u1 == n - 1", - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", - "wx" : "00961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35e", - "wy" : "00d2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElhz2SBfAbA5Rs8JzbJIv3hi9jEkG/Nf1\n72bEZ4UI817SxdGBaM++cPLxI710GSMruS3WkRPilBBhiJSBxaAnvw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 308, - "comment" : "u2 == 1", - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", - "wx" : "13681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b10288", - "wy" : "16528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEE2gerhaM1Op88uKkXQUnQtEKn2TnloZ9\nvcuCn+CxAogWUodg0Xc3bAnfed45VXwynMF1NRes/+j6LsKYAmuDhA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 309, - "comment" : "u2 == n - 1", - "msg" : "313233343030", - "sig" : "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b89", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", - "wx" : "5aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c2", - "wy" : "0091c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWqer/ba0CG1UMyXl15xulc5C+GbSu4SQ\nljOgS7GqMcKRyACIeUkF4dozM22HTi+RzPRcxZGFvt5d1vP3rKrhiw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 310, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e91e1ba6ba898620a46bcb51dc0b8b4ad1dc35dad892c4552d1847b2ce444637", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", - "wx" : "277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e4", - "wy" : "64108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtU\nASDg9cIGw+RkEIIz+wuMOsiS15744Pv5LtEzrdtFVCcBMlhNxS7vQQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 311, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e36bf0cec06d9b841da81332812f74f30bbaec9f202319206c6f0b8a0a400ff7", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", - "wx" : "6efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1a", - "wy" : "00c75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbvoJK2jelGDwvMkZAFpfboDhnemJaL48\n0sdwqZSb+xrHXm5Qh9ZVDV+b6x555QKTB7wlUjXi1dyZJBrDq4hsSQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 312, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ea26b57af884b6c06e348efe139c1e4e9ec9518d60c340f6bac7d278ca08d8a6", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", - "wx" : "72d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058", - "wy" : "00e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEctShnE+dLPWEjqQERbcNRpa18C1jLAxl\nTMfX7rDG0FjoxM2ZQ+RZF0x6wB+nQhmOR+bBmmvbDE9sI3gxwbP5Qg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 313, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205b1d27a7694c146244a5ad0bd0636d9d9ef3b9fb58385418d9c982105077d1b7", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", - "wx" : "2a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e7402", - "wy" : "58f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKo6i9Q3M7QwhdXW9+nzUfRxvEABB7A41\nUSeUwb5+dAJY+MFxIu0wP9pxQ+tYvt5wKVtlMmYBOwsOvT8FMTf27A==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 314, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d27a7694c146244a5ad0bd0636d9e12abe687897e8e9998ddbd4e59a78520d0f", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", - "wx" : "0088de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b8", - "wy" : "0c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiN5onOmvHpS+aiCJyKixJT/9u2yOnIYk\nm6IgABpK07gMSZjlSEL0E7ntsYJay7YzXoHk0YSysByL69yF0fKJRg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 315, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100a4f4ed29828c4894b5a17a0c6db3c256c2221449228a92dff7d76ca8206dd8dd", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", - "wx" : "00fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7", - "wy" : "00b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/qLTH3D5DV+z4A4YasQqs8FhXO5xTgtO\nETGz1NgiW/ewN6GN8qwVND8w90Bn3fKegX1fd/jc4FcU2lnAlPDNqQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 316, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220694c146244a5ad0bd0636d9e12bc9e09e60e68b90d0b5e6c5dddd0cb694d8799", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", - "wx" : "7258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db", - "wy" : "17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDt\nzLNrbO6lo9sXrCuJknkRKPo7ltwvvUyjv6eC7ygy/GZWlD2xjnNGsA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 317, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203d7f487c07bfc5f30846938a3dcef696444707cf9677254a92b06c63ab867d22", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", - "wx" : "4f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914", - "wy" : "00c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyhGHepkR01rs00Umcl9N7npVjPfHO7q\nrNRQFsmLORTIgYgQuMwG3bQOihJhxSj6pYlFXVpt+Tt3vF4OSTx0cA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 318, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206c7648fc0fbf8a06adb8b839f97b4ff7a800f11b1e37c593b261394599792ba4", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", - "wx" : "74f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66", - "wy" : "00eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEdPKoFPtdjsqRppteYHEnMrOTfeMoKb6X\nTte2jFwvXWbv8PB8VvmHplf0IZYgX1iMDx2W/YpjpfI4tI9Hh4j+Ow==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 319, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0221009be363a286f23f6322c205449d320baad417953ecb70f6214e90d49d7d1f26a8", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", - "wx" : "195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6a", - "wy" : "00b2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGVtRp8xKIbgnSnCpDed5gUw8jKNYMoII\nwJop8za4LWqyQWt8kv/9wpw7EoLdKnek0E3390UgRzk9hJmJxc7prQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 320, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022029798c5c45bdf58b4a7b2fdc2c46ab4af1218c7eeb9f0f27a88f1267674de3b0", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", - "wx" : "622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa", - "wy" : "736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYi/HRzIDS+wt3zvBbTSz0fejJ90qjBm6\ntLtP46JLWKpzay8vrnb0367MkJYzOwEyjVHrP9qckifpDQtEmYPE8A==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 321, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02200b70f22ca2bb3cefadca1a5711fa3a59f4695385eb5aedf3495d0b6d00f8fd85", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", - "wx" : "1f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c7", - "wy" : "0827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH3+FyvLXVQ56+bZQI+u03ONFAxFpIwnb\nJplpuDS2EccIJ/RbeAIOy7r0hP3Vv6rmhw8RhMIVgbr274K9e1MPkw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 322, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022016e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", - "wx" : "49c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377a", - "wy" : "00efc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEScGX3ICtHaR6Q0K5OJPo4fsLuU/DOoPn\ng8ALJMeBN3rvwg2pK6x2KVH3JHS+zHNNTMIrqBuJXigv2sTfevDzfQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 323, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202252d685e831b6cf095e4f0535eeaf0ddd3bfa91c210c9d9dc17224702eaf88f", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", - "wx" : "00d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe", - "wy" : "7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2MtoUXthalZACqOGhjXlS29plZii9hZ3\nV2VJgLr2rL5+yM9EnISaoDRhow762kFFPFfG5vvJO7xvpJrabcBVXA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 324, - "comment" : "edge case for u1", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022075135abd7c425b60371a477f09ce0f274f64a8c6b061a07b5d63e93c65046c53", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", - "wx" : "030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3", - "wy" : "00b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAwcT+2Pyqm/iyt8bIO/CWcd0Rdr6h9rD\nmLhAZco0ffOyJ4GN4aObWJywcdg+UxfMzcIzjlHjEv4x2Nw0pIAXUA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 325, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d55555555555555555555555555555547c74934474db157d2a8c3f088aced62a", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", - "wx" : "00babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7", - "wy" : "252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEurs2d7CVWALY6SmkE1VkDq8eoTU/incT\nMcSUbjSAr6clLxlsh+09KlnTsbVZE3/tABP+zvwZ+1qSaCubylG5UA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 326, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100c1777c8853938e536213c02464a936000ba1e21c0fc62075d46c624e23b52f31", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", - "wx" : "1aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60", - "wy" : "00bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGqsgGHk0cREaig6bFD/eAvyVkgeW06Y9\n4ym0JDlvumC75BMHBRdHkkQbMY06ox3+hXeCHptEbsVz0nLgNsTr6Q==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 327, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022030bbb794db588363b40679f6c182a50d3ce9679acdd3ffbe36d7813dacbdc818", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", - "wx" : "008cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff", - "wy" : "47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjLC5CUmcg+qAbNiFsd1GegEZ8GqIoCdu\nsM/aJ0U1qP9HtUKIM7w/LIv52QQRWM8zcYpplhzQFym8ABHR5YardQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 328, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202c37fd995622c4fb7fffffffffffffffc7cee745110cb45ab558ed7c90c15a2f", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", - "wx" : "008f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d", - "wy" : "3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjwPPGkInK7FTJyMJP3Lm/urIXhcA6fvp\npqLdZC10v107iacYna2M91/CL28ViqJ/nCygDaynhb4zWPK9o4YsoA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 329, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02207fd995622c4fb7ffffffffffffffffff5d883ffab5b32652ccdcaa290fccb97d", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", - "wx" : "44de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8ace", - "wy" : "00a2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERN47nHpXqMnoIJUnU0IefZh7s9efcfAT\ngFyJfgGPis6iRgdYyPmNP9zhIalDZZ43LDJv/y5fwq5/o/edquE8Eg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 330, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ffb32ac4589f6ffffffffffffffffffebb107ff56b664ca599b954521f9972fa", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", - "wx" : "6fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a", - "wy" : "0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEb7iytI4zAxJorWpRdITciDnqkPZmnqDH\nrDIz4qwxOUoKyLvn9zwv9N+ZeHJ6wd/C/VhkfSDzH5kQUxa2RnHyBA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 331, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205622c4fb7fffffffffffffffffffffff928a8f1c7ac7bec1808b9f61c01ec327", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", - "wx" : "00bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6", - "wy" : "00f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvqcRIqBIaT6QX/YCs8+d0Yr2m5/J2EMd\nKx3Sa5Qsleb0PHuLletiCCwS2529p/445Fy+SkiGkH+4G9sMXqkkbA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 332, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022044104104104104104104104104104103b87853fd3b7d3f8e175125b4382f25ed", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", - "wx" : "00da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156", - "wy" : "00e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2pGMcxugaiDLlO8zt3jpgaQEowXxlB/j\nNma0WwM1MVbiuyaU9XW0UYO+eOXJtSEL879Ij9TIKUUW2JVyyk9TkQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 333, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202739ce739ce739ce739ce739ce739ce705560298d1f2f08dc419ac273a5b54d9", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", - "wx" : "3007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d", - "wy" : "5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMAfpLDk32t55ZN+jWw7/Ax9+sCrtCgMU\nQREGzetw/j1adUb8BVKZeyDj1vQT514stm4RYyJpcRS3m6xzS/xNxQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 334, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100b777777777777777777777777777777688e6a1fe808a97a348671222ff16b863", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", - "wx" : "60e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9b", - "wy" : "00d2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ\n/fmNvc0YzpvS2Qs6wx8TmvgyzM9sy7ssbqEfqXNw3JkG2kdNfYp1Zw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 335, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206492492492492492492492492492492406dd3a19b8d5fb875235963c593bd2d3", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", - "wx" : "0085a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba337", - "wy" : "69744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEhakA6XhY9pPAt9+iYeOA2tbqBG0fZd3u\n7dX32K8LozdpdE0VrdT2wLw7DaKuyTs0y4xl+TQN33TnsACe7szOPA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 336, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100955555555555555555555555555555547c74934474db157d2a8c3f088aced62c", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", - "wx" : "38066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046", - "wy" : "00a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOAZvddiO/EyT3jb0ngN7I0zBix3lYIdQ\npiyrA0VAEEaj6EvtjPy4Ge9NVQRE8s5LZRdmtp4uKQH4iDb/kANP7Q==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 337, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", - "wx" : "0098f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabf", - "wy" : "00a33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmPaBd9yVwbTL+lJFSIylI6fVYpRw0DXW\nIaRDxy85qr+jPSlUb6HGSPLH1cz3DPHOSrebXbGsBZ2+zQaNvf8biQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 338, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100bffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", - "wx" : "5c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277", - "wy" : "00e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEXCu/ojybmtB/A4qom0kwvyZ9lAHkJV3p\n6NoKUHjsgnfj6IKjHV5qN54Hk5g8ze05uVxDU6sv8B6lNpukewwxkQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 339, - "comment" : "edge case for u2", - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220185ddbca6dac41b1da033cfb60c152869e74b3cd66e9ffdf1b6bc09ed65ee40c", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", - "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", - "wy" : "3547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4U1R4CCmESO215wGt6EzV+xrJVnul6Ptoprkz7EtcyEzA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 340, - "comment" : "point duplication during verification", - "msg" : "313233343030", - "sig" : "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", - "result" : "valid", - "flags" : [ - "PointDuplication" - ] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", - "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", - "wy" : "00cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4XKuH99Z7txJKGP5SF7MqBOU2qYRaFwSXWUbME6SjN3Yw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 341, - "comment" : "duplication bug", - "msg" : "313233343030", - "sig" : "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", - "result" : "invalid", - "flags" : [ - "PointDuplication" - ] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", - "wx" : "008aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e", - "wy" : "1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiqLGT6nGQ3Vjq/vL0AsgSNSMGMFSoqb0\nkDbedkfr6C4c5kOHmVxooGD6O8A5mwXMBu7H1Zj3UEGkkX5pK39R/w==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 342, - "comment" : "comparison with point at infinity ", - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0022033333333333333333333333333333332f222f8faefdb533f265d461c29a47373", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", - "wx" : "391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71f", - "wy" : "00dd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEORQn/37ngBPBSux9lqigYiCSmKeDg16U\n/WVJ1QL/9x/dZiTsNDrZ/PTZhyGB5Z+EL5ukzMrgmmwJcvtqxrTGvQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 343, - "comment" : "extreme value for k and edgecase s", - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", - "wx" : "00e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138e", - "wy" : "00c1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4\nnHo0uJ6ME47BUz7wQZu3N24L/ekxnRCgaWh5HZ6g7tnBzmNFrtl1ng==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 344, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", - "wx" : "009aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952", - "wy" : "00fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmu2w0oHbFk4TAADFaX+uDzBe+Ei+b/+0\nOsWT+7lQ6VL6b2MzWb3NgrVrC5+WWwN3idRrmoFBt5GyrvpxP5bBdQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 345, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", - "wx" : "008ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee", - "wy" : "1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEitRF22KBYmDk5of9GITki5/AY20DFUfW\nMxXnkuGb+u4d5k+Z1fHNi27Jyw94emVK6GmTuj2xAI70PP8GhMsivQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 346, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", - "wx" : "1f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32", - "wy" : "00e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH1eZyVvokGOyTybkDLkowahop2+wCUYH\n6AQ9tAnJHDLnVyToE6QZHjqDkAfwji6Jc4iwbUoA3m3mDlNtkfq1Zg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 347, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", - "wx" : "00a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc", - "wy" : "28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEozMaThtCI+wsAn7dSCySihTtNY2T8dQh\nfTmr9p/LXMwo1oTSqqvNY4N3XKpiOd4m1MaTe7YD7LQZYIL0z/1QnQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 348, - "comment" : "extreme value for k", - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", - "wx" : "3f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb24818", - "wy" : "5ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPzlSGZd0x885s4tmyxBCpiYNhoCAOEXk\n1DOtujuySBhepJW2jLx+1Bc+5jyQQtxQJiXH634h+wLKmpEU4KOhjQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 349, - "comment" : "extreme value for k and edgecase s", - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", - "wx" : "00cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e", - "wy" : "054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzfuMD0IuFE4TfCQSyGwXH1/j+j9bu1RO\nkHYojzzteG4FT9ByG3fBHHm+rLPJQhGwoZvaCGUu/q+SUTo7ChY2mA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 350, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", - "wx" : "73598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3", - "wy" : "00cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc1mKahxoJ4+mv9DOQGTmgjW8HA9rIKko\nEIvjNnMPh+PLrmElGbUDLsyFrtgRJxqV/nk51dNGAUC6MY9NFKujHQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 351, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", - "wx" : "58debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a1", - "wy" : "6773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWN69mn7iydWRMkeKVECuTV1+1Dcwg2n5\nLqhsghg/EKFnc+dvXtv02g5PG9/6wPVyV+HfpGWEKTEwmiQkX9pqXQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 352, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", - "wx" : "008b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b", - "wy" : "00950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEi5BN5HlnNAxfjDVypyCSTvdXhjf+qxlJ\nrLJBpaasP1uVCQRJb5gksdY/MxO64huJ+uia/fyBG17OA/1aowGGTw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 353, - "comment" : "extreme value for k and s^-1", - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", - "wx" : "00f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a", - "wy" : "346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9IkrbVJcdx4DXyolJwjzeE5II4YEtPlN\nxW6qHlRtlBo0axqgvOaLHFDltS9Qn7VSLlwl4Ci8j4Y0Au23vK2LGw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 354, - "comment" : "extreme value for k", - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "wy" : "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuA==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 355, - "comment" : "testing point duplication", - "msg" : "313233343030", - "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 356, - "comment" : "testing point duplication", - "msg" : "313233343030", - "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", - "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "wy" : "00b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5i3xSWI2Vw7mqJbBAPx7vdXAuhLt1l6q+ZjuC9vBO8ndw==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 357, - "comment" : "testing point duplication", - "msg" : "313233343030", - "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid", - "flags" : [] - }, - { - "tcId" : 358, - "comment" : "testing point duplication", - "msg" : "313233343030", - "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", - "wx" : "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", - "wy" : "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 359, - "comment" : "pseudorandom signature", - "msg" : "", - "sig" : "3046022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 360, - "comment" : "pseudorandom signature", - "msg" : "4d7367", - "sig" : "30450220109cd8ae0374358984a8249c0a843628f2835ffad1df1a9a69aa2fe72355545c022100ac6f00daf53bd8b1e34da329359b6e08019c5b037fed79ee383ae39f85a159c6", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 361, - "comment" : "pseudorandom signature", - "msg" : "313233343030", - "sig" : "3045022100d035ee1f17fdb0b2681b163e33c359932659990af77dca632012b30b27a057b302201939d9f3b2858bc13e3474cb50e6a82be44faa71940f876c1cba4c3e989202b6", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 362, - "comment" : "pseudorandom signature", - "msg" : "0000000000000000000000000000000000000000", - "sig" : "304402204f053f563ad34b74fd8c9934ce59e79c2eb8e6eca0fef5b323ca67d5ac7ed23802204d4b05daa0719e773d8617dce5631c5fd6f59c9bdc748e4b55c970040af01be5", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", - "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", - "wy" : "01060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv8AAAABBgSS1aVnPg8l2NUPt+WMSdhtRtQhaVXgqj1A4Q==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 363, - "comment" : "y-coordinate of the public key is small", - "msg" : "4d657373616765", - "sig" : "304402206d6a4f556ccce154e7fb9f19e76c3deca13d59cc2aeb4ecad968aab2ded45965022053b9fa74803ede0fc4441bf683d56c564d3e274e09ccf47390badd1471c05fb7", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 364, - "comment" : "y-coordinate of the public key is small", - "msg" : "4d657373616765", - "sig" : "3046022100aad503de9b9fd66b948e9acf596f0a0e65e700b28b26ec56e6e45e846489b3c4022100fff223c5d0765447e8447a3f9d31fd0696e89d244422022ff61a110b2a8c2f04", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 365, - "comment" : "y-coordinate of the public key is small", - "msg" : "4d657373616765", - "sig" : "30460221009182cebd3bb8ab572e167174397209ef4b1d439af3b200cdf003620089e43225022100abb88367d15fe62d1efffb6803da03109ee22e90bc9c78e8b4ed23630b82ea9d", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", - "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", - "wy" : "00fffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv/////++fttKlqYwfDaJyrwSBpztieSuSvelqoeVcK7Tg==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 366, - "comment" : "y-coordinate of the public key is large", - "msg" : "4d657373616765", - "sig" : "304502203854a3998aebdf2dbc28adac4181462ccac7873907ab7f212c42db0e69b56ed8022100c12c09475c772fd0c1b2060d5163e42bf71d727e4ae7c03eeba954bf50b43bb3", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 367, - "comment" : "y-coordinate of the public key is large", - "msg" : "4d657373616765", - "sig" : "3046022100e94dbdc38795fe5c904d8f16d969d3b587f0a25d2de90b6d8c5c53ff887e3607022100856b8c963e9b68dade44750bf97ec4d11b1a0a3804f4cb79aa27bdea78ac14e4", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 368, - "comment" : "y-coordinate of the public key is large", - "msg" : "4d657373616765", - "sig" : "3044022049fc102a08ca47b60e0858cd0284d22cddd7233f94aaffbb2db1dd2cf08425e102205b16fca5a12cdb39701697ad8e39ffd6bdec0024298afaa2326aea09200b14d6", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", - "wx" : "013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0", - "wy" : "00f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAAAAAT/SIkjWTZX3PCm0irSGMYUL5QP9\nAPhGi18PcOD27nqkO8LG/SWx2CaSQcvdnbsNrJbcliMfQwcF+DhxfQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 369, - "comment" : "x-coordinate of the public key is small", - "msg" : "4d657373616765", - "sig" : "3045022041efa7d3f05a0010675fcb918a45c693da4b348df21a59d6f9cd73e0d831d67a022100bbab52596c1a1d9484296cdc92cbf07e665259a13791a8fe8845e2c07cf3fc67", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 370, - "comment" : "x-coordinate of the public key is small", - "msg" : "4d657373616765", - "sig" : "3046022100b615698c358b35920dd883eca625a6c5f7563970cdfc378f8fe0cee17092144c022100da0b84cd94a41e049ef477aeac157b2a9bfa6b7ac8de06ed3858c5eede6ddd6d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 371, - "comment" : "x-coordinate of the public key is small", - "msg" : "4d657373616765", - "sig" : "304602210087cf8c0eb82d44f69c60a2ff5457d3aaa322e7ec61ae5aecfd678ae1c1932b0e022100c522c4eea7eafb82914cbf5c1ff76760109f55ddddcf58274d41c9bc4311e06e", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "0425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", - "wx" : "25afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dffffffff", - "wy" : "00fa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJa/WiayrrtZ8Hylt5ZQG+MVQ9XFGoLTs\nLJeHbf/////6RqduUgMi37xJHsTwzBl0IPxOpYg9j23VPDVLxPZ8NQ==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 372, - "comment" : "x-coordinate of the public key has many trailing 1's", - "msg" : "4d657373616765", - "sig" : "3045022062f48ef71ace27bf5a01834de1f7e3f948b9dce1ca1e911d5e13d3b104471d82022100a1570cc0f388768d3ba7df7f212564caa256ff825df997f21f72f5280d53011f", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 373, - "comment" : "x-coordinate of the public key has many trailing 1's", - "msg" : "4d657373616765", - "sig" : "3046022100f6b0e2f6fe020cf7c0c20137434344ed7add6c4be51861e2d14cbda472a6ffb40221009be93722c1a3ad7d4cf91723700cb5486de5479d8c1b38ae4e8e5ba1638e9732", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 374, - "comment" : "x-coordinate of the public key has many trailing 1's", - "msg" : "4d657373616765", - "sig" : "3045022100db09d8460f05eff23bc7e436b67da563fa4b4edb58ac24ce201fa8a358125057022046da116754602940c8999c8d665f786c50f5772c0a3cdbda075e77eabc64df16", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "04d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", - "wx" : "00d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb9", - "wy" : "3f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0S5sZrZ3NMPITSYBz1013Al+J2N/CspK\nT9t0tqrdO7k/W9/4i9VzbfiY5pkAbtdQ8RzwfFhmzXrXDHEh/////w==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 375, - "comment" : "y-coordinate of the public key has many trailing 1's", - "msg" : "4d657373616765", - "sig" : "30450220592c41e16517f12fcabd98267674f974b588e9f35d35406c1a7bb2ed1d19b7b8022100c19a5f942607c3551484ff0dc97281f0cdc82bc48e2205a0645c0cf3d7f59da0", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 376, - "comment" : "y-coordinate of the public key has many trailing 1's", - "msg" : "4d657373616765", - "sig" : "3046022100be0d70887d5e40821a61b68047de4ea03debfdf51cdf4d4b195558b959a032b20221008266b4d270e24414ecacb14c091a233134b918d37320c6557d60ad0a63544ac4", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 377, - "comment" : "y-coordinate of the public key has many trailing 1's", - "msg" : "4d657373616765", - "sig" : "3046022100fae92dfcb2ee392d270af3a5739faa26d4f97bfd39ed3cbee4d29e26af3b206a02210093645c80605595e02c09a0dc4b17ac2a51846a728b3e8d60442ed6449fd3342b", - "result" : "valid", - "flags" : [] - } - ] - }, - { - "key" : { - "curve" : "secp256k1", - "keySize" : 256, - "type" : "EcPublicKey", - "uncompressed" : "046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", - "wx" : "6d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000", - "wy" : "00e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb" - }, - "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", - "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbUp/YNR3Sk8KqLve25U8fup5CUB+MWR1\nVmS8KAAAAADmWdNOTfONnoyeqt+6NmEsdpGVvobHeqw/NueLU4aA+w==\n-----END PUBLIC KEY-----", - "sha" : "SHA-256", - "type" : "EcdsaVerify", - "tests" : [ - { - "tcId" : 378, - "comment" : "x-coordinate of the public key has many trailing 0's", - "msg" : "4d657373616765", - "sig" : "30450220176a2557566ffa518b11226694eb9802ed2098bfe278e5570fe1d5d7af18a943022100ed6e2095f12a03f2eaf6718f430ec5fe2829fd1646ab648701656fd31221b97d", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 379, - "comment" : "x-coordinate of the public key has many trailing 0's", - "msg" : "4d657373616765", - "sig" : "3045022060be20c3dbc162dd34d26780621c104bbe5dace630171b2daef0d826409ee5c2022100bd8081b27762ab6e8f425956bf604e332fa066a99b59f87e27dc1198b26f5caa", - "result" : "valid", - "flags" : [] - }, - { - "tcId" : 380, - "comment" : "x-coordinate of the public key has many trailing 0's", - "msg" : "4d657373616765", - "sig" : "3046022100edf03cf63f658883289a1a593d1007895b9f236d27c9c1f1313089aaed6b16ae022100e5b22903f7eb23adc2e01057e39b0408d495f694c83f306f1216c9bf87506074", - "result" : "valid", - "flags" : [] - } - ] - } - ] -} diff --git a/test/wycheproof/ecdh_secp256k1_test.json b/test/wycheproof/ecdh_secp256k1_test.json new file mode 100644 index 0000000..16db618 --- /dev/null +++ b/test/wycheproof/ecdh_secp256k1_test.json @@ -0,0 +1,8441 @@ +{ + "algorithm" : "ECDH", + "schema" : "ecdh_test_schema.json", + "generatorVersion" : "0.9rc5", + "numberOfTests" : 752, + "header" : [ + "Test vectors of type EcdhTest are intended for", + "testing an ECDH implementations using X509 encoded", + "public keys and integers for private keys.", + "Test vectors of this format are useful for testing", + "Java providers." + ], + "notes" : { + "AdditionChain" : { + "bugType" : "KNOWN_BUG", + "description" : "The private key has an unusual bit pattern, such as high or low Hamming weight. The goal is to test edge cases for addition chain implementations." + }, + "CompressedPoint" : { + "bugType" : "UNKNOWN", + "description" : "The point in the public key is compressed. Not every library supports points in compressed format." + }, + "CompressedPublic" : { + "bugType" : "FUNCTIONALITY", + "description" : "The public key in the test vector is compressed. Some implementations do not support compressed points." + }, + "EdgeCaseDoubling" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains an EC point that hits an edge case (e.g. a coordinate 0) when doubled. The goal of the test vector is to check for arithmetic errors in these test cases.", + "effect" : "The effect of such arithmetic errors is unclear and requires further analysis." + }, + "EdgeCaseEphemeralKey" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains an ephemeral public key that is an edge case." + }, + "EdgeCaseSharedSecret" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains a public key and private key such that the shared ECDH secret is a special case. The goal of this test vector is to detect arithmetic errors.", + "effect" : "The seriousness of an arithmetic error is unclear. It requires further analysis to determine if the bug is exploitable." + }, + "InvalidAsn" : { + "bugType" : "UNKNOWN", + "description" : "The public key in this test uses an invalid ASN encoding. Some cases where the ASN parser is not strictly checking the ASN format are benign as long as the ECDH computation still returns the correct shared value." + }, + "InvalidCompressedPublic" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The test vector contains a compressed public key that does not exist. I.e., it contains an x-coordinate that does not correspond to any points on the curve. Such keys should be rejected " + }, + "InvalidCurveAttack" : { + "bugType" : "CONFIDENTIALITY", + "description" : "The point of the public key is not on the curve. ", + "effect" : "If an implementation does not check whether a point is on the curve then it is likely that the implementation is susceptible to an invalid curve attack. Many implementations compute the shared ECDH secret over a curve defined by the point on the public key. This curve can be weak and hence leak information about the private key." + }, + "InvalidEncoding" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The test vector contains a public key with an invalid encoding." + }, + "InvalidPublic" : { + "bugType" : "CAN_OF_WORMS", + "description" : "The public key has been modified and is invalid. An implementation should always check whether the public key is valid and on the same curve as the private key. The test vector includes the shared secret computed with the original public key if the public point is on the curve of the private key.", + "effect" : "Generating a shared secret other than the one with the original key likely indicates that the bug is exploitable." + }, + "LargeCofactor" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The cofactor is larger than the limits specified in FIPS-PUB 186-4 table 1, p.36." + }, + "Modified curve parameter" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The parameters a and b of the curve have been modified. The parameters haven been chosen so that public key or generator still are also valid points on the new curve." + }, + "ModifiedCofactor" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The cofactor has been modified. ", + "effect" : "The seriousness of accepting a key with modified cofactor depends on whether the primitive using the key actually uses the cofactor." + }, + "ModifiedGenerator" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The generator of the EC group has been modified.", + "effect" : "The seriousness of the modification depends on whether the cryptographic primitive uses the generator. In the worst case such a modification allows an invalid curve attack." + }, + "ModifiedGroup" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The EC curve of the public key has been modified. EC curve primitives should always check that the keys are on the expected curve." + }, + "ModifiedPrime" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The modulus of the public key has been modified. The public point of the public key has been chosen so that it is both a point on both the curve of the modified public key and the private key." + }, + "ModifiedPublicPoint" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The public point of the key has been modified and is not on the curve.", + "effect" : "Not checking that a public point is on the curve may allow an invalid curve attack." + }, + "NegativeCofactor" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The cofactor of the curve is negative." + }, + "Normal" : { + "bugType" : "BASIC", + "description" : "The test vector contains a pseudorandomly generated, valid test case. Implementations are expected to pass this test." + }, + "UnnamedCurve" : { + "bugType" : "UNKNOWN", + "description" : "The public key does not use a named curve. RFC 3279 allows to encode such curves by explicitly encoding, the parameters of the curve equation, modulus, generator, order and cofactor. However, many crypto libraries only support named curves. Modifying some of the EC parameters and encoding the corresponding public key as an unnamed curve is a potential attack vector." + }, + "UnusedParam" : { + "bugType" : "MALLEABILITY", + "description" : "A parameter that is typically not used for ECDH has been modified. Sometimes libraries ignore small differences between public and private key. For example, a library might ignore an incorrect cofactor in the public key. We consider ignoring such changes as acceptable as long as these differences do not change the outcome of the ECDH computation, i.e. as long as the computation is done on the curve from the private key." + }, + "WeakPublicKey" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The vector contains a weak public key. The curve is not a named curve, the public key point has order 3 and has been chosen to be on the same curve as the private key. This test vector is used to check ECC implementations for missing steps in the verification of the public key." + }, + "WrongCurve" : { + "bugType" : "CONFIDENTIALITY", + "description" : "The public key and private key use distinct curves. Implementations are expected to reject such parameters.", + "effect" : "Computing an ECDH key exchange with public and private keys can in the worst case lead to an invalid curve attack. Hence, it is important that ECDH implementations check the input parameters. The severity of such bugs is typically smaller if an implementation ensures that the point is on the curve and that the ECDH computation is performed on the curve of the private key. Some of the test vectors with modified public key contain shared ECDH secrets, that were computed over the curve of the private key." + }, + "WrongOrder" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The order of the public key has been modified.", + "effect" : "If this order is used in a cryptographic primitive instead of the correct order then an invalid curve attack is possible and the private keys may leak. E.g. ECDHC in BC 1.52 suffered from this." + } + }, + "testGroups" : [ + { + "type" : "EcdhTest", + "curve" : "secp256k1", + "encoding" : "asn", + "tests" : [ + { + "tcId" : 1, + "comment" : "normal case", + "flags" : [ + "Normal" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b396812ea1686e7472e9692eaf3e958e50e9500d3b4c77243db1f2acd67ba9cc4", + "private" : "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", + "shared" : "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", + "result" : "valid" + }, + { + "tcId" : 2, + "comment" : "compressed public key", + "flags" : [ + "CompressedPublic", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a03220002d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b", + "private" : "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", + "shared" : "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", + "result" : "acceptable" + }, + { + "tcId" : 3, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 1", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004965ff42d654e058ee7317cced7caf093fbb180d8d3a74b0dcd9d8cd47a39d5cb9c2aa4daac01a4be37c20467ede964662f12983e0b5272a47a5f2785685d8087", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000000001", + "result" : "valid" + }, + { + "tcId" : 4, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 4", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000406c4b87ba76c6dcb101f54a050a086aa2cb0722f03137df5a922472f1bdc11b982e3c735c4b6c481d09269559f080ad08632f370a054af12c1fd1eced2ea9211", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000000002", + "result" : "valid" + }, + { + "tcId" : 5, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 9", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bba30eef7967a2f2f08a2ffadac0e41fd4db12a93cef0b045b5706f2853821e6d50b2bf8cbf530e619869e07c021ef16f693cfc0a4b0d4ed5a8f464692bf3d6e", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000000003", + "result" : "valid" + }, + { + "tcId" : 6, + "comment" : "shared secret has x-coordinate p-3", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046da9eb2cdac02122d5f05cf6a8cd768e378f664ea4a7871d10e25f57eb1ee1cc5b2b5abf9c6c6596f8f383ddbcb3bcc2d5a7cc605984931239ca9669946032ee", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c", + "result" : "valid" + }, + { + "tcId" : 7, + "comment" : "shared secret has x-coordinate 2**16 + 0", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f2976154c4f53ce392d1fe39a891a4611ba8cf046023cd8f1bcd9fdd2e921191b25cf31caedfbb415381637bc3f599a34fba3e1413f644cb1668469f4558a772", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000010000", + "result" : "valid" + }, + { + "tcId" : 8, + "comment" : "shared secret has x-coordinate 2**32 + 7", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045e422fea67cca5ebaeac87745c81b10ef807030367e6fce012254176ec8cf199881592f42c264371e19e3037388ab64f32fa8870e62905e7af205e43b02aad12", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000100000007", + "result" : "valid" + }, + { + "tcId" : 9, + "comment" : "shared secret has x-coordinate 2**64 + 1", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bb57b9a1231be042d185c03eda6926a6def177fe6745eda000c520d66581f0cdf1d73c80453f2fe30725adf951390c739e36fc8677691db107881342613d00ab", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000010000000000000001", + "result" : "valid" + }, + { + "tcId" : 10, + "comment" : "shared secret has x-coordinate 2**96 + 1", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045563c76c19377638f7d517bdbe0ace467eb5d4dd9fb4bf18332bab8f07b1d80c261332d46e316711278bacccd88005ee4c115fa84089fd190674626e5ed1ebfe", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000001000000000000000000000001", + "result" : "valid" + }, + { + "tcId" : 11, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = -6", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048983aae8c002f2b555acb2370adb9b50ba4cac1bfcc9039a125c70ca7c5fc0d1f6efeb8ae4ba8c69429d93244382447ac534891c66090025282655719bd72512", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0b7beba34feb647da200bed05fad57c0348d249e2a90c88f31f9948bb65d5207", + "result" : "valid" + }, + { + "tcId" : 12, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000423556564850c50fba51f1e64ef98378ef5c22feafa29499ca27600c473cace889d5679e917daa7f4c7899517d37826284f031de01a60bc813696414d04531a21", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f7", + "result" : "valid" + }, + { + "tcId" : 13, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 8", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ddbf807e22c56a19cf6c472829150350781034a5eddec365694d4bd5c865ead14e674127028c91d3394cac37293a866055d10f0f40a3706ad16b64fc9d5998bd", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "result" : "valid" + }, + { + "tcId" : 14, + "comment" : "shared secret has x-coordinate that satisfies x**2 = 2**96 + 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000464688eae7aabd248f6f44a0d6e2c438e4100001813eb71f9f082fad3dfe43e287dab3dabe7d436001a0fb763015dedbb90f811000ec8f5f29953e3af42f92065", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "39f883f105ac7f09f4e7e4dcc84bc7ff4b3b74f301efaaaf8b638f47720fdaec", + "result" : "valid" + }, + { + "tcId" : 15, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c404e17141d102bba2f1cb16bb954a208798b04dca8dd139a8ab7f01f0dbef39c7b8e55f2257a480077e4190570a004cbe668200c9c78eaa53b61b20fce4c685", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "5555555555555555555555555555555555555555555555555555555555555550", + "result" : "valid" + }, + { + "tcId" : 16, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e160e87c0a562a1dbb59b4c2f614720e7753608672eb8d883b91e25f8cfc58474623cba584e1324bc49bcdf0891166b545b7704e2bbda705d0d73b7530e47952", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "result" : "valid" + }, + { + "tcId" : 17, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045d4d182b18782a02685dcc7b671ec742ce308c7acc8e6260f67e81516eb546e8a38f0756074eea4857953398b6d05597c7ceb5e65e4e8cee31e81c5658824ce4", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "3333333333333333333333333333333333333333333333333333333333333333", + "result" : "valid" + }, + { + "tcId" : 18, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048ecd6a2576f42626792076935e2fe961599e484cd212bce2623b83aa22f546d2a7f855b09bef286bcbe9e8bab17fd56d7055df64f344310c3522e8f227e472c8", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccb", + "result" : "valid" + }, + { + "tcId" : 19, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046826f79ef84da803460aed09198d2bbb42d7892ed608aacbb281a95acae11465a25809191aa5bdfa61b8963beacb4eb133266a90f33d1b2ca4f6152d37a94fd8", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0c", + "result" : "valid" + }, + { + "tcId" : 20, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a54bb2ae80086053a5fa4fdb1836a8c6ac41783650b0f79a5428c98ff64d078a12bbb4cb8af20ca75ec15b2e0d47a83ca93fc78cd92640a02e8002966f1fe80b", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0", + "result" : "valid" + }, + { + "tcId" : 21, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bace46eed492743c693e1a33adb046b7722c55ce369d1438e67f9c5b3412783145262dd4a86c8a527b23f4114b8a9b9f36f9701835f50b678b24d2a9155ebc2c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff", + "result" : "valid" + }, + { + "tcId" : 22, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000401055147863aa060c0e104e243ec01eda2b0e0c6814e232d671abcba9715d5ce0c13006aa7960c54fe3f20220bef766756c910fd05764afc318375540cef2d5c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00", + "result" : "valid" + }, + { + "tcId" : 23, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004595e46ee7c2d7183ff2ea760ffd8472fb834ec89c08b6ef48ff92b44a13a6e1ae563e23953c97c26441323d2500c84e8cee04c15d4d5d2cc458703d1f2d02d31", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "7fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff", + "result" : "valid" + }, + { + "tcId" : 24, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046a40adc811b09e83ba0fb8a94fea50591ca9e58bb7d47304950dbff78dad777ee3bd08f742d7e8e30cff31bc6a6cc02c8717ee25838aabffa6e48f65cce74d81", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000fffe0003fff8000fffe0003fff8000fffe0003fff8000fffe0003fff7fff", + "result" : "valid" + }, + { + "tcId" : 25, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045a33fe91d7e35db7875208bee77f4cc0006f1439cc845f695b6a12673dcd03d18f86ee121c5ea0da3eb0210509e12db845296225ca973e2e19ce3e3d01486090", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffd", + "result" : "valid" + }, + { + "tcId" : 26, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f6ebaab62c35fd4b8bec9d95bcfc433e6bde7c0f0d5ef75d6fd326aaf28f23b0b2f4d1c2e891706b7bada59fb0f6a32b5463982a9c8c2d8ea38954418183b634", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffefffe", + "result" : "valid" + }, + { + "tcId" : 27, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004524392416f8cfc5f84dc9b72f2887c684e4bd24796f0065078e18d16bc43b56ea02178311799eb61ad3b3e7dcda10404dc4541c13e3de0ceb40c9aa7afabc53b", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000003ffffff0000007fffffe000000ffffffc000001ffffff8000003fffffd", + "result" : "valid" + }, + { + "tcId" : 28, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000499965c477a240aebbd19cd094c8b62852de8663d0cc9f06eeb395ffc92d121f64811882f406080d7d04ea4f339bddd2e5ef0345b5834142f75b562154d5ec7ae", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "7fffffe000000ffffffc000001ffffff8000003ffffff0000007fffffdfffffe", + "result" : "valid" + }, + { + "tcId" : 29, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ad3d179877e74ee258ba6f8e128bc2a0045c06a3d3c30fcce01ca8d9e1afee4ea3fe47156fb727fc1c55ef9db516df665cbb073405c2c301a8fe1d10f3b9b300", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "000003ffffff0000003ffffff0000003ffffff0000003ffffff0000003fffffc", + "result" : "valid" + }, + { + "tcId" : 30, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044bb19deae638fc5fa7070cc90e969bac3f8384a59ea11cb01bc091edf1a4cbd677ed6bdf8971d3e63c903d9acabc28b75af661a03457261c5a8d5940ad02c509", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "fffffc000000ffffffc000000ffffffc000000ffffffc000000ffffffbfffffe", + "result" : "valid" + }, + { + "tcId" : 31, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000424175c078e305d3139e5dab727a6ab8587b26daa470a529a23c10585cb56c038bf1f2b937ae074ff94b15f5cb5e60eb5d32afba2077539db794294bcaab71a81", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff", + "result" : "valid" + }, + { + "tcId" : 32, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ef691afe2ee4aa18a8485a71c0e20eff1337ae0622acc09ccda10f49574ae840b82730bb2eef59a17ab095acd131e5fcf8ba11150a9421bbab6b9f146aa78ffb", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000fffffffc0000000fffffffc0000000fffffffc0000000fffffffbffffffd", + "result" : "valid" + }, + { + "tcId" : 33, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004067e7df09f5e38f2b2823f65a6b1135c3290586fef6eceffa6d59595748879f66932b3f70d603229e10a57344ecde503a2df930651046c2f1d2b719bfc93e0a1", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ff00000001fffffffc00000007fffffff00000001fffffffc00000007ffffffd", + "result" : "valid" + }, + { + "tcId" : 34, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b8722ecdde7c85317e486b03656b83910ac3c88687a4291e8bb9a4b6a52cc6e02e4158a5a88de023d6a135bd04c1585ef46741890376135453ec562da5b3760b", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00fffffffe00000003fffffff80000000fffffffe00000003fffffff80000000", + "result" : "valid" + }, + { + "tcId" : 35, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004728e15d578212bc42287c0118c82c84b126f97d549223c10ad07f4e98af912385d23b1a6e716925855a247b16effe92773315241ac951cdfefdfac0ed16467f6", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", + "result" : "valid" + }, + { + "tcId" : 36, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c3ef35fd4cda66e8e850095e1e697aee56decc29484aa463f879c7b6dd7669e625945351276719c5e3bb8e514f69305b6085b7c782a07b26a842887c33a93dc6", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffffffff00000000ffffffff00000000ffffffff00000000fffffffeffffffff", + "result" : "valid" + }, + { + "tcId" : 37, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004784907c6be6202770b98d01f1ffe11b9ed2c97515843f57c2c06363a9dadc7011de5fbaa7356cf3ba28cb7b932a07c8321007c7c45396751fe70724343d2b19f", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffffffff00000000000000ffffffffffffff00000000000000fffffffffffffe", + "result" : "valid" + }, + { + "tcId" : 38, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047c016dee8b5411f8e95184daf8e318119e844b8bdc70d75efb99b8d0ff10ab745e905103d57d6537908e6e9864aee4f0917f5b920d06f980aa823f043ef9139e", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00000000ffffffffffffff00000000000000ffffffffffffff00000000000000", + "result" : "valid" + }, + { + "tcId" : 39, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000436e1e76ffdbe8577520b0716eb88c18ea72a49e5a4e5680a7d290093f841cb6e7310728b59c7572c4b35fb6c29c36ebabfc53553c06ecf747fcfbefcf6114e1c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 40, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047a19501d646fc9332a8525af4cc79523b57d736b69bb24b06270c1b1dadf88ce834efa1bce854ff5bcade40cbcee9f40154bc26036adc5cf87e50ea388af2987", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffffffffffffffff0000000000000000fffffffffffffffefffffffffffffff5", + "result" : "valid" + }, + { + "tcId" : 41, + "comment" : "shared secret has an x-coordinate of approx p//3", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f43b610a2a5c5f6e2b395567489657059e3351c6f9a7e2ebde52638abfea006ab2d690513e9187c0cc903ceee022ee421c594a8bd7610c68cd8143adfc741dde", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "55555555555555555555555555555555555555555555555555555554fffffebc", + "result" : "valid" + }, + { + "tcId" : 42, + "comment" : "shared secret has an x-coordinate of approx p//5", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d93bfdaa797cd4bd81dea80d7c72a24923ce50e94bfc4ee1bd5f5f10eea3f8ecc0b5941890a26e88e5029c283e0fadeccc0b980f8a5098aa7835c5c958d471e5", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "33333333333333333333333333333333333333333333333333333332ffffff3c", + "result" : "valid" + }, + { + "tcId" : 43, + "comment" : "shared secret has an x-coordinate of approx p//7", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040ac1ea7a29f7ace8a38b2fedbfe4d0d9ae45344432ab3eb5e0a5b66716f61c6aaaa39a5f098fd4472587d14bdf72b3dd3e966b5f0b6e400fff6e0e9c8453fc79", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "249249249249249249249249249249249249249249249249249249246db6dae2", + "result" : "valid" + }, + { + "tcId" : 44, + "comment" : "shared secret has an x-coordinate of approx p//9", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf2e8a61a21d96e74a296b397e53044f373acb73a6ea4a398d89c56549e96b7fe846fd0df239691d0682b067a50a2423d88b4d970b1d3d8141a066d13c186f96", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "1c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c555554e8", + "result" : "valid" + }, + { + "tcId" : 45, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000456baf1d72606c7af5a5fa108620b0839e2c7dd40b832ef847e5b64c86efe1aa563e586a667a65bbb5692500df1ff8403736838b30ea9791d9d390e3dc6689e2c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 46, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff07ed353c9f1039edcc9cc5336c034dc131a4087692c2e56bc1dd1904e3ffffff", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "7c07b199b6a62e7ac646c7e1dee94aca55de1a97251ddf92fcd4fe0145b40f12", + "result" : "valid" + }, + { + "tcId" : 47, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa05a5e4af11cf63ceaaa42a6dc9e4ccb394852cf84284e8d2627572fbf22c0ba88", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 48, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a48307eb78d38770fea1a44f4da72c26f85b17f3501a4f9394fe29856ccbf15fd284", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 49, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037effffffffffffffffffffffffffffffff0000031a6bf344b86730ac5c54a7751aefdba135759b9d535ca64111f298a38d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", + "result" : "valid" + }, + { + "tcId" : 50, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff0000013bc6f08431e729ed2863f2f4ac8a30279695c8109c340a39fa86f451cd", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", + "result" : "valid" + }, + { + "tcId" : 51, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa0a5a1b50ee309c31555bd592361b334c6b7ad307bd7b172d9d8a8d03fdd3f41a7", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 52, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a483f814872c788f015e5bb0b258d3d907a4e80cafe5b06c6b01d67a93330ea029ab", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 53, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037efffffffffffffffffffffffffffffffffffffce5940cbb4798cf53a3ab588ae510245eca8a6462aca359beed0d6758a2", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", + "result" : "valid" + }, + { + "tcId" : 54, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0fffffffffffffffffffffffffffffffffffffec4390f7bce18d612d79c0d0b5375cfd8696a37ef63cbf5c604790baa62", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", + "result" : "valid" + }, + { + "tcId" : 55, + "comment" : "y-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045450cace04386adc54a14350793e83bdc5f265d6c29287ecd07f791ad2784c4cebd3c24451322334d8d51033e9d34b6bb592b1995d07867863d1044bd59d7501", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "80000000000000000000000001126b54ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 56, + "comment" : "y-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000001126b54ffffffffffffffffffffffffffffffff4106a369068d454ea4b9c3ac6177f87fc8fd3aa240b2ccb4882bdccbd4000000", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "e59ddc7646e4aef0623c71c486f24d5d32f7257ef3dab8fa524b394eae19ebe1", + "result" : "valid" + }, + { + "tcId" : 57, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 1", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "12c2ad36a59fda5ac4f7e97ff611728d0748ac359fca9b12f6d4f43519516487", + "result" : "valid" + }, + { + "tcId" : 58, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 4", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "45aa9666757815e9974140d1b57191c92c588f6e5681131e0df9b3d241831ad4", + "result" : "valid" + }, + { + "tcId" : 59, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 9", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "b90964c05e464c23acb747a4c83511e93007f7499b065c8e8eccec955d8731f4", + "result" : "valid" + }, + { + "tcId" : 60, + "comment" : "ephemeral key has x-coordinate p-3", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c0e994b14ea72f8c3eb95c71ef692575e775058332d7e52d0995cf8038871b67d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "e97fb4c4fb33d6a114da6e0d180e54f99ec1ece9ff558871054e99d221930d16", + "result" : "valid" + }, + { + "tcId" : 61, + "comment" : "ephemeral key has x-coordinate 2**16 + 0", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000100003c81e87241d9451d286ddbe65b14d47234307b80ce74b8921af7d4935707549d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1eea9c2756a3305bb5178f2c37436e7b41cf3805cd0a1087d2d02407fc553c09", + "result" : "valid" + }, + { + "tcId" : 62, + "comment" : "ephemeral key has x-coordinate 2**32 + 7", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000010000000715098598dc12cf294ea5ac1eb5eeae9139f5cfd3d0ffdcfa7297a01dce1ee9df", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "2f1c5c590f97f79351fb9d36c597d1c61f1c409fcdedaeae795112fa1a2c7453", + "result" : "valid" + }, + { + "tcId" : 63, + "comment" : "ephemeral key has x-coordinate 2**64 + 1", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000001000000000000000161bd3a38f707713b97eaf8d0184e0079e2a62cfba75d428b1326ea861aade950", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "82b8e90e6b6441b7164c9725ac1a35f098788096af95c276fac3c5a383d6b56c", + "result" : "valid" + }, + { + "tcId" : 64, + "comment" : "ephemeral key has x-coordinate 2**96 + 1", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000100000000000000000000000115820e7e26670c6b45c1e0caa951eab312754180baa9fcff9f7e7bf46deea7fc", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "8a955b6cf4d518558e59372444d3fd9b78933e2d3229dfdfa6f5f66403290e19", + "result" : "valid" + }, + { + "tcId" : 65, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = -6", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040b7beba34feb647da200bed05fad57c0348d249e2a90c88f31f9948bb65d52077435a6bef91b92ae32cf51d7149cad0353a46513851427c34436536ec7eae483", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5626bbf79f10827e23fa5aef9a26533f5f4e7472934ed9759b7b3a77cda04b82", + "result" : "valid" + }, + { + "tcId" : 66, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f75f450dbbf718a4f6582d7af83953170b3037fb81a450a5ca5acbec74ad6cac89", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1908ae936f53b9a8a2d09707ae414084090b175365401425479b10b8c3e8d1ba", + "result" : "valid" + }, + { + "tcId" : 67, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 8", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee37269a64bbcf3a3f227631c7a8ce532c77245a1c0db4343f16aa1d339fd2591a", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5e13b3dc04e33f18d1286c606cb0191785f694e82e17796145c9e7b49bc2af58", + "result" : "valid" + }, + { + "tcId" : 68, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 = 2**96 + 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000439f883f105ac7f09f4e7e4dcc84bc7ff4b3b74f301efaaaf8b638f47720fdaec24f50efd39b8ae7536e8806927eac6fd52210a239fb4129e0bfed333476575ea", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "a995572ad174897ff1971e6d1e39f908448a5878da1e60f3901f57cacd49e5f6", + "result" : "valid" + }, + { + "tcId" : 69, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045555555555555555555555555555555555555555555555555555555555555550134a74fc6e7d7acef5bb20e969abb6f026ec0cb04dff34f7916ca64b07fff511", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "cd8427ea93f9fede38a70d0c39dbd96759613ba00f27b9db3971c80aec07e2d6", + "result" : "valid" + }, + { + "tcId" : 70, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa769afe397a5709201bda50ce2d31a13fde4076722a857719924009cc28159869", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "766b0752cd895b4b8543d44c9a348868ffff12aed632f8070e731d450d8a8c94", + "result" : "valid" + }, + { + "tcId" : 71, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433333333333333333333333333333333333333333333333333333333333333330434e877eaa71340aa5e57e58a01f0b0aec8d24b5c64aa77ef95fae9b4958c5d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "09b0aa839893b7ad37cc83160e6f3c5506bbe323497c21505ae9937c75d943c8", + "result" : "valid" + }, + { + "tcId" : 72, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccb2e808a8b6c6e5bc068f96348d68171e66159a0ee27073c82fc3f9581a4a1fb28", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "3c2a61121f094d5eecddf7d3b0016c170b90fd3f2fea0b12e31db04ae7c279a2", + "result" : "valid" + }, + { + "tcId" : 73, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0c1d854210f797c547bd3b3feccde1ce3e67c61c3400141da2068520e2bae9bf90", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "9a641d5efa8be7dc723aa58e2e52a150c8efced2fa1084041249773c7562c66d", + "result" : "valid" + }, + { + "tcId" : 74, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f022bcbf40d658bf3ff02d98aea5ae45d43ed85f6de9268f0eae85210f2fed81c6", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "d32977eca64d223ea90f10f72f810ec64d661833acc4c839591da813ef86f736", + "result" : "valid" + }, + { + "tcId" : 75, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff210a46304881329c9807b71b6393ba104b9f27d976065e852429fd664de98eee", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "55137fecb21eb3ebed1b41fb2f7e1ca337009465f855f3f920bc7d0b73c2da32", + "result" : "valid" + }, + { + "tcId" : 76, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff007011d6e851e5a53fde41c1f348690c0188f24c105d5cfca5b6ff3c93dbfdef99", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "0bde659ed89281e6c8a5fbdab764d0499b86d19d33f4c978e260bbae587d4057", + "result" : "valid" + }, + { + "tcId" : 77, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff4b66003c7482d0f2fd7b1cb2b0b7078cd199f2208fc37eb2ef286ccb2f1224e7", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "3135a6283b97e7537a8bc208a355c2a854b8ee6e4227206730e6d725da044dee", + "result" : "valid" + }, + { + "tcId" : 78, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000fffe0003fff8000fffe0003fff8000fffe0003fff8000fffe0003fff7fff0a2331880cb3f8f9004bf68fc379beb6e3affadcbe81bd4f9bf76e4ac5ab2c37", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "2a3d29ce049fc50b00fab50e7581b84d441d297be6515fbe83dc485bdf32b6dc", + "result" : "valid" + }, + { + "tcId" : 79, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffd3b6a2629d598a045be28a1687288cc4d0c389cc6fe627c5cc3aa2ab963db7495", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "03c202a64e60ff5948d29816d68420c64c0518a7522a929381365b1245770a02", + "result" : "valid" + }, + { + "tcId" : 80, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffefffe35e39d53d101a6aa4ab434c55a70b03d244b6a2025a18d4d549dea451c031392", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "d07fcf7b89bd1ba24194caf977db68a5503a471a37d374e0917a5fe31d48c99e", + "result" : "valid" + }, + { + "tcId" : 81, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000003ffffff0000007fffffe000000ffffffc000001ffffff8000003fffffd3aa774f4d29fefddd9546ad1f7b2b79cf42634284fbb1d7c702e9fca3fe049af", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "ea9f3a53ab4053df0bae0156767a62ec5ba0de4373ef12cbfb19aa80c6bcd904", + "result" : "valid" + }, + { + "tcId" : 82, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047fffffe000000ffffffc000001ffffff8000003ffffff0000007fffffdfffffe23e4bca0984da424a6120a13dc676c777607562d16ed9b8fa94c21fff7151d4e", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "f0557be2b26ddb56d44d2cb852224a291de771418fe148a730a76dadf5882f18", + "result" : "valid" + }, + { + "tcId" : 83, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000003ffffff0000003ffffff0000003ffffff0000003ffffff0000003fffffc2a95c81253ac554846812d2a4415f6edcf954209008d260a806b85aba759ff72", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "c68f07233efd0745d8bcd51a89158717c2dc532f75a9e4de2076e1b830654ec8", + "result" : "valid" + }, + { + "tcId" : 84, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffc000000ffffffc000000ffffffc000000ffffffc000000ffffffbfffffe031537fcabe5d5e25165a18b1bd408212cb523efea0fc0fd1eac46e83b0d0b52", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "6eec8a68eb5f9caf2ab3053a3047bbc08412a1d433d79eea65effc5e0cd583bf", + "result" : "valid" + }, + { + "tcId" : 85, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff63a88b2e0c8987c6310cf81d0c935f00213f98a3dad2f43c8128fa313a90d55b", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "bbd9d305b99ff3db56f77fea9e89f32260ee7326040067ce05dd15e0dcc13ed8", + "result" : "valid" + }, + { + "tcId" : 86, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000fffffffc0000000fffffffc0000000fffffffc0000000fffffffbffffffd2407bddc5a50b2a7b96a288efb838bf768c6066e60b72f08a9782da2e39bd34f", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1f81aa3d70f8756b9495fba82921717d4006206a4451d8d59f3c9b8d95b548e8", + "result" : "valid" + }, + { + "tcId" : 87, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff00000001fffffffc00000007fffffff00000001fffffffc00000007ffffffd4af9cc406a46943ffe0fe630bd21f205eefa05355f3a13c9943d58e16e880435", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "66e707faf954d1ec84fe0f68f829beb2fe95058271b636362e3eb5c5d492cbf8", + "result" : "valid" + }, + { + "tcId" : 88, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400fffffffe00000003fffffff80000000fffffffe00000003fffffff800000002796cf7bde36dc6b1950001228b7249d3438a35fe5be98661255bf63a879b3a5", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "42dd6d83bbce6afab5045e1393838a97a46161c25ae91db0143e985d29162faa", + "result" : "valid" + }, + { + "tcId" : 89, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff73b0886496aed70db371e2e49db640abba547e5e0c2763b73a0a42f84348a6b1", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "ab43917a64c1b010159643c18e2eb06d25eedae5b78d02fa9b3debacbf31b777", + "result" : "valid" + }, + { + "tcId" : 90, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000ffffffff00000000ffffffff00000000fffffffeffffffff0013a9be0cbaaacf4e0f53ee45bc573eaa44dbf48d5fafc26856b44d6d00e2be", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "f39bf49011cb323ee00f77e0344a9b9da1256db92646dda0e342f8c1ad3741c5", + "result" : "valid" + }, + { + "tcId" : 91, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000000000ffffffffffffff00000000000000fffffffffffffe6e563bca873bd591c9663391c826150795e3c42cedd269e68ff0e56dc971d554", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "27860fa0679edd4556f0423a21cc21e1e3f1701da3e62a544974ae94f15f91a0", + "result" : "valid" + }, + { + "tcId" : 92, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffffffffff00000000000000ffffffffffffff000000000000005b5b2ec553be67fd73add4cc2bced4ebe6d04a05b0e926e312037b3951667847", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "2bcfc95bba84524d8093dce1092bc157ca1fa42a37aaca9b0759437f940c3e7d", + "result" : "valid" + }, + { + "tcId" : 93, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000ffffffffffffffff0000000000000000ffffffffffffffff31cf13671b574e313c35217566f18bd2c5f758c140d24e94e6a4fda7f4c7b12b", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1a32749dcf047a7e06194ccb34d7c9538a16ddabeeede74bea5f7ef04979f7f7", + "result" : "valid" + }, + { + "tcId" : 94, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffffffffffff0000000000000000fffffffffffffffefffffffffffffff53a54141598334650d1f99a12850769f53d34529b07ae591244c6ed702f1aa171", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "119aa477afad550e98db77bfb4e71a4b6ec79ec4fe17b7283f9b8bb7b9fdb5ec", + "result" : "valid" + }, + { + "tcId" : 95, + "comment" : "ephemeral key has an x-coordinate of approx p//3", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000455555555555555555555555555555555555555555555555555555554fffffebc7c976bddab1d1a302cfa176c25434558ec7cac238e739ca9849aa104323b106c", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "21edb700cf62c1bb816a877988ee8c5bc16a8464bcb6454adb8abf8b5cef7ceb", + "result" : "valid" + }, + { + "tcId" : 96, + "comment" : "ephemeral key has an x-coordinate of approx p//5", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433333333333333333333333333333333333333333333333333333332ffffff3c7b2bf3716a9e336e162966597e5c423bb9d3d0d0c3c02b9e2dc4aabad17bfdcb", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1ba54571d1d280f5fa2d0c5846ec392c721acd4ba7e4aadc3dc2353957abd80b", + "result" : "valid" + }, + { + "tcId" : 97, + "comment" : "ephemeral key has an x-coordinate of approx p//7", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004249249249249249249249249249249249249249249249249249249246db6dae22817588aa19f910e8bed1f89a6b5ea6cde4800dd9beb28d1336bb46075118144", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "9d422ce42f74aa0272e5530b5dd094225f11d1100fed954ff714a2d471559cef", + "result" : "valid" + }, + { + "tcId" : 98, + "comment" : "ephemeral key has an x-coordinate of approx p//9", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c555554e83c4d16ba6991011cf3f94feeff3f48ad29ed9a22bcef8fac40d9b2af25e2b909", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "a5ab2cc5bb6881f7e734d7ccc9d448127d9465fd342d81c8381572059b3aa2b7", + "result" : "valid" + }, + { + "tcId" : 99, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000459294e8bc54e76d48b5594f01fe4729566d9b6df6385982fbb533183921f1a124543e4110bf4cd22e1d444d83e24c5ecdb328a98f2f93e8edcb99b07d5d9fafc", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "e976057e8a322dfdb2debd55d8e58802fb54425950b2dbfd00f0813de27105e4", + "result" : "valid" + }, + { + "tcId" : 100, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000429b579690264954985187aaa9ea313d39b5c828e022afce8fd0cb764ed693473ba8cde1b2be1749cf4d5bc0df578009c9650e44b6c385c5ee2621ffffc205cb7", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "09fa5a510558a12110daf75117af1e175f93d7c4d8ba41c5bf3efe95d829ff50", + "result" : "valid" + }, + { + "tcId" : 101, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044150a111e0489cc82d43ba66f404ba0df2b1fa13ffea361442f7854f9abb381465627e96f372fd0400eca42113890cb110c11eda22405bcd295b1caab9d93af7", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "98bc618faef7c4311c3d8fd37b39e9baad780e14f0527fa69a3f4c2b66ac6394", + "result" : "valid" + }, + { + "tcId" : 102, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a74646c798fd5a0af442da69c822cdf1134adba361f90663d626481aa10e0004567160696818286b72f01a3e5e8caca736249160c7ded69dd51913c303a2fa97", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8a0b2ddef3a1108f6ea367ed08079a0ec98494fe46cfad584bdc98e99e6d7f99", + "result" : "valid" + }, + { + "tcId" : 103, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004611c65eecd9e3de528f639e8b6698688db1f4fc8c11650a601fe6daeca5c59665fa45a23400633ba3630244aa6b0144de2ab3b6295e3dfa15f586e40a84053af", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "89b86329f0f13aab07a48d0d3b7afe530ad260a90de6c25ec3da8b6905502551", + "result" : "valid" + }, + { + "tcId" : 104, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b49c6791647937568c7570064856420835d44af1ceddd682967fbd44fc97294cd135651bd7ee3aab957eba10ed4b7a5c40ca00d959ca663080c4eaf0e189bc21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "751b521de6384a017caafa10419fc35d58f6dbace86f6b533c117e38dab1d689", + "result" : "valid" + }, + { + "tcId" : 105, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c73c71d856cb949a31c249c1e99b11ffb698cbc1dbf4002e956cdeb655f84045716e98dec10a9905fa1d3a851f4f1fe617356cb56d5643a148eec376237a27f1", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "f282a78942218fac638eeb0eb15098f5aabae15b3ddb7abdd40a8ad3b5540c8e", + "result" : "valid" + }, + { + "tcId" : 106, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004acabedbe760e9330af3508209ba0081b9ce061327d1ea0b6ffdc577dbaf28e269cd00176358828215d30ade0cff8cdc0856c84fcdb424feb93ce58a2554a9bcd", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "6aeb7004f6cf6b05f30bf481e8b32a1e25fc66d96a4a53165727bb304cc27baa", + "result" : "valid" + }, + { + "tcId" : 107, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044cc9197bfdef17d33a9ea743bf83747b564d6ad11e6080957a9d3ac44165fa793ce20d13d431071be367e592f8a22f88edee1cd51cadb0845ebea64b11c45708", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "67b5a9926bc58025c8bc2b9504b72c3a8465173d70f5d5ec1580fe88c5a4887b", + "result" : "valid" + }, + { + "tcId" : 108, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fbf411afc88358dff2ba156ce273d7b15d0ba3980a60a82eb38bfa58995e163d57c62e53070e8e6cb1df4ef509eb2598dbdb07a5ffd71301eaa2892ad1238f4a", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "12182c05568a6b18a98ea19110330146e7dbc49274f324b5edef4eb861f72bec", + "result" : "valid" + }, + { + "tcId" : 109, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cd7863adddaf0099647139ce64ca0b39dbd312ccf96c15a62f2c49e628248235999f82afd0f76e744afd0fca2aab36f22ff7ebefd8e541fcb6e972704b8ac521", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "f75920e61e7d05c3cf4107e5e81f3c1be7ffb0637f0ac8b895d87361345d9a87", + "result" : "valid" + }, + { + "tcId" : 110, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd4fd857640a6bdf5da42ffc5c2c1755c4c125a99d380a5935eb1c4c3a9c2a3a4760df25ca561724a82e3f9c9d782536db4310d6c9c769f51b733de44a9c02f1", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "373aca70b036b70cf8e46fc9457a8e19c6821be2f2d6c16edadd20d7b30eb3ba", + "result" : "valid" + }, + { + "tcId" : 111, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000445654b3b66065743ac86854daa77c9e5cf713a402fbd4ada365f4f96bf1717cd63cf23ba035de430a2128dab0d2c7b939d44c66624f6979275cd37cd02370669", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "caec9de4a74d76603c5d5d07de2df0d435bef2b9063b5123305d2fcbd5dbb318", + "result" : "valid" + }, + { + "tcId" : 112, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dda793fe7fdea5c7481c756f59fbff48481777a54218d95eaa24e7b86d8a5858fdac18590cd96e193db51c50307d2606674d5b8afcc82d1b672dd8e09719a6ac", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "27980511f433feea84475b82281b1fa6b946c97c646738d5ac3345250f86037d", + "result" : "valid" + }, + { + "tcId" : 113, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042e043b851fc5a5f12deb76fe94182b99bbce727b476783f9d868ad3ab7ac7a251462b469c2e02491e05a3a4523e09a6be8e5b2d10419cb7760a8503ae4eb7e7b", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "20b27f84ae128f674e144d82bcd1544146bfd0150b0843ea585314f59cc54aae", + "result" : "valid" + }, + { + "tcId" : 114, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043d8fddf41e52320c8081e0d60f5397993abdfa979c4b5e832ac61bf3cc2e6fd94504fe3207dbd18ebad2b921a52a16a33659939c16fbb9186caf5e2cf3170346", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "92592791ff90b595dd2ae7ec039bf6b7bfeae7f044761f5e7fa86564ebc46b2b", + "result" : "valid" + }, + { + "tcId" : 115, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000465106fdca0c408738c2316f3ec2238d459157bab2c2855323b95bd271c91dedcd9fc2d685446789829251d293a50d150df5f1fc1a0604e4defaa9a8e3f8c9169", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "8e61b2e072bd1401da12a3f3d8164daedab0bf0ca795bcf56aff81d07caf7281", + "result" : "valid" + }, + { + "tcId" : 116, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004320c813548183aadb0e7d21a0ffe472bfa9b4ffe815adefd09180a3ae2d15fbcd0ca20611d2232847aa80e7f7691c008ff886dfce550f90c4c19982ed779b466", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "a41170f616c5499e289b4893b3973e1155f66ff354ae6a812bcd0e33bd7dd5cc", + "result" : "valid" + }, + { + "tcId" : 117, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a0e2b1a92a6afa9fe68424bc63dcad620b7dc844e4571f5404ab9d18bf08545ccba1c1ff49bf7baa9be1fc0ac4bba63b41ba7a374e15fc39b884d80a75b07092", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "b8cbc27d4ea1b25f2292292ae53a3bb954b7ca77ccca5b4dccf1b958b0aad163", + "result" : "valid" + }, + { + "tcId" : 118, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dc97139a3dd1411d74616154aa0d6bce787cfafbd8fd060b680b04b422b0d22f6ab50e5c68e027805953bf7c3be40a8f7c9b56c6dbbe86337e6163ada01d9d63", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "4baaee93a752397bf2ad0be72ac82b0ad2417e167bfdfce4904f012d4c33fea6", + "result" : "valid" + }, + { + "tcId" : 119, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040978d42e1594569589b578266cedb6088a84c9cc9baff0070dc1d934342605e62ce80a966b5ca0344981f4229c7ab622a853bd9bc59b662ecd92df238e4e46ed", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "3b3d86187d05a0012d83be280987dc95b1c0c9b57f253b64530d1d4220aa4abf", + "result" : "valid" + }, + { + "tcId" : 120, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a8630a7bdb78a970a01b20c3e7b95d25d3eebdc8e94ecfe0f508e4136eca49afa5eb12114b50ac77d68d410cd5ef5107b2e68f08600e5e6938c452d51d6993ba", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "472d4b34f5be6b499f76b0d9e439e115f6a89b725d9e9e811185a615f14007d0", + "result" : "valid" + }, + { + "tcId" : 121, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c4ea8ed31ab4a8c994a965efd4770bbb5e26ee54cb7217ffd31fa888c108feca063c415201329dda130f43973f442ad320da0ccf289cd1b71489ca0a7201d5a6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "fa67f4a9ea34fde196a7dff6bc1a2917b1526d54950335bea2abe22e1edab410", + "result" : "valid" + }, + { + "tcId" : 122, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000491780d1905316105d6a6aca94a0d4488d134f985f7e29adecb1bc6cd0c211a788035b06e495d1e58b085bfb6720bca84557b670de34587df0d7e3aad5bbc803a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "95c131de0c89e5b17f91e56779c1571de2c8a20794084fa274eccc8eed1d3d65", + "result" : "valid" + }, + { + "tcId" : 123, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041961a1a4b29671f1d835b313ffeba4d8203d8414cdc0ea11e47d619b47038b1de50a63b89cbc8956a5870c6c4830e2102d5281b9b5dc127b1052fe7b3e11c438", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5bae6d6d23a68f283fe0de46f1d74c0f52e278cb181f55c4353f768ba162aac7", + "result" : "valid" + }, + { + "tcId" : 124, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000429a9e7f25109a8c4bd80dbea05fbb46aade58797c3b2fa5f00f0f081669ae39d2c78fb1160de6eda50f472ba659d4f1db4ea6e297244b6ae68a051d96e62e75e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b4fe1201a8647be6d6d59f406fa970cc858f5a46a50a6ae9d992c0e23f5e2ad3", + "result" : "valid" + }, + { + "tcId" : 125, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041617dc03d3eea42e8ea2c5bd034a38c5a3d74165a548074b7b5765ccd8465b7f61089d6dde53430f34cf8285ddbc584d1543fdc70c2333fc315eed4e930ac3a1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b721ebc7eb1b09438d754ae80302b2a2bf40f866ec507540ab5120b22f868886", + "result" : "valid" + }, + { + "tcId" : 126, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000420e7a1358436f675f3774d60954b5621145b8f5260b5503636f54878ecaaff8dccaf2fffcb7c7084e325dae5e24bff5a34e37980d1722016dd6667da71f164c4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b8da5d1bf9419e2b876e708871a9a29574686689bae8d87985d72a4e573dded4", + "result" : "valid" + }, + { + "tcId" : 127, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042759bf4c336501340cbc67afb4a8f5744f9131d973966a9de50ded60fbe045121b67a9e81e53b064adeddd16a4c030dbb189ccd7019b329d67a527c311723469", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "39aa2bbc4b6f30c268b19909d5070155c39c60649b7a2ebec266bdd18fff8cbf", + "result" : "valid" + }, + { + "tcId" : 128, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000419b8a10f5021f11e29e18611fa8284b7e9a3f67cf36eec8ecc4d7a5b54803411311a8a4e199d98eb358e19a27e80cda6af142d6091ddaa9370ed610453abc6c8", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e40396a908c2cca4504f4f40be394a12244ae184f6909ec725ce723485bbbb97", + "result" : "valid" + }, + { + "tcId" : 129, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049ba841f41245ac08955966470425593290b9e1d87bda8f47df19048db8e3d83097f68905f360ced26801872a7ff124c3637b02c4a596b83abafe7bce567ca177", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "13a21dc50cdfaeabd572f2d94dc0f3f768f17f990ee59d7f16ace9bfad8a705c", + "result" : "valid" + }, + { + "tcId" : 130, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000468af761d053dee64aca5e98f547feb2dfb6f5edb8138011c7f5c33809b4b9e00466dd76cb8ceeb5132862052ad3e08bfea245ef16ca0d00ed0c4b45fb6bd3028", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a82fb3bbdf6d69c7398ee9020fe006d5b28c632f2da357393fe58deb8d27fd08", + "result" : "valid" + }, + { + "tcId" : 131, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000405dc8b18bc286f203213b1319413dfa4911d6c2e30f3c778c55e4e5f5d9bfdbacd0b3b209e76049895ae80ff63c0225a563228cd99243f628a9dbae70d773c66", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8fa44f09cfddef86aa9007cd4bea6f0bc9b5b2115256303df09f8a20909c5271", + "result" : "valid" + }, + { + "tcId" : 132, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bacb606384b1930bb4b74ded236d03d3bb1739a51b73f20dc3349ec3b383180a6896ed59fa0b654a9c404b34fee2c767be2383f4b8b171d2359806b04b502d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ef762992d22bacaf06aa1e482c0711046b52e0e40de2a21d4e38df0109ad67c0", + "result" : "valid" + }, + { + "tcId" : 133, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000448ab89b2a312de510a6d3c9ac9e4c4f5b46e04d3f858433b7646e46273d94dce4a0c7da616388f1eb8d55ece64ab695e5405d779c92f3bc2595c27d65def8db9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3b0936f22337ece971ee102178f37bca3cb69b50b8ec9c9b47334c68b5d4320b", + "result" : "valid" + }, + { + "tcId" : 134, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fd9de304ea5f18dd641510b9809473d39a2373ed5a470ffc5ea7c83093911b4540baabb9d912279aeea44379110abec75ab7994a6183c6294bad27bab5bbf821", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ec571878fb1e3b1f5d4f66b8b080bd4e50410b6eeea4dcd3cedd4622bf876160", + "result" : "valid" + }, + { + "tcId" : 135, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf8976a28221000d7f5219fa8d06f9f8ae47be626f89c2bb6c4d0323bf02f8490c78bc948c6bf82a191f1de972e57db35b05918594ccfbe8da19bd46facbda78", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9f3d9de87d9cc5099ff4f56d913b98b5eb1260e2b3a2d7a3c5e01a7e68219d10", + "result" : "valid" + }, + { + "tcId" : 136, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c3229c9b4f409a6539484152b39535c512a66748972025165fd888c388369fb3298cc41dda36fcb15a0d97cabf757bf0737dae70829f4b9a1d499d9e9911673a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "23adda6571d4ad7e940c21023af3ffedef9d8f64e83cc1cf6e992d1da1451d91", + "result" : "valid" + }, + { + "tcId" : 137, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046f2c3dd84b44daca936a2edaf43adc8c1bd5f42801231718fce6f5e94d144717a247598c11eaa2c507b0e96dfdd03294cba4472ae8a2128e36f1eabd315aeb25", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "91e70bd8bf85bc6311b2cd7791b7edf00e22f9cb8bfd72571ec9a03bbf716f37", + "result" : "valid" + }, + { + "tcId" : 138, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a511b09334f032cc33ee4ddbb839304f6bbf1daa4a80de524ca24ebb65a0a92e4ea48243cf7e26deaf4de7779ca71f76d9dc6c8c1b7f44cf190fddbe82c2c940", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a7d2f3e3faa772d7a86026e2f183dbe7a298ae3d1bc3abcea0df3c11cae4ca60", + "result" : "valid" + }, + { + "tcId" : 139, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047cf4a6ec110db892e45a7b2ab38b411a6c41e86fd21a6455ca1a4c2e2220681309b3e399ae30098bf872c9aed5db69d14cb71149abb05cf5227a620c4b16b740", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c611d27e7cb52e7c56cfa9062e59f3defe7c1e225727b9049384a180bd1688a8", + "result" : "valid" + }, + { + "tcId" : 140, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000436c7dcd152fb7e53fd16228465ea0c419da29cc6c79fd4266303b3bd06aa0b9036363a959f8c0b400da525ad7674677f829092ae7f7e8dbf88397fcd19047af5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "661f5d36b57af48982e44ff89ae75f849a08b1daed6417a20212bea88c7f2f8a", + "result" : "valid" + }, + { + "tcId" : 141, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b61d3cd27bfa1269234a777e118f7db10a3844e8c7d1162c099a8099d887dfb849520e9a038f8ba8804d44f22b37452514f0aefea93bab7bdf180db54485aada", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "540e255f6cb58d237990a7437cc7aae770428796deb607bc29fbf0a4d11873c8", + "result" : "valid" + }, + { + "tcId" : 142, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ac9cbc8bd917192928d9a065fb1f89be4bea850186fd466a7a9014066ce002c51a906c90eee55cb5692f0ac046746ee4bd2205fe5f435d1e71f19a8cb8550f3e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ac6705af9d059cac9977967c0ce514d70dc51d88fde684123a921244933ba8ec", + "result" : "valid" + }, + { + "tcId" : 143, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c050d058aada9e43767f1f760abdbc421ae220fd01e832ae81c628bfb1277c99d35483fe6aea51dea9c017c326ba7bbd4175687a72dc5c4f449eed0c53a08052", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f7a5b69bc39a976bfa6644a152789c3149352093b1dcc4b6b06f6c4c7c90fdf3", + "result" : "valid" + }, + { + "tcId" : 144, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004399542882ca4d5fae3282c4edffc3c7eda7c451e46adee4219015e91c8c69cf8b123f8ede48ab76fe2c9218326cb06542a832d0a32b7ac0d485b4629bfaf0d76", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f0587fbd10e332ad297b5e463d4f09d2167c8589c46dc6680c13b044a34485ea", + "result" : "valid" + }, + { + "tcId" : 145, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bfc304fd88ad8f11801d35286a49505cf349403d8100efe903d078efd5d3a66ebf05d6fe2a14c069902f0d8eb6800460731d48395efac4428ed87b00f3fc6fb0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2fb4991332a5d648df5ca6bbd08575c7553773a97312303440cfe7e43d3a268c", + "result" : "valid" + }, + { + "tcId" : 146, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046881678d6c6d8ceb01de5d6664a0b57b470f149492e8e7513e121fad849aba1b2ad34db024ccd2694e497f6adf4d3cf5adbf518c768a4628bc2e159d0949f2aa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cb65082df5f54cdc668625017cdf45f22f305a8f34ad91fabf36c071496c84cc", + "result" : "valid" + }, + { + "tcId" : 147, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e38dac9ca4ef5b35da77d846093e0d29c1ca350e72b5a6ce901bed9f472ea199f805fc3202920782f49f4b6e7257a4364dd5451d982f29b62d5d4b8e07a33068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6441ac7be81c2fb6472655528f21454d40236a878fbac2ce31e4358ab4ed02cc", + "result" : "valid" + }, + { + "tcId" : 148, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042d8c6732e3d0e1822193243bb9ec3fc2c7f264e94ee61b295de5b3c10db937f135343453838114a4752a5514bcfb9dce10f83e0190c540fef10675cb42584a05", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0b586c442eaf016f382199729f60240ce50c0f7107c488a423d42794db5f6663", + "result" : "valid" + }, + { + "tcId" : 149, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000420bec8d2b5aae1f955b7992198bcfe20880494150058cf6151fe14f6071bad3132dc1ce503969b824c5a9e23aeb472255dd23f97d02f68281ad0269818b17e49", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b376d9bc1909eef92953cebc3bd6f2bc0cd6cca620c190141740f62239579334", + "result" : "valid" + }, + { + "tcId" : 150, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f456946770af5d069d60b279ae519ea18e719abaf5787476873a5e61f969074d47eb27520d72fce10650d312a5431bbd6b3f37cd46755b7a8e1ef1a796f90908", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ae739f624ccb1f0ec964b2d1896d2df83ca1969ad6ca26b334342013d83282aa", + "result" : "valid" + }, + { + "tcId" : 151, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1390a944d24f300fdab9bd272bbaca056feb71c0c37468e0327b08504d55f3a80a4b240565aa43be8f3e2089b4788049c5d378b667e987e01aa8a08a4cd2c95", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3c25126ece58ad8e93ebfe6e7547b05b39c6d9858e559fc01ff6b6e50b0a22ac", + "result" : "valid" + }, + { + "tcId" : 152, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043e61ff2443d10b1e25fb0ce19f57ae39223d33fbb0e5ee2b4740fa19384b7d0e1408119a70aa9b230d9f18269c065c53d4c2619673b49377af4cdd536c931aae", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e47d658df5c1f9599d4e560954ab860e9a6377decb0b56ef3c13dee36185b2f3", + "result" : "valid" + }, + { + "tcId" : 153, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b06028d729039617f912e86d1d1f44e93e63aa216ab0641813d06c16a3edaee979d21572f9540d7b07b0a6667f7e0a9452f6f9f3671e522e2b497eec138a46ea", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d8279c1ec95189fe63d75d1c6d7fc312e411a3d11e4d671a49fa17fa36c3cee1", + "result" : "valid" + }, + { + "tcId" : 154, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040a8f74cee50d1e853a38c026f627fe47d81fc11f886268b35379a32ada249bb91d63cf0198e1c926bcb65ce21813e4d72118b7092a5e8bc152909222ac19603a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "077c7a4e606099d781cbe5a89caf7bdf4f448b1c0d7d3097263a045170275a3a", + "result" : "valid" + }, + { + "tcId" : 155, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040edb7020cf4d6ab14b5a3f8f698d66eff983588846d718b4845d674e7bbfc0edd92a27e40e5ab2e0cd2d0ac1ab679402ce36f16d3ebfc0fd9df817dab17292d9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2025808c609ab0b07924444ea4aa0fa52563858a53221f719c91b15576f49ea2", + "result" : "valid" + }, + { + "tcId" : 156, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f06c77cac24a6ee51421863a0d1469418f0a6430e062da18f27dd57401c0b612032b7e0591455ca33b4e49e53facf5864410ba046ba5d4fc6bacfea9a0782ff3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9832405d565c97ba1d6ff46e1d8fe33886222cbaa69963868d12a8be07abac6d", + "result" : "valid" + }, + { + "tcId" : 157, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cb2b9df4ddc430df7b0befcb5a826da1589a15bef1b6b25f1201daab5b2fa4ac3801e27d112f0f3276722dcb58b8b4f4844a2e614de49db440b7cc7620812734", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c4bbf44547e8128b9a46ed92ceb07df691e2e91d0b47dac0dc2afd14121e7a80", + "result" : "valid" + }, + { + "tcId" : 158, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000445206b62e4a3c4404c74ae8695cdb905a8e6a9456da09c72c72eb7712d9d52e81ddc2d56b634e4ab66b798cdb4db86cf94f02208f747304ab3d5aa2bb125e137", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "170a91aa8196df6f0d09ec197fc526996ffcb6792880f01018b3327a096fe638", + "result" : "valid" + }, + { + "tcId" : 159, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004584d2dc258bd4650e6fa04fe9d3d2a5e768d795945ed2323f844d0a8fa0c6fbd5f96256b9e1b7263fa00fa758cd6be15d9f6157fad66c729ab0dad694564e834", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ed527e31223f175aa786f146b3fe0561a41b1051d5eb32249790481eab1ef381", + "result" : "valid" + }, + { + "tcId" : 160, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046c5527898ae8067da56ac82caf338c9e7f40ee4489115daf0aba923a8b6e501e430f5970ce9d01d03ec076f8daf685cf4d5a9ccd5eb9e849d43ae2f36f2e80e5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5a74555732d8541d2f73e3a59eb31a131c8d41464a1f2c37531a25f4a6d3bfe4", + "result" : "valid" + }, + { + "tcId" : 161, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000452cd9924795fe2a251af7cb569f66d9141db894545d798a0db3d30e50f100fe204ea81c808587c90f3f2c94d993c2d0cc4be64dd6aeb9dc81c70d78885b2f776", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f2750c996f22762629a3f808da6eedd7cc72af4fb0bd816c86e636264bf57664", + "result" : "valid" + }, + { + "tcId" : 162, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bbad8da4c018bdc15a5af8f3da4b384c530ea75560cdfd242bfa3235d8d3595f734cbd866487b83fcb84a4ac74ac548f2535b79b57d02f03a1a37e2791a096e4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5d2163ca850749991cf782c3852e86b05e6b05ec8662905b60cc7b7e37434fbd", + "result" : "valid" + }, + { + "tcId" : 163, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004389aa52235043bbd759868898bbe277ab996ea9387bd7098b0072442bd2b42f5b823364e9144a1eef1f10093fda0c30168f3004e2c2ea74fde4978f3aa1a31c0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f8cf2cccdcb53b3d3c6d1990ae16c71ad9d141ca49f8574a72047ce6c2da950b", + "result" : "valid" + }, + { + "tcId" : 164, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fd1bac144354cfe1cd4c64aa3a2f77f0aefa26cc5141082676370a0f1ec92cd8fee66992d2d2fcb87f90da0a6743378466655519bc782dd7b0ab570f6ed451d8", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ccf6e14d1add6e4b5a4228e5aad0b31fac4b45e2112c1c767e933c6a0c3f2edb", + "result" : "valid" + }, + { + "tcId" : 165, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000478c926b0ee01c000c25a83631219f08d8b34745d2ea2fdc9ebdc5a2288fa9b0306bc00ab3790508e5705eeabfbaa0744719c9bd7b467ca4a37a06f6fdbe6d86c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "57556459e9d32b75a13776bddc8f547cb64708133e7917b61e3697c392003de7", + "result" : "valid" + }, + { + "tcId" : 166, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044cae5606bad6013f7f36190d7254cbf0d5a92b338e4a47702a3c97a3371d7ec280d273dd598c20392c540e58bec9b180406f3fa6e6c529a851bcf2b96d8f3809", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e5490cb494bc6ab2108da2cb0b926cd878712f54bfa72b59f702c180c62b0c91", + "result" : "valid" + }, + { + "tcId" : 167, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000408ccbd74f297fe71ca3115c0b1ef4e0421b99ce91ffcd4b72a530b22993e18e9ba0ae1bdbe1c2836ffe9a61ae5a899f152c90b42823638be4d51dc3afa99e6a0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b3ca753c1e1067b550736a66c0d6b6f47e9394c56bb80b5d4204fbec9e59b490", + "result" : "valid" + }, + { + "tcId" : 168, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aaccef834f57e6c5526fe92748cd8cdc1375c2ac71139f5d2587305bd3fdd3cd965dd5374b6a319850c23ebc2ec7a2deb7ff3e428679d4afc9df7e75f2e06e4d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0cf8c178ad95952520264d0f4a24389bf1b23dc7ac1b65d4e8fe822dcf20d67", + "result" : "valid" + }, + { + "tcId" : 169, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a585e1ed6e47224a472cf4ed4ff34e6251c62ac682e4b70992d5002f08d9e203e9b7b28895b9db4016e5d94a9f59385c16db738a83b84e6d43ecef820c55d462", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "15e40dc49ed62d35e8c91999b05068f419238a222deba206df47d909d3a1f40f", + "result" : "valid" + }, + { + "tcId" : 170, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b104d0cc4a987771655105cfc840f195746e112334c54801fd93f4be8b114a1d3cd8cbcf4b274166f82cfe57393042e3534e68df2f4c3dad1b7ce72b47cad256", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e9458064d3bfc444417486ac1334a93c9aa4468031134ee0196ca6e31713956c", + "result" : "valid" + }, + { + "tcId" : 171, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000482bed3d552098d2fc9e02f1f3cc32f5f31cf6cd101bbb8b42bc6f732badc1976229257d92b241f2031ecaeba10f1ac154d8a3bea309328231272eb6aa01aa65f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f4446e98a63b0598011baaa4f930513218e8370abfbd46f721c8dbf37e170d85", + "result" : "valid" + }, + { + "tcId" : 172, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045c4fb681213bf39b68e7ca914d2830b12a7a32c96a9c788ad2987c009e08d0a376a02ccf594c28995cfcb285ed5d91dded92921108a0b40928487cd07180ab21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "dca827687aa24f2fcbcab5c38069f4860dee6698fc23908b06c7dae713a141f9", + "result" : "valid" + }, + { + "tcId" : 173, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046b29f8c006869ab6be793ea72b970aceebb7a4c4b6fbafecd1e35713a28bf284c76b07dc14f1dc533f1c4ccb0973eb53e53023f0b0f1a8914c7708c2d73d4817", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "19714f1d4aaf8bd61520b647633a8e53099499ac368c3dd6f1b084891619b0c0", + "result" : "valid" + }, + { + "tcId" : 174, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046e6849c2b07a37c4f36be911b323e4ce70c18b15902612c4fc0fe6d91e7c180de925544363c68035498cbb2236f5c1ecd0e4b2cbb5801a8cac4d0883f651bbd0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d7a2da8de2434e2ad264f9706b30d0657c727606d8285d2179800a970b4faee3", + "result" : "valid" + }, + { + "tcId" : 175, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433649a1e74c7ffb5edc3949c58b7a7f4b5348288f621c50fbbdb714fa42aa793cbfd969e077b00ead21082f0980009868f79e430ef1c216394bb0e9eda135e9c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "853d4e01d4dd4c9d6e7820adc16f32ce7bfeec0d578deaf28af9cbb3315e8f1b", + "result" : "valid" + }, + { + "tcId" : 176, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf976ef204532bf67443e8b8d9987a683184ec26420329ba268e54e90b480de0beb108df26eda91eb4fd23d26af6f2d78a4281d5ede075c2c715fb1c4f876784", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "35715befcfded16e67fc0dcebe945c6264ca0d91b3663bd3ec0722b585e5d652", + "result" : "valid" + }, + { + "tcId" : 177, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042c435d9faa598070b4920277506c100de62a7df05c34a39317785d628d74dde3c7f5d0bedf54af1c7d21ff955128002fd5296237384723fef1fb806c2a6d8ea9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2baf108668e82b7fcaf3f5e3272637b426c551d8af0e55f5d74bc317a4474767", + "result" : "valid" + }, + { + "tcId" : 178, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043819dfaab5537863c8dbf406ac18dd675619c9a7a554620ad8a14492bba425a3d68e8c68181555e22362415c95a31724ebfe8b2bf1764e209eae9e53b3f462a0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bba443b160997aa8b7fb2748911dc2154c0f6b986fbe9a49e0a2934fa5f32954", + "result" : "valid" + }, + { + "tcId" : 179, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000470ad3a9c9a9db71d420abae84ccdb12768851bac6a82ffd03d89621a50a7c311bfff7c664c211f93768f84b5255d95c7f67887c3305d789d7fcedc2d29989f9a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b4831736601e7387050ba3d401aea241c3506b56a0473886c408b366c8696429", + "result" : "valid" + }, + { + "tcId" : 180, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000458391361fbc8115c978e82037814d31aa3a88873ed6c74c4aaea9727e300d94542924c67b5cf828be827e581dafcbd16e653e72a4f2d4d0550805387b9417e77", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ecd0c9e1acb90ff8bde88f7757a089cc86cba27f0d15fdf737ab3b8ecf9fd9c8", + "result" : "valid" + }, + { + "tcId" : 181, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000423a2be684b0b5f04bef5c6ca8a991bf752f5964f6fdf36d7129100daf80f1434b6f3ca2a5e85ce005e1cb6d2b13094c434fdc1c095a3ae5e53f64949ca56691b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6b9ee618598f33c184cd63cf8930a4db3a2d4ea022d50e63cdfff85734a77ab4", + "result" : "valid" + }, + { + "tcId" : 182, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004147b8a2fb4f6e85eead81ca0b3f230b8d8cc230de73107d9cabcbc5b39e4e7eadaa44ec1ed0b95f6109223bc480e917419d860f9b9a75f81d6f8ca3ada377533", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d801dc9354cb756e6c27de5a7cc88ed5cb214ac5091b4090624ee8afbcba35f9", + "result" : "valid" + }, + { + "tcId" : 183, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042b3fe64bb142789e89e1092db46b613012bcfae57759ea908165c0362f804f36c0053faf3266ad7eecedcb24636b99c935f1c8e73168f0eeb3ddfb660801e55b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "03307ea557024686910d2d1d2d2760d82664413b8feec66ae8d2dbf1025f0c45", + "result" : "valid" + }, + { + "tcId" : 184, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c4ed72445465cdb44f58b0e1af0823226ea79eb2e1bc3f27fb8e4ce7b85f4a30c237e574c59a992406fd517f4d905e03d7a2b0a40ef85aa3c73bd46a1a06a918", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "dc2cd94321643e89dcc92acb0128d886b28cb7d66a0eaa5b96194465708780d6", + "result" : "valid" + }, + { + "tcId" : 185, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000418ef4e2fadaac1b982a7d2d12e9d5148ecf336b1d3775da2f7df822ad49a1324bd07046a3f8e949e7a0d960fe9d9a1de0f61497cb4e7b2f39aee6844396f997f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b831f4a0fb75927bdd2945c0081f11cce871c9d6dbf83b7895748c3f46375ac7", + "result" : "valid" + }, + { + "tcId" : 186, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004398ca1a944210a10b1f5732071259528df87d42d3d7b006bc6fd9e1e09f6fa30fed379db3f1bd915db2ba27384ec13715417446ee84fb5fd0a4bf6431cfd3f15", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ed607a9e6d41a4bc0535c5161c98613edac6b519590b481420fb2ba1ed2c35e6", + "result" : "valid" + }, + { + "tcId" : 187, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1c182adb101ebe5fec3910f80058e091d1325433d4fd3bbb38eb75bcaf2698a21218f7544ce84dcfe52e817ec0ba6bf84460f49932b3ec5ed27682d337f270d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "64a68fad2378591a18f8f2a4e346faf59da29446ec16b3fb8c37aef2d79faea5", + "result" : "valid" + }, + { + "tcId" : 188, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043f68c4e412c57da015568e0a9fcc3db499b77e6c0f55050828c50c35493af5e3d0b53fe30b0c6cf42cdf9f4f01d5c9058f8169b241bdea225932f9033f8bc5eb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0fddd50bb27666d4d38e6ec18c8ae1be3d763be7dd11067213e997fa4059c67a", + "result" : "valid" + }, + { + "tcId" : 189, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000456dd4c2b1d7a1a2d6559b5203fcb8974fa81be7d64cf0ae7a14fd965dfd69cddebe1ca78d5583fda3487040dcd94764f8dc619e8d74aae8d9665f340693c21b3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9c412023b7a66ebc9579a8d16bfd3109ba085c42f3fd395e07534529ad2340a4", + "result" : "valid" + }, + { + "tcId" : 190, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e1e5053b6f43b8714a025acfb86a8f51195488099b1f5d63310a6becd7ccb47ef0d16bc0c3234470ffa8d45f582fcb65ff9ccaaa6ae0cd6b572bebaa50c17741", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "28717726dc3674abb4f82b66837e8685ede16cb0cd965824352ac0a2f9d893a7", + "result" : "valid" + }, + { + "tcId" : 191, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041a46571a1438ca23dc7912a8a7b2245d70c852a6e9f4d385dd608427ec3c41e7fe06e2dedfbaa376a614657ce61701a7db181e5b1f3139045b8424ee54964b7a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2e74661109f0cbc6d587790330d67988658bcfabf1f7498a2b3279212828e207", + "result" : "valid" + }, + { + "tcId" : 192, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048ce5a3c8bd2544695a005841612a7c5d05beb07cf7bca1027172b030acf7d275fba0c339f74ce36d104fffbd5ae1c9c72588693190ed2b3687433087213b5bdf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d202df6662ba06d3088363c60e341283f7b6300104d58cf6d707262be6972b59", + "result" : "valid" + }, + { + "tcId" : 193, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a0abcdb1ef035e186e720606b07fd615532039275ac1b6f22720b756c0f857cf76e465cfdef30602b2e055a303bc6e176dfe972d06cc6f3821780387bd6357c1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a54a81c18f4b7ab0f3702013678566ce29e91c4142114d62f867a5278f89cfff", + "result" : "valid" + }, + { + "tcId" : 194, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004859b6beb70671b3e64991bb661180dbbe835f63c0a5878c3f83f0922660a7c093389bf4ce6b5c1c2f801c84c54391d53aa953ead5e51b7757b3508345bb4cdeb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9a954112f52d76709d64739dc75e9ce7a76aa19242b306391fcf25ff92b76901", + "result" : "valid" + }, + { + "tcId" : 195, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000435510d43f4d1a173a0467d5cb35a4170c3fc407e55b416b4dfce28650f8802afe8ef2adbde8b40a1714286176d674489bf9acb2e4a8353a7dae1a9e97cbb4150", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8763cb235f2780c1bbd35fe6c387d5505f72eb0a77b104c775c2b3b42786d7c9", + "result" : "valid" + }, + { + "tcId" : 196, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fa4af089c14d6a8be1881135989411607160d141a7a8cb4546f358a797d2aafdbe0086796436344daeec063f4f4a414a8779e72a960892335acdfbfd452f727a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b9309ddc5eb64a4d819a8a332b061a59f163a5f50d4865697e4d123efc9b2b29", + "result" : "valid" + }, + { + "tcId" : 197, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043cdcaa086427023bbd91b5b2e212be77de5591a1a0c210d54f0482f27c426558f8e1f4fe6e3bf037c0e03d4043c1d9b25436e0803b1a42b6de2e40d99e839c68", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "87e9f5ec4a9091d94ac22a6a71408213f444be094c618d459682e17357631939", + "result" : "valid" + }, + { + "tcId" : 198, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d7adbe30a5682acf9d398f58da8fd3b583283d9eda74ae067b9b533cd6c0824cfe50d0371c0e7b59043ffad25e17445cfbdfb3fea40e55bc7de19ac5f27c64a2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c69a00017184a13c713cc0a70e89c60174361d07dea5085fd707f4b5ed3faead", + "result" : "valid" + }, + { + "tcId" : 199, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004029e1c6eb37c383fb4e27ebb3197688f8d8af755db83b7628e17579cb3f90f058a2bf57857f5ff6331cdcf87440b6e69cc1b6e444ce540b8222b955c98a99955", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c139b75615e1010c920b07d14f6a1980ff4c97a0a9bb8a097aec2a456b6bc4ed", + "result" : "valid" + }, + { + "tcId" : 200, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043a35de213b2dc33eb348948a22ed5a93600fad071bb017a6a250e6609b13f7cafbec06b663a5f54689d0ee6709fd0da46acfd26038935935f749d6d4bc21060f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "70aab5e96e4991321faf440ca2dea861ba007df08ee46c6f579731ead51636da", + "result" : "valid" + }, + { + "tcId" : 201, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046b910d9e9943cbeff717ca9546aa5677e06118f5f04a0246b5bab73505775d65c87a4c1fd7bc584c56991119699b90b4b3a568e508eaa83f118332da9152b13a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e2ae03b844b3f279d5cd16bff20ab5cad07e4c984f21cbe73e1997a02bd2c291", + "result" : "valid" + }, + { + "tcId" : 202, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f102b90ad378725fb7ffe3fc3fe6efb320a728a03ce09a88ee25bab2cf133c04af2cfee528f3913c83504498ca8b3b6deb9e284241b8d01c678ab79ad8091888", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0aab6b19e4205548f929362e72b077f2365667bdd81d93a404343e7a5f84c6ba", + "result" : "valid" + }, + { + "tcId" : 203, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047f420fcef93b0b9d0a9f86b2c65e18938e17aa84eade2a7a6440adec914cb2f6ec1663baab8af308333399adceff908ee33c8f86b3df9ef93a51520931f851ec", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d96cdd08e6eeeca690989b659024f324e18c2faf5c50958da6985f70826095c5", + "result" : "valid" + }, + { + "tcId" : 204, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046b83adf58bbf00da4b77b6c4615925cf5a8f7b72997ad96904855490834bcf82224db940bba028dbddaf3cba949dc41b0db795515e34549fac11a183b89d5bb7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "434bd68e45630ca1b3484517da080e3c3198ddec5ef1f7e9d2e3425df214b90d", + "result" : "valid" + }, + { + "tcId" : 205, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000404102367dc53576a8385fc58ee2337e2b9af547e69934fe3ec797a84c225df0c621cecc727669f2e558762b65b33b3cf3f228fe9a9c22223ab71e77f904d6aa9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "aea47444c897f7157f336c77b7401979066d6617b59a01988f78f6c9a98feedf", + "result" : "valid" + }, + { + "tcId" : 206, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004258340105842ebe760c4fde13e31eefd52e51aaef938c4477d148bbac6d37412301f4b4d1bfe0e7046cb1f993a359f9191fd7bca7c53e039fa51db8a117efaa3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "486cf8959f7d939c4c79a0715ba7bbf0cc3fa7b2a1d60e86ad097c91e5612e24", + "result" : "valid" + }, + { + "tcId" : 207, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d9a521d8147c1e83df82b9db62b25e6ff1417ddd41aef3ffb182ad23f27822f7b0ad917462cd2a5abce2ec2c4a4f7456ebdb65db10d962056e75f6f8853d2a4c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5a1f0674b1397b6e653ff6e473d641da4fb9e7bc90a73802739a0349148500fa", + "result" : "valid" + }, + { + "tcId" : 208, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040b58006e371570686658d458f26faa34ccf8b49fba8234ebd7304cbba3ab1b2468787e9c7ea3043e0bf27aa9730a5abe473060b77c53bddc70e201d7f5b1d89c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9a907514a9ecc85f9659b9e97909a38f972b0c9a7c009778b8190438a8ebc00a", + "result" : "valid" + }, + { + "tcId" : 209, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044ab8f5ac88eecfcb0394f6cfe5528596b6b4c4fdac8247fd62957289133e620e1af51852e11b19d6137852e218fd64d2ebb567f8fa92a1ed43a5e34f5694a94b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "941685fe4de816261157b2fe3d3ac28195d81fac6225fd3103ee60a0c24df472", + "result" : "valid" + }, + { + "tcId" : 210, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004903201ba08353ba6158c06e66df0b413b771d21acc0832213bd03d589575e67677a90ccf2f3079cd2ac6c59cc0256a612c079b8a91b59ece1efd076f53bf5b04", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b203eb0365a40624a442572e0bad80e1f0c9958e5709512e76b28f4e0bfb2291", + "result" : "valid" + }, + { + "tcId" : 211, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c8021be2269a2ee83853e4a12bb0680825088d9ac0e56fb505109f4708dd9d5dd802ad690d8e8b817a815de607865afabfbed7650988f925ecf23fe5654d0c9c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e09d25f822471e647064b5b68cd2ae42d6be7b8765cdc026bb7696a524c83f49", + "result" : "valid" + }, + { + "tcId" : 212, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a53f7c412c11ad6a362bd2be2e7d1f20440297be86594abbcbea2594ddf9372379db08ad87b536939a70582682cb7570263655cc25a2979f845fd68be3d82953", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "97e3c29f69d9032e676933edb152f2438ec7dffb17641442ce9342e138f81667", + "result" : "valid" + }, + { + "tcId" : 213, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000446feed4e522963192cbd6c6edabd5175d10f93999a585a045a3026b69bb4d528ed7f6abd7b39e40e08e2126991ed410394bfdabea990abb7b2ca5eb9f048fa4f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cd7874612d68c907b434bd81bf1b1a83cf9429b24cee753cc228ecbdd6657388", + "result" : "valid" + }, + { + "tcId" : 214, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000467db11ee0b73071bf3b815864a178581ada3d100918365e7120d9bdec9cd9c3325f5eb5a1b66ad104a5c9e43b07afa4b152a75fa22a3e429af41e459e7993e45", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "621ddb1893137c12147e909dff830859dcd73ddb00acdb4097f1d66e14fe366e", + "result" : "valid" + }, + { + "tcId" : 215, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000414cdc4f16c07d6e6074caa8ecca26a0186347e723dcedf9aff9dc6fc8c3815bf5d64fe2d7e6abc20802a1c158040cebd614deda0347987e0cdcfd41e09618cf5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "19ad362ef44a36342cf9143b88470d5659fca6a3a30c904271f6d6bdc05e9407", + "result" : "valid" + }, + { + "tcId" : 216, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000424193c3501ffa77ebf1ee62f7c118b28c05a1c0a946f442b208a8305c6a745f8863603299dfdf5d2bda19230007d0e03ae61fe1caeafa584ddad4cea6dc7d76a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "43bd8cf370257bc88f38b0ded68af2f9d93977234a19fbf67abf2e0a4c09c120", + "result" : "valid" + }, + { + "tcId" : 217, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004081ceab1d3cd5317fc782c9c8dc33399705aba6899c0b804efa96ed4ee944da900adf51cd31b5000f2d175695d48a12213ae1595b98372643ec0eb400ef79d41", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9d920e7a6f61fe4140bbe56f4317e3892d21a80fb480a091a3c16a0a67a7a97d", + "result" : "valid" + }, + { + "tcId" : 218, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000413e56b207855eabb4b8a27dfe8d1ec89644be7c096f6c2f3a122c9cd0b8b508bb5b7970e3a1411f4ffe3711405ec65ef98db12a2b37d8c18c8d1984134e85492", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0796221792860298f1b4c5aa1561ec5db01ad876c3552bd96b00aa23ef47b71d", + "result" : "valid" + }, + { + "tcId" : 219, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045cf95e23e681059f008b32df326ffb7795bdf74bb337f77cff5052de7826794b5cb038ec1fdefde51f6c68dc5e12a198a51ce86b92167883687b253415d6d37a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8cec890842617de7789c3c2909e2d38031d5aad957d995bdec622b010ce9e0b7", + "result" : "valid" + }, + { + "tcId" : 220, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049c49754a4c45d97e5b70d0931b98f60b3a99f51a95497537bd85ede7e9879429dcadfe273a4086c30dde4755667923e58c463e8d94cbb7d56c9e0f4de79e6d21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1d4c7c7aa359140edf907c8234ef16b92f201f562c2237aa32adbcbdc0cabd0c", + "result" : "valid" + }, + { + "tcId" : 221, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fc7fd984dd0dc3c93846f8b41b07296ea854401325f155f1236f2e4414a9b9da473f38a5f84d08c0ac7a1dab8a568eac21066074947449a8c3d16f055a379bff", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b15134b9e91996e228ea7ba6cb4500a117983c8eeb687174657354e59961e521", + "result" : "valid" + }, + { + "tcId" : 222, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004337e2e260a3565ff81e0be900c8dafb2ce2310688c3eeb6c025cac208b08a18a4484fc5fb01c2d404da99b56a4dc226420dc3e676fd0223ba3a45d43cdcf3562", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "906acb96120ec7684e391100cf0bb747691678eb3e147f53db886ba0fc5aa70d", + "result" : "valid" + }, + { + "tcId" : 223, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e2b170d1dc4d9e329514a54f10dc81d902f3752c3a6e2f8be5d820fafefa9d8be087dbd390152ebb04c73b8c504b994a768372d3f920a5cedc4242bf834ccc6f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "73dd087b1cb3c5a07acdb9b0a4a02c64b7087ae97836e943439dbfdf41eac833", + "result" : "valid" + }, + { + "tcId" : 224, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046702ab6b257c24440bf719c02d2161e4e31e22d55ed8ad0f33e5af9568ac4a9abf87accc758577389042f5b650c37db6b0c7682203156de73728a582bed6a6d4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f73c49f6da537b2ff30ead7538c04726bc74152535d22b6baf92d06adb45e676", + "result" : "valid" + }, + { + "tcId" : 225, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040cec0aa4de0c143f5d4c3d36de3db4cd72e8fe0fbd336de879a562ac87e628d8e75d0d0ae3d7b4d869e7f6ff564e21efc30a15ff2d4c87618104fbd42ef5e00b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f4a757ceb0ba6cb9618acd8fef68d2c8fe9901fff14177f27b6e6b8c6bd34cb7", + "result" : "valid" + }, + { + "tcId" : 226, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049276151fb999ff3f7fcf542491fb62479fd1eae93fc2e7d22c38d944867c447ef0e7185e4d55a1c2eafa2cf8d262636d6e4b353fe71ae3d3cce6b158d86cf5fe", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3eb4a634d0090175347613b7eed6d49b9b5944e70acc3ed98474989d30a4c299", + "result" : "valid" + }, + { + "tcId" : 227, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e657a91abdcb67bffa8f78565ec796b4901f2991c12722d27bca6a0217f2b00c9bb2cf5f6c5780c70fa8f03159bcb0d56096aeecf53ea5e28d1058c3a50d2091", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "520dff4d04085871cff69b3a20a75b8f3b103da0e468365e8c9287c0a7ad7d9e", + "result" : "valid" + }, + { + "tcId" : 228, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047c051c1eebc76746eb267e8e91a47d8ab81b89bd3b3a9de6f1c3e6b98db81c7b75df088882150b97e20146547ee07b6b5620bcece4d40a53eeed84e5d4779a1f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c80ac13c5d2e6723e848edb023fc17ecae553781a4aac90f2577fae7511711cf", + "result" : "valid" + }, + { + "tcId" : 229, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d890400f1230fa80d8d4c95173924e9e7b3458f7e54680ab1834e505a2dccb26f714374c9978432830b8e1b82742ca86777f9b8b686b1924ee55e7c572c2b119", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0c28a9938cf095a4b0ebf3daa6a16e19e3f4199e3475ca3aa58746f651b921e", + "result" : "valid" + }, + { + "tcId" : 230, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f44866b8ee1b937d182ff79aade41b549b71ff1bfa882a192ec90dc87a51774d5e335f19880e8438b9f205932664512cd6dd53d5a40a7008fc5c98124a7d9554", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "78dbfec6b4aad2d0a99bdde7b90996324c0f7b9d136a6ede5c2995197d0d412a", + "result" : "valid" + }, + { + "tcId" : 231, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fd298ab944a08702816a7395f84e45ed782968b701838b67fa2528111cd4f4148599867c89174f00ccf30627815e6618bd2845f35819db0754180535bb4d4b2f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "36a2e77f56c3e5b11e35bf4ba5de1885cf0264643cac5d6f7bfb1ae01e39a6c0", + "result" : "valid" + }, + { + "tcId" : 232, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047b78d59967ed07c83f0ed7f8f0b26388db76b0863b64ac14b7ecbed8e3a1bda24b49dae1adf948860741376c919cfd50ffcf749672f19f78ad565e88f6096df6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9f4e92d9a959c09eeddd152f6d95ff2c3157446f477fbed214a00621d014f936", + "result" : "valid" + }, + { + "tcId" : 233, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004791c9017b3a93ca2f2d03fcf18b4230331fdc3de5785e847c9f51d22caf50cdbedc729c92f0a88233a29a2259e7e6265b92a1438c0b5959167fbe2aa4a65a6c0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d0b16561349f182ef2792d0c2dd585601ce4e032754b7628b3d801f187c14fd4", + "result" : "valid" + }, + { + "tcId" : 234, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004475786ce215a1873e04a0c67642c319a6d24dffb06a4cffbb15a8256d2c811ec5a1bba7f661e38d694d9a11564b511af6c6632a5efc933732642dd5c4928a41b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5fd6d7f0ba317a36434e1a995bed54a42898d940ee5fa4578373e8d4c23f5567", + "result" : "valid" + }, + { + "tcId" : 235, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004759ae77233b119fb3789059760112f38e8d9e69f431cf0e8f0bbe6a06e23bc5b18d69b80980f53b7e8c76c9b82dc61f05cdc03826c2c9637cc02af2a6db0e4fa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bbe559b77e83905b08954dc3736a2752d56a5bc366a5fcd84e042a78c8af68d3", + "result" : "valid" + }, + { + "tcId" : 236, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043af2b8629a3475294ee0d5437321fcd5fa4554c780b6b18b86242d3edf36f551ede37c4ea319d42f8fc3cf97cfe7dd17e85ba6e11ba260ed991c22ee891abc2b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e62429b8eb322d24e4bdb9a72bf6e9c94d82962b26d99f633e1f21709b7eddbe", + "result" : "valid" + }, + { + "tcId" : 237, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ca2df3b3d7d958b0d46ed6e0ffe3b7488f2e13660951eb821c24246d6c7f2ec2055e780e6a534f9ff469b0ba3c8d38962ac0acdc7b4b3dc057c07ead3f4b7aa0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5822c168aab9bb6ffe00b7c4c7be5551daa8304b8d2c0696e2d77fe50b9d8d8d", + "result" : "valid" + }, + { + "tcId" : 238, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ef17ac084abad12496df80d80dbe21dfade58e302ac0398002c5349d852528ccef34500266a5dd3fb454828ed85684a62e6eb142f65f5497e64d23148f757976", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bae26fa69da00aa03fd9028fa84d46b92c13d5e555b2e7b3db0d09bb95d41486", + "result" : "valid" + }, + { + "tcId" : 239, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004624cf7459a3e097f114383a125c7cdec33b947c5bc0a2679d7aae508b5d46479408cac791f2ed71d9bd594bd66f6ce70d928d3b20fe02b5b66cf743b51739a74", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "97ce8c4b6e031776b19fc7c9577cb26f085274a58407267bca35a97692a2e8e6", + "result" : "valid" + }, + { + "tcId" : 240, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e41ec556bb3f85cef6651a2db1816dab3bc82898871482dbf1cc801407ce4d1dedeafe8c33721250bf75cdb9181e990492d37080e7dab41da1673d62a8b835df", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5eb5722f98aad0622097d944bb120e09e7a122498b20ae2bfff91c8b362daad2", + "result" : "valid" + }, + { + "tcId" : 241, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b5c3cb146d30fecfd7fed0093dcba01846a28aa50c7fe3c0cf4b8c5aa837d5b0b21b7605cadbc7b6206e5dd4289e1de9cc36bc98094fb18223be636e6d36e0fa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f5c9b88d48112041334c574f93313670cdecbe0c0b6c2655778df8ff62025d3f", + "result" : "valid" + }, + { + "tcId" : 242, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b3c62848beb063fc8f285c0da7207e707c71460b8f792ae0890f2362fc8f02109cf80c0e0d75d2f54a6bffe3fef39441ed0cbf29c8397b76a824ff9ecf4c772b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "effa362fce62e271016d50a0e35c031455fca280b80ed2cce87c83e57e3cfd36", + "result" : "valid" + }, + { + "tcId" : 243, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000407ad8cd055528feb4b3a53d354c7c7cc0616ca3ff787bbb0bf79909606d27e8a70b4d271ebd8363d9ad910cf4d84e52171b5b359792f7ff8a89c4427fb6afa21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "59b8dcdc6676029109871fc67b466a7fb622225cd6c77bbc21b1b628464798a2", + "result" : "valid" + }, + { + "tcId" : 244, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047c66fd67b79f88531a0747288726dbeb299dd8e1159612bff2d979fe4bd1060c15c54c5cf40b7a6b36f4400bdbaa2b6dd0669c3b45a55925635287116aaaff1c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "42dd3a8e14dfe9fe2ebf80746989ba66f28e5460116a02bce24c549d117d6b0f", + "result" : "valid" + }, + { + "tcId" : 245, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000494064698280e7eb6e14dd81efa9f0ab527fe6ceeded60cd4d422162c397d5bad163a63342b44629e57c09bb490118b1daf06bc0bd1de48a98ea7ac3e893e4470", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0e1025b39c5481a748a0461aa7773a6b342adead4b4587521a1953d4ff0296b", + "result" : "valid" + }, + { + "tcId" : 246, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b454039384abb191e593463976dea937428b76a2f21f8553a994e0e23a0de3282888d4e22eaa986dfcd20e5a4c9666a2a341eaadcdf86b6e137660c95561566f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9dd7118006ee56fccf307a31a6334be7e19db2deca68fd45b3f4f94f100de6a4", + "result" : "valid" + }, + { + "tcId" : 247, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d43b704bcda6ed2cd8cacd64a67191da2f68f25a6a983dd79010b1066942730f2eaa0d0933f710917e3223f2feb23388add3fed3a2a7de18af50803b0b20d6c9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1fb16336393ba603fb2eb701fed0e982ad32964afae7dbbfbc5a8112382e51e3", + "result" : "valid" + }, + { + "tcId" : 248, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049ea3db44d3c1e09715ec330d3607a06cfdc1b0baf4f570fbad15d63e1a8d190bdae78a1a46ed6fdaa02ea2785c2bad33aace95397b290eb7c26428ef68494abf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9a6d03a17e68561a105da66d2fb1d9ec9e3ca6c686f65d9da926849d7af4fcb7", + "result" : "valid" + }, + { + "tcId" : 249, + "comment" : "edge case for computation of y with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e4cb3b67d62108687c74b36a081c3adb9fc4e188b5e611727312b70886e81a795edba4df71b9c4b06f7b052b5b48d9e0be855ffcc2f27926524cb22ffbb9e865", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3c03077e0098a845f7c9b22b73eecd495a2d6a0b34d211154ee3898634f823b4", + "result" : "valid" + }, + { + "tcId" : 250, + "comment" : "edge case for computation of y with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046e833dc786039cb081ca12034adfae41e3454cad0976a09612f1af4c390d589f16f499bb679ce63d15bd4b821392e6c3deb9ac2163d0211a68a6167bcb5dd0e2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b8454bcf8463c2bd59f7538b65f11b9c98c18c13438417cc08a39c8842a0b7ed", + "result" : "valid" + }, + { + "tcId" : 251, + "comment" : "edge case for computation of y with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000493b0cf66e6c51ec9f5b02589607443bab7b97b18f3dd2c9cc831c0a356b60c21f960bebf79b0c295794237c60576d6a74e5f694d9fccdc2c4a469e00b18115ac", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b4df5f335a0461a38852205ac73bc51512b5c7f6a8305f1a8d4f191cb6fd3b2a", + "result" : "valid" + }, + { + "tcId" : 252, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000467f4d7cf5b8574fa36ec8d3d4caa369efe0521ff9e25760cf99894c64f064ca34db1597fbd96d7b7e319236e0660b05800ed99099c8c1022d55be3a8fd231e96", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a9de6e92af14bf4eb11d7533bbcb28cf622ec5e52e4a2f4cde4ddc3d21babcee", + "result" : "valid" + }, + { + "tcId" : 253, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004439638adcda870137436eeb09e27c32637307921974b64b9f73e266d8e95393094cfcf350b98282437974db3e402fd86e3ebdddc5e23fcd07303a0a5cf282ba4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "edcd8e48df11aa67a90c75614983466d244e4b5473f8ac01a41c146db13c4827", + "result" : "valid" + }, + { + "tcId" : 254, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf32693dd77e182d8b2650382832f37f6770090132aa77a7ebc18215e00c44c04642ea3461ff10e2e1800dc392738d7d01174679c9d2e382a80ed4961fe48b6b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2c8dd74792ced281f9cb161d2f64d238cbac2d18f8661b0f5674d79cd5c6edb8", + "result" : "valid" + }, + { + "tcId" : 255, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d20a02a6d0424820f7c2ed6afd1b7c149f6762bf8ce4dba50ded9792368dceacc574cc6298fa1d96edd178309f7508ce8aabf69fc0c49b85299baf91239e6665", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "503fb9bf4b57b00e0c239b3e8371f24660aa01cbf79f4c499e4fe1a155528ff9", + "result" : "valid" + }, + { + "tcId" : 256, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004afd321e9ff7b24d856bf14bbc5afef1952744867cae4a9f3e38f6673da908aed714966dfee5af5b7ddfc1779db74987e9e87f532bea76a2cbed717a36c9100e7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e61ad5f80632382b626f9a77fb7f5db020dbc084c888c6b09993e12fe4d31604", + "result" : "valid" + }, + { + "tcId" : 257, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cfd6d84113fc920b44bf6d67cb841691dbae07bd6732e5dec045e60d90b98f7110cbf8c9ffaef36f3d53132b1c10db5672acd5df5b87cb98d19daf87b0de3573", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "51c10b8332b33faf529c58cc2da45a23bbfecc1d4e0aa4ea54fd819b7e31e555", + "result" : "valid" + }, + { + "tcId" : 258, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f09616827b93b6017d770c75e35b0162c5455ce2380ef2fec54e336dfe94cbbcf3d01b7b102bec4ff0245db8c943c68c23cf1172c65544aa1174e44cd524f049", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "98d67822c318db0653a470a6ed96e7c22a046a2a25664c19539af62ae1d3a96b", + "result" : "valid" + }, + { + "tcId" : 259, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bfeb62d5cdb7333e0976fad3a259ddb9cb525aeee68327657aed59285352f3476e88bc9799df4d0c142bc632c81d40486fe2376392e0180af93debcb82c639cd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7c4648cd808df9a54f992b294a3ece562ba5efbeba7e1760f1f107ed1af8c187", + "result" : "valid" + }, + { + "tcId" : 260, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046d864a7cb7f8e3a1fe1c8094e3852f8f43cc4ca6a9039512b2ade5f040e3b4237c908ec1cb9fbc1f6d49460ac19f2d4526f66e00db60d207408bd46c95bffff0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "41b89b46f018a3ac884ad921e49fcf5d9677ae84e39e6ea8de844acc337d8481", + "result" : "valid" + }, + { + "tcId" : 261, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004feb68f41e806a239f62445d23d1b925978a9b696d6f0caa9dc29f40539b073cc2c902affb20066d2c2c920ceb8a453e42cd2454988c332cf0db907bb4fe95943", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d155b0e0e37da1a19af0e85e68e7bb4180aab55b1e95501a1a3ae0cd95404aee", + "result" : "valid" + }, + { + "tcId" : 262, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000457d04c653325a6cb998f61ce347109eca0efff9a16a734134a69cd1e0b081aceb43aea4f71b1f2802fbe4107d0bfb9f6fbbda464501b87ff73c47103e372f635", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "12bd72e952e6b81255ad79af19310da2e0ef9772003384a1f35753e6beab71d6", + "result" : "valid" + }, + { + "tcId" : 263, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004605fd33a42d921e01ee7f75806106de72cb5039f65ff31d6ca2e1efd6aa81a1c95789f0923d705fd19d5a8ae18b66687cb29091e17944b37d27f398bd5546bdb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3514b8362ee1e70e846ede7ed57283f5d5891fdb9b0c5605da45dbc5c6f44e53", + "result" : "valid" + }, + { + "tcId" : 264, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004303ce896aa570cf8f97954ba48fcc25f5f252867f01a9b9edeceaa6bfccedf561134d6290e1649bb028a16c6f54eb06c7e724a947a6248274a4bf6a6aa139096", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f6c829ed9ca3dfdd1f165a204461e1c16620e752216e2b6e3aab6197f3dd2b3b", + "result" : "valid" + }, + { + "tcId" : 265, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041c2ca67311dc5c454dc830386b7997e50bc67e3d5ff522d3e8a39f144998f884862c975f548a5f55dd8504dab5c9e88f0ed3123688d475b211da5a4d6920dd63", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3719f7afe82c3fa54c0c1260476246441d387970935e4c76965ced96da3a07de", + "result" : "valid" + }, + { + "tcId" : 266, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045633cbcfdf74327de0883f59e1788eed76bb0b9e0f9e55e2769ec9aa365a30e1d913bd531f4a61c2d07b847d318ee96482d2f8fa7a12aab3b303c10851ce7fcd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0a368c74c56c61aab02440e64b2699c24cdacb4dfbcdebe0b3cf801e86f1f74f", + "result" : "valid" + }, + { + "tcId" : 267, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000419d53e44b058c317fbedbf106c98f31832cdfb84f21add753cf213ba5de9026a614cf7b7b60e759a15a6c7d864eddec6dc253519975df7f3e9bc0c77fd80e510", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "de5b6c29f2f4f17f8ed925f129159410e4557dffc5472944b8862c42bd2b180a", + "result" : "valid" + }, + { + "tcId" : 268, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041c96cc2b22e5bdb195b2a47187fad5ee6736bd96dcefef20259a551e9847b5e0c5ab052c8836e4f7cc7b65545775d55b0c7b0c7f830c6539915cb624a507dbfe", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8fca30fc5d731f42d37664d52b64e022d98a25065fb1f8bd77853d7f2bbf07e0", + "result" : "valid" + }, + { + "tcId" : 269, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004733242cc4afb82271034111b81309e156ae4466e7f2fc5fc1042f4f6e3c44f435c6f614d4be18a73170c85a6b68a9614052934e1d612466dd4921989474ff513", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c9431b6deda0c9f92f368f7ca12986f0e07e012422b840c7aa784a0c713b501f", + "result" : "valid" + }, + { + "tcId" : 270, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041a24b6520af4f028824beece59b603d15d6d15cde0719ad2f7b8e3fcb6c1342c7ed702a30e875b2436db2f2d3687d9580d3bd7b3f8d1280a81071f3ccd6b407d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "672c2339e4c39e36cfe13e2cfe352859e1ef66318fe9f97dd26d9d03a9171f7f", + "result" : "valid" + }, + { + "tcId" : 271, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044ade6fa13e59117e054ac1bca3ca52f414035493ac2ee7b1a811f1fb52521e8116ad612cd7ab0c21ef78938945d870dac827becb5b873c84225c4aef159ee4bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8cd11340313b978fa37749f4b367c087fd900f17941002de22ce4029aa550e7f", + "result" : "valid" + }, + { + "tcId" : 272, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000434b2ac5a3e4916d081d1ed404b5bccfe076aa7f41e29d0362390f7f08458b44c25987b7f7a214323763e1aa1044a8779bbffc5e22be628138a1d80268364698e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6f1cc2d07f6ee07d0b138b601c94deb20aa234e526fab3ee4adc98707085a73d", + "result" : "valid" + }, + { + "tcId" : 273, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000458c25f4047782b815b41001dea636c86ef19d67ec056324127225aaf6ff10832761325c4a70307dceb9bf451c7405e42580868e665f3f259995f8c358eb0799d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c2812eb9b456297572e8d870754b48489ea366f351f822759de831726815e582", + "result" : "valid" + }, + { + "tcId" : 274, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e3d05f1aff72acff70e4d51b4207880ec06b4c269db02753d6d858aa5e6d561e7c756f6b0cd106bb732e5f20c91ddde4f24a3699df1125206fcc47449abb7d1e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9cf1689a015ac3958dc95fc71cb0d103e81b4594684638933a5daaa99fb3b1fa", + "result" : "valid" + }, + { + "tcId" : 275, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000475638ca9ef9fa252429d21243c778be355bd130c1ef626593ca0c244cf2b6ef253b88766230ce8ded7900956a5291a6967c2a54279844cb07d7c585d87d40661", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2d6049f8e46c67c17ddfc8178dd918b23fd1969e11c959b64ea42e39c9a87dea", + "result" : "valid" + }, + { + "tcId" : 276, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000444682e437448730f594a820ead232c4443f7e784370bfb031304b85199c4159f7151eceaa0a698d15785cc7a2e812aeda12f9ba4238a7f5e76e930f3905015aa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9b7f8be262b9cd2751ef8eae2bad7b1ecf07cb76613cfe7088cc9bdef1d04436", + "result" : "valid" + }, + { + "tcId" : 277, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c98b01fe92feae441d9f4de50d4dfbe9789711d911be6ef7cd9c55f4b3e8cabdd9e3aaf16605b0ab50632df6c00ec8554f36ecf427d31df930d4458fe1cbaf11", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "52980b5980df38f7c2d59e4e307da25655d50c6e030234b241c098c935a5596d", + "result" : "valid" + }, + { + "tcId" : 278, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049173ae014b645724587ee26e17bfeb61f91253fe8653dafbda4381da9fa57e9815a9166e1dfc2a81cbe126a2594e51fb98fbee7b3d6588ad86a86431141444f4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2f1f6990c30136d6f44de8145f191840c4b9efbcf87c39b7995c262bdcdf9d40", + "result" : "valid" + }, + { + "tcId" : 279, + "comment" : "point with coordinate x = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "afe5b60fe3e1dc873b3f3022893a359880e817537beb96b3d48d375766ab59e6", + "result" : "valid" + }, + { + "tcId" : 280, + "comment" : "point with coordinate x = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e4102f16fa7f386e912d3a7f77dcc7dc9f8af54cae117ddba10a3d09620eff8c689c20e12ce8f78412945e1d3acbf9935e4653fb0dce02b14a7d526a114f1387", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "33150538973510827cafdfe9449e7a5a2e1a7946f4e485a00ff219b2cd58d801", + "result" : "valid" + }, + { + "tcId" : 281, + "comment" : "point with coordinate x = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047aa67d0033226fb2b1bf975d4568e1f2299e82f2e459ff0b6ee3c0c57dbd40417c20634644993bd84aa361037ce8bf3fb72286dfdf4482458b076a7a5f46d1dd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b5523f9382b35ed9e1c4f2b420df9f61e6ac8f6d342213fa4d75458f5bd828d1", + "result" : "valid" + }, + { + "tcId" : 282, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480694ba7d6ad6efa8ad5ce0435a1bd225e0288b6fc22a11e7013aa0d4e9a496b316d67d1c70e6c130420f57cb6e0d60cda154c737f0118007cfea5c2d5b4e397", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ad9a53d05315009fb1487369f72fdc33e6dbba1485efaede2951433526d2fd0a", + "result" : "valid" + }, + { + "tcId" : 283, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000406c66970e539d9ae0f8f67a72f426c100b3b2cf2e276e9b0aea75b4efc98832524eeab2b413ba17db811f740f9fb9fc3c73b5ce51f1e74e7e08bcd8ab48dae83", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a88cca88b59cd86edda202cb4ea1b2d541d5c8c22c062a08f9db496d56257330", + "result" : "valid" + }, + { + "tcId" : 284, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000441277a6f20d855af6acec53e9923216d74ee2aed18a4140591ebbb0b3455072669bc7f19d64647e74ff00d0c89bbfe508e322b4397ddb8564ed2832eaa5b2d92", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b7f531b4a9ac00952bfcf2cbec41e58b54c4f412f464bcf1f1bf10a24b9b1974", + "result" : "valid" + }, + { + "tcId" : 285, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004146dee2bcaa5cc0817fe191b6d10def6259df744afdc9e5b0dde523b348aaab445b1546f79b7a6aadfa547bfa416f62b54f7a476d6d888056b9c05c72e0139f1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "473473518f0e843d1fb5105b16fe88edaa418b396cab7cb5532416d171f2e7bc", + "result" : "valid" + }, + { + "tcId" : 286, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c48ee90f8fe800664086ed5ba12930cacdfa175a67a2c4398168f626699deb8dd78c35a48042aafbc6c7caf3a68385ddb5d406acee86d96403e75baffece00e3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c2563f49e623b139a83c4cb71cb73deb06458385658bf8796bac0c2ed12c8a67", + "result" : "valid" + }, + { + "tcId" : 287, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004737d92f5dad51d58261a77e755678ab02b107912041c5d295f5829cbd10cd8c59b55dd084f84937c27565a9075fe108745e17001666743db551436e691ea818d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "28c247ae91fdac1b29896415fec60f4252feed9c9ffa0216d31350d708646d89", + "result" : "valid" + }, + { + "tcId" : 288, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000459efed747303891baab0e1dfdc32d69906e0fc6815b056dae0eda2080957a3ebf205fd299c63e549d24c153935d950141c3dc2699afe8731a46304e203cac15d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "76e9e6f1339bff54b82a45980745526ff9249e942b1f836aab719fd959fc8099", + "result" : "valid" + }, + { + "tcId" : 289, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048ef9a7997b717fdbc5d2a7f9a67f705e5dee4c82ca383b7ee2d07c24850396d072c98f7dc1658f9dc3c434a9fddc2f986cc0e3e3ef409827537617ee67105f2b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0de82177c80f4e35f3b7a300e89ac288f30e01a8658933c16b8c90605e35d6c7", + "result" : "valid" + }, + { + "tcId" : 290, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000404569ec9fb3d6bcedc059e7fd04ab7d3f6bac730b1b75a11749e4346458f9296a051c84d558dbd2957c15907477776af660ac01582c001dc1f868ebfc6b3b264", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f41de3a77597835fa904d1f05411368e6e878abd0485477d162b2c764ef045ac", + "result" : "valid" + }, + { + "tcId" : 291, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044b298a3eba6a09fcd8415976e0faea997fd519ffd3363bd20107752123e101466abb70c013ba2389c371be19dd3296f0600e64f05755e15cf89320ac7ffb25d6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c4dbe3b94e729b1e0ae34ffb0f6b0d95d7e619ab3943aa3836cf1e721a470a9e", + "result" : "valid" + }, + { + "tcId" : 292, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000418bde07952d7be8914d2b2544c65a3debdddd9e7ce8a9c46a03d124acfb8548b01a4a175a2a81af98e6028770d055e22f1016df15462b65f55a2d4850cc415e5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "83b31061f1b70148870a9282a4641cc8428943a3b10e0301955f5960c386fb04", + "result" : "valid" + }, + { + "tcId" : 293, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004002beb755f694a09f60bce5b34dc347c5c3aa236de9007bcdd0707e9bc8071694f443b0045999f2f5899ca793424a9b423b0ec0a3edcbbf4afb9e66526cf89b2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5f74c066595fe9ea283274964ae83fba1a73ef9d29d24e6604a4aa0881fe390d", + "result" : "valid" + }, + { + "tcId" : 294, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004957e5bcd11fc450bffcefe636c0b73f10fe8585e04c6c7aa7fa0b603d24162d99e553e940956aa04a237a0c2570a0c7bc3712172b8f78c7b470a042ae31f3223", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c672601d951bdb550ea9cc58d2031337db39a3799de21af4e5c23e2fd7f537da", + "result" : "valid" + }, + { + "tcId" : 295, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c43b1b4099da70f8d33fbb61b68d9b0e9c7aedd4f4761c6722996666974e298e978c02ea7899cdd46a47405ac0d89fd6a4d66718a4502438ad45463260976841", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b2c2c00532d468d25374ae2e6ec9bc52bcb2e8df20ad1a40719b7d91746daeab", + "result" : "valid" + }, + { + "tcId" : 296, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004deb85f604be1930dbac6629cb96210f6fbc87ce2b260b66cc7d661861806afe1120bbcf8356dcfbf1de4bbb7d2066c3dddfbaf330af754c57859137a9cc4a68e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e5fe7c96371878cf86db4210a487d7d33ac4bcc45b8df2152e82aa7228a991e2", + "result" : "valid" + }, + { + "tcId" : 297, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000427899fe24811adc869d49ac451cb210631d19aff8971ac7c3dd2fe826262507fd9ddffef4cc9cd81bdd3eab8acdd5c287a8934f82dfc255dded1ac1f1100aa17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1bb9a501ab9d215230cd1072042b3c8271aec3b2c1da10d1a8c810fceaed47a4", + "result" : "valid" + }, + { + "tcId" : 298, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044301f54b3592d1ea2a40989c94261d2b1d1fe297ed6ed64125ee241de05d004bc79014f156e9b7bfb36b8ad2d66d55f3a753829a9ddb86055bb9166dd3aff457", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "fdc15a26abbade3416e1201a6d737128a2f897f0d88108645453a1b3ddd05688", + "result" : "valid" + }, + { + "tcId" : 299, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000436b0f66bf5f9fd4b2df9cdae2af873a075c55497d7fec4737a7c9643c2c76fe5da9f7287b3cd4e5f05b9a1a4f64e8a8d96c316e452594d02a4592a2107ece90b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e36348e3a464bc518384806c548e156edd994cb6946473c265a24914d5559f1c", + "result" : "valid" + }, + { + "tcId" : 300, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000482abb58afb62d261878bdee12664df1499b824f1d60fb02811642cb02f4aff5d30719835d96f32dc03c49d815ffa21285733137f507ce316cec65ca562ce2ad0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7d65684bdce4ac95db002fba350dc89d0d0fc9e12260d01868543f2a6c8c5b8d", + "result" : "valid" + }, + { + "tcId" : 301, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047de7b7cf5c5ff4240daf31a50ac6cf6b169aad07d2c5936c73b83ee3987e22a1940c1bd78e4be6692585c99dc92b47671e2ccbcf12a9a9854c6607f98213c108", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6ec6ba2374ab0a9ae663f3f73671158aaabac3ac689d6c2702ebdf4186597a85", + "result" : "valid" + }, + { + "tcId" : 302, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000406fa93527294c8533aa401ce4e6c8aeb05a6921bc48798a8e20a0f84a5085af4ec4828f8394d22de43043117b8595fb113245f7285cb35439389e8547a105039", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6d6e87787d0a947ecfbf7962142fde8ff9b590e472c0c46bbc5d39020e4f78a7", + "result" : "valid" + }, + { + "tcId" : 303, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048a4f625210b448dc846ad2399b31cd1bc3f1788c7bed69cc1cb7aac8ab28d5393007c6f11f3e248de651c6622de308ee5576be84ef1ed8ed91fd244f14fc2053", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "56ea4382f8e1abfcb211989f500676449abcebfe2cd2204dd8923deb530a6c7b", + "result" : "valid" + }, + { + "tcId" : 304, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004885e452cbb0e4b2a9768b7596c153198a922dabbb8d0ca1dc3faf4f097f09113be9aaa630918d5056053ecf7388f448b912d9ccfbed80d7ca23c0e7991a34901", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2c362c27b3107ea8a042c05cc50c4a8ddaae8cdc33d058492951a03f8d8f8194", + "result" : "valid" + }, + { + "tcId" : 305, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e226df1fcf7c137a41c920ff74d6204faa2093eeffc4a9ee0a23fb2e994041c3457107442cc4b3af631c4dfb5f53e2c5608bed04ff6653b771f7cd4670f81034", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0188da289ce8974a4f44520960fae8b353750aca789272e9f90d1215bacdd870", + "result" : "valid" + }, + { + "tcId" : 306, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f53ead9575eebba3b0eb0d033acb7e99388e8590b4ad2db5ea4f6bd9bde16995b5f3ab15f973ca9e3aa9dfe2914eebbd2e11010b455513907908800396fb9d1a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f78bd7ff899c81b866be17c0a94bec592838d78d1f0c0cf532829b6c464c28ac", + "result" : "valid" + }, + { + "tcId" : 307, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004882773ec7e10605c8f9e2e3b8700943be26bcc4c9d1fedf2bdcfb36994f23c7f8e5d05b2fdd2954b6188736ebe3f5646602a58d978b716b5304ea56777691db3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "99f6151fba28067eac73354920fcc1fa17fea63225a583323cb6c3d4054ecaca", + "result" : "valid" + }, + { + "tcId" : 308, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a60b6458256b38d4644451b490bd357feade7bb6b8453c1fc89794d5a45f768d81eee90548a59e5d2cecd72d4b0b5e6574d65a9d837c7c590d1d125ee37c4d51", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "68ca39de0cec2297529f56876bc3de7be370f300e87c2b09cdbb5120382d6977", + "result" : "valid" + }, + { + "tcId" : 309, + "comment" : "point with coordinate x = 2", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1af254af90c16dbd217f3356f7fef9ad532d4902a6d67218e3188a9e840fc929", + "result" : "valid" + }, + { + "tcId" : 310, + "comment" : "point with coordinate x = 2", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000452d9a44bf0bc729e5f3ffc8a73a4da332e2962b22013391b60eb66de6e1b83431eb0d9c6e92a424bc24ab23caf99e3cda830263689653626f8be91590fb75cbd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9e232223afd0d57a7b150f65700ac60a78bae2aafc0cf9d1a820452ca1e57a14", + "result" : "valid" + }, + { + "tcId" : 311, + "comment" : "point with coordinate x = 2", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000478a99dfcb7df4d9277f97b5e24e979f48a8aa8983ef9dd86765dccc33d8ade9f9857dccce2a7ff0ac41b255eb8df45df61b4db58fb5e997614bf0d5ab217dd90", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ec2f7542cc1df665764c5b9bff751208d668be9f3d61cd6c33b35ed0f4fe5a17", + "result" : "valid" + }, + { + "tcId" : 312, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041162424aa9fa0d42bf60e06a16b7e7ea45ac0e2f07f1e36735bd0d98c70b8850693f2ac128f47f213322c5f8872dde9261affe614e3f364a792d17b0e8421840", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b095e9c2f933a00053a95758dc20fe1e72a798462f90fd67fafbbd68d761dd67", + "result" : "valid" + }, + { + "tcId" : 313, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000430d2d42a85385b64817d0900bc8c984716934529056da032d5fde844915d669b0e5ef40d566f5b23992132c4ae588017ebd160e5dbf4804f936cb0f257a93446", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "95484c5554b543f8eb2fc218cc46ffe648a3bfac41e6dfafca1ba11f8c53ed6e", + "result" : "valid" + }, + { + "tcId" : 314, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a77a259a55ed98d643e1a3e13804c95e543c1557e6141e4ed47dcf13b941a6fa8bfa5f879ab14aeba7b2ac06e5a719c86f4a2ed391160380aa3b6f74141cd354", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f22ebb6843281b54b22a9ff1a91485c7db8f95db4bf8a1131f892b3bfce56662", + "result" : "valid" + }, + { + "tcId" : 315, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f89454593dba5720164d17bc1ca32f10ddd1a7d37b7bf02e5ec0d59794f4d63d34268de3f6a2c108514a52702f7e67d27829fa0340b3c4710651291483c8b213", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "99623d9f447b66cb322488ea463b3e40d5620f4df78f89c62fe0ba8b90ff386e", + "result" : "valid" + }, + { + "tcId" : 316, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b00befcb868eeb5d558ef2ec2ec679dc082ec15a57c5899311178424674b8f50588742728a6384a180506b8739a79c4ce95e1055c0d0eab2254ca55b18a3e7b2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d611afb4046c9f4b2887b7dd4d45b80e9584eca93f5a855dc30e529eedbf5017", + "result" : "valid" + }, + { + "tcId" : 317, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b3e2f9c7f9f068c5da8882fd581e7112e538aa01feb5f017433c00fc8a828fccc56a3f692e3b237b7caf49869009e6743e35ec5aed19d814cfc13869f78eb895", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0438085ab0104fb47c696be5c08f95e319ed5507ab781fe1cdccd6ddb34bda67", + "result" : "valid" + }, + { + "tcId" : 318, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e5dae9779e0c168e60b842508e253d2ac80e7e504daed9fac077b9b449c368b57bd8661bbbccef478f050f4ffec8aa47ed7f98e89514d9083facf0a7f2f7b70f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "326dbabffe17c6efc710bdb8d04d16c8624c083d48bfa6e4411d221264d8277f", + "result" : "valid" + }, + { + "tcId" : 319, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004420e10bb81b379d728879fe600e6f1bf2b85d8023848a040c7654a9734da1ac4cbee561571a616b094a38436e02c6d7b54b4279a234193a828e86e21e6b71d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f47a91e29ebe69baab6b340bb64a6dc34fca7546fd6eba53f5bbe41f6178c7c6", + "result" : "valid" + }, + { + "tcId" : 320, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048dbf1ba87597004af552317225916abf3d71dff90fe9e61f9d2863a6de218d4a0897e334000139b0849d772757b150e5d86b55d7a00a744bccbb7cb8d1a6b07b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cf83319c735348dd13c44b055f67a292f7afc5d9d2bd0706c966ad765368d422", + "result" : "valid" + }, + { + "tcId" : 321, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041accb85b612d32d58459caec0bb6768f05ce8094e3862422a7c12340dd31bd7397e0377d33ccdce8bd872f898be6cbcf7274b3beefb5dd7cadddf027d0c02c2e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "41ee7801ccb702f2f633d1d0ec20d7c427936886df89ad33d19dbb56f66a2656", + "result" : "valid" + }, + { + "tcId" : 322, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000414eef41b67c17b1d4a040554287cd6a9e6b3080335ea4e16821dbd643ec67dba6d67cadcbd1a3f0227b7caf2c0604d2b3507aeb96ed98c32e2350fe295ed8998", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "af828d6bc21ad6b4570b5f68a6208d3a2f46edca69b1980fe5046792c68cab80", + "result" : "valid" + }, + { + "tcId" : 323, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a99af5dec3c995080ddcc15d7994daff266aa53f181fba4bcdd504d206bfca2f3739588f071e4192b615361ec81735fe2ef2923c4056c432f4c2782e5d722215", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4ebf7f174cdb3fda94f99698317ffef5f4d4fb933f3292f1aaa782c354ba03e7", + "result" : "valid" + }, + { + "tcId" : 324, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a355d8d17d50f6428e0af345921662587e2b6249eed1e326abb7c8605036b1db1fd72efaca9082bb6fab44359fa7f6ef8a45d036852832e2ade9d41f28219144", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1649f83c47a6640a94b773ab4309bd6964109433e3f3ee5b024d1915ef5139de", + "result" : "valid" + }, + { + "tcId" : 325, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fa53e5b58d55ebf517d8db07b021d80918d1f260f9e0b3d00bd47b24a91ae6ab85ab2adcc31b98caaec2681a841d50bc0eda875561fab70c979463ffb6a1d74c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f434c3ffe109528456c23d6cfe51ec0b10be606d7a26775fe2ff0a9b18f92f39", + "result" : "valid" + }, + { + "tcId" : 326, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433fe37949375debd9734f54b7036b7a978bc8fc4ae3fe927a521f940d9e35dd38f81a9160c05df04e34290db40c3e045b832373941ca85b433854e43caed323d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bd02b9dfc8ef760708950bd972f2dc244893b61b6b46c3b19be1b2da7b034ac5", + "result" : "valid" + }, + { + "tcId" : 327, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b9ba8445067d0e81bd32dd99e6b4ea3d442d063a8eb9873518ee3bb18c053706099964b6889105784d9d6d9d9aa79c76b6a3d3376315953afdcb5a7439e7c706", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "412269bfc15d8b1fd7f25de33b1515ea67f2194e73ba06c85ef99bb42722f95d", + "result" : "valid" + }, + { + "tcId" : 328, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000478b248634270a7a6640bd0c64595dc4e98adfe6bdb8112593a4173e36d4a9b4969a1f3d19b325898e36459c41eba1de99229b0ba2cf1337461c84391d9aea1fc", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0ad7556a621074a771bf129163d09a2e9d2e174f2b8a4b6973e89ea138c9a603", + "result" : "valid" + }, + { + "tcId" : 329, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c788884ac868593db241f5b3ea7013810d3ce28a02680a96ff357b261fad611bef353b0e82c1c68c471ff1ed5c4749e168e7af8591a5e6dab599b96620de0ede", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "76acc74dd60872ab29e1bcb99dd46365c7c7f792619c901c7ba5c68378b233f5", + "result" : "valid" + }, + { + "tcId" : 330, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041864e373ac60c23543fea9e1f237950a8169e07c817db69d500e5592d1df9d5a10da4651efccc46d37e7eae16c36ac86a9a86b88ad08751a8dcd15060019704b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "50e23b94fcc33d93dbcd71e955e195fe0bf6ac9b04b15f001e53b5dc7bad158e", + "result" : "valid" + }, + { + "tcId" : 331, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dd7308d2a6757f924dc979066e75ee6fa52b03393d2892f59788effa553b690d1fef00c1c22ba80b95d529782dbef55a63046179fb4ef00fdccf5b62ce55c136", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3324bf2fb3486b1104fffa35ef38975faffba1ebe42c54399206face505448c7", + "result" : "valid" + }, + { + "tcId" : 332, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004575d51be2bddf5bf1ab42431ba7e3b5f2947bc574df9f60a448b8db5ca28c92cd836f55c556440a7df125de6599b21ae68f15d5b9f422d6eec88ab2f65406bf9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "235fd3e7216c92f73860f0ac0121b4264ff89d80bc75d59dd455298597c5f2ec", + "result" : "valid" + }, + { + "tcId" : 333, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c7422a80aebdb518bd2daba691d39a25ea2fe49a35cdfb2a0f94bdfbadc6629ae55ac7c400afd2976b7c3b24f7126807a5a0afb931cfa5c6ada1f4ff984ea5a7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0bf758de27052319dac39b324a6ea55e928603a3ef9049ad147f8ca35f55b656", + "result" : "valid" + }, + { + "tcId" : 334, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ad4062216f84ffd66e326497bcbcab982283493392ec0f739cef8cd7eaf3453414c5a289a846e28bf2042ea5dc7b15e252f48d3cf980e7c4751cc35493a1c328", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "312eeaaee397224fc17dec7191ce69cef40e8fb373516c2b1edada0336c99c13", + "result" : "valid" + }, + { + "tcId" : 335, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ccacd1bf7c7f4ea9c7e59bd802804a9d335262716ac288c6eefd7a7135349a4f7b8612e2bdbd43b3fc4fa6941ac15a8f37e34fe7810a0c0d43c05afafb6480ef", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "aa1691858e6a1a06c6df57ce10a4c730974c06d1e0106d1a31b51b915cd6b60e", + "result" : "valid" + }, + { + "tcId" : 336, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049aa7f1f93474fa370c4df3805bd2839328895880dce197a06cf9052e6ab7a6938c9a208b335bfda6b01321f029a0d83c8bb96561208481f7af6c6cf1d2657843", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5786d6ea09ffb21a63adb020b117096484ef995e8c4a72afa479cba95c959920", + "result" : "valid" + }, + { + "tcId" : 337, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000483b7affcec11685d15614e2d53c1e73504e3d98344bbd5fc0ad86dc4c36704323a7f73a09533d1a1076aa9c4af22a6bab92f3f0d766798db7aa4183c037f86e6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ae0c7845b82995263c51e13e297412d17b650aa83dce4f55a069dbee671c16b8", + "result" : "valid" + }, + { + "tcId" : 338, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aeebdd971cf4e988fabd8070c75c64aab90a83a36735fecfb385605979c008ae8c39888f0daf74f98cebbb08f6b91a5193f684a56761b9f2b63d87d3f60491ed", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e5e764a38b73816f6e11e7cf298b2be54d11249c615f0a71498a0a821b5736bb", + "result" : "valid" + }, + { + "tcId" : 339, + "comment" : "point with coordinate x = 3", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6aa7e74a7a838efa9607f3587d4117f1914c57fa924b441c27fb7a7c31fbaac4", + "result" : "valid" + }, + { + "tcId" : 340, + "comment" : "point with coordinate x = 3", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e38eec4c1a4d81a5d994b0d7780305af651892cbf07f3a07628f4e2473a8ab754bda96622462880d3536d390132a85db6147f814c62efb580a6f529598b0dd1e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "391b624f28eb398156666dbec1d635f8ff1753eb86297973a1c2831b1091e2df", + "result" : "valid" + }, + { + "tcId" : 341, + "comment" : "point with coordinate x = 3", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000410f02d496e9a8758c831389892a45ed009282ea1eb201ab8caf09e6f2de9fa4acc126becc204c41a94aff4f2ead7552ec23fc68f0005147625a95622b521090d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e3f39d071b743c8041454d1dacba93dc9f3f12a5ae1bfbebaa59fc4cefee6b82", + "result" : "valid" + }, + { + "tcId" : 342, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044c859aff342c56a9508b859ab1509edcabf66e044e2026cc293474389b3d58c16bc06cf99dd6d8249c5d24386a55a97214ea0cda270ad9470986c3a3d023cb07", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "09d0d1b92af1e7111d223bf5efcdfa6df2622ab3cf161af0ebbf06ad00c09b6e", + "result" : "valid" + }, + { + "tcId" : 343, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1eb4f7c680a247a14f3d67f85cdb1c4c6f13d44821fc456c9247a606622afec4952cf05ff06f06d7030e88904737096cbf8dd90e478a3b5dfed2ee487a0835c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a738727e0f5b20448009d1029ca727f2380d2c6e152a6e2da8ea50531ce39499", + "result" : "valid" + }, + { + "tcId" : 344, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043bf79d6c1a20d85115e973079707f5131eed2f83be5683c34d0fb3eee1ae40dfd2ea4f1b735cf62341835a5721c25daa0dc1a3886ab75ef653f472d8f3aa1e97", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a314e4ee9e303d970b4e9f0cdc262657d5c5192f055466b9d09d9c888d6b7256", + "result" : "valid" + }, + { + "tcId" : 345, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b1f808286a42eeee85d585e54dc28aba2aebfb956805f5c01127bcdf435154cb5b178fda5896d9e7508661fee7ee55fa9623610b3d9f4a59156b76d8877b4ef1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8f4e1bf8e5182a1fbcdeac924df1ba2f937162d48a206783c48132cb582c07db", + "result" : "valid" + }, + { + "tcId" : 346, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a21e80d09e11acbccbc909de6c9f1159addbb5dd477211b90a370f8c7548e60d1d7aacb6e455bcdc230331d79ad9464a77b702c858400900cb4488cb6c28bd61", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "16682c862cf53755b3c28adf7de052d5cf0e81e5d8acb346702a392bc6b2b1d5", + "result" : "valid" + }, + { + "tcId" : 347, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045055a8c45e81385f4144c7b6fb32119395a94dbd07665ed7bc1cce1e62dc47c8b6d50a39a55d3b8e996624fb6ec2f2960c7c2bc0bc94b2a63d65096fd99ca41a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cc33e840b5354bf6e088047e76dc168f15c0c1aa946731600f52d6f1c9299b27", + "result" : "valid" + }, + { + "tcId" : 348, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004af522fc0a61440173945b914d6404b1940b547a6f768550280fe28bd331c9c661d282429f2911298f9c5b82f87c7f5044706748c19035689b216d64474bf5ad0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d7b4f5e2dd1ebecfc92318d92085271be482fe65a03e83b2e358a397a597449b", + "result" : "valid" + }, + { + "tcId" : 349, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ec1a88652de714d21fddb54db4a3423521aead5828b843bdde9a42cf4a8bf124a69568c664e2d9317ac732c98c435548dcec0eeb8ab31027ee5f1693ccd97c68", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1d88ed8e4579a4c62fed95eafe1528f8d5056041fc41f3ef063605ddc980ee09", + "result" : "valid" + }, + { + "tcId" : 350, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000448e4c9cc88a601eb639f81ffa679540bf1d7bcbe876a955e73bfade055384160bae130243ef5fd328f65278e00cad6001327ab42fdf3b9654aad6f260542b02b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a6698578650dadb452d677c3983e6b809152d7d2d8fba349cec686e72e6f8693", + "result" : "valid" + }, + { + "tcId" : 351, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e861379f1c1b07540155bbfef4a69a84be81b1441d43e7850c7ac1005a804238bb33c7981d383a06d1b795552a7b31f49145fba937876fdc9f0d138aa5b3f322", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8e42c38902b25fa138b95f4f280b684c09e1212c4f06a2bc2c2b2b8790112034", + "result" : "valid" + }, + { + "tcId" : 352, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b4489cd499168bd48cd2c31167edad246c63859bf8b48398617a7a0556341e3c0b0f66f665038baa29db8c296d4f2ae07b9ab9193bfc00981d7df0599ce0648d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a19f1165d31c1695359929deebcd24846ccb9a3c2a38c10bdc7c855bf8a32df7", + "result" : "valid" + }, + { + "tcId" : 353, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004884e74885ea450f5aab0cc8f06c006630e8b183a06bda509322fcd97ba5d2d2b00e1373d533bd5920427d106b7f33eeb53d21b5cf46ca0151e91859e811a39cb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0a87935c036de666b7619f14ec58f9f78698cc23a667616f84c177f34661ebe2", + "result" : "valid" + }, + { + "tcId" : 354, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c50224a8cf3a19da6133e746d00217285df85589ed334b54d95b005b8f033f7df7bc6a5ddc59d033f0c66bed57149a160f25723117a2fcd413aff8c9ada43bf9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "90accd1c3af1cd782ea1e864a307aaef6a01fd3a6305a0adae37e76844b9ce10", + "result" : "valid" + }, + { + "tcId" : 355, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c66a917fc435c9f41c47428e718a3017b3c5c992b4d94a663602f73fd825d043a03cb9f58174cffb359e2f541cfb5e551c50fd811b82362eadb216a4cfd0f8c3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e164d88fcbd1ccdd654de0415bfbd2a171590713015f4a1755504e62f7a03870", + "result" : "valid" + }, + { + "tcId" : 356, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f55a451e6e0d8f7600c7bf7c05741c5e5985b8ffe4eab62d4ffc04aedb725a66e942cf486efcf3b85488cf3cd4fb0248b820703b938ce77a074a2f9286af03bf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d4b6d4251ac1f8a0b0c75bbac3517a13ea0c857b5499b03d153be663a8715480", + "result" : "valid" + }, + { + "tcId" : 357, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a96aa25bee8c8cb6f6aaf40be98ca047da245e8d4cae28fc892a0369b299cba3ef5f54bb59f4ad58a84332a00d89a1cf3d56c4e6ec9c3a467a4a2a04ad3bce97", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f5270d0c4119f1ef467a37501688b4bf4a516e5f58a0f5a40f23ae70ee813c26", + "result" : "valid" + }, + { + "tcId" : 358, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000449f572fa8cdf6750adabc3ab0e46bf23dd7ad7114bf319f35afa6a2ccbe2e7d343c44f018f8efc9f52691b274a8c89283d13ce93d1b58aea11d62c88599c309c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1763eb5bd3677de88e98aad84038838422d6e55605a14761788cf305672eb670", + "result" : "valid" + }, + { + "tcId" : 359, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b36f6b02bf1d213d9abcfc98c25fc81ab3b98cb13d678da871310aa093ab7b58a50b134818321a48ffc1ef9f8624e371ddf078d8983fda6c4eb27dfb255174e9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "98c95ef9fded241da09392573144daf44b0332518f458167e09d672011ea4618", + "result" : "valid" + }, + { + "tcId" : 360, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000474f57ff3da8d60ec0b382e6866be4502f695688384b405e2179aab61066196d7d24064185d68de95bd72b219c0c0a93879324f299fb19214b33a3ed2f1bf4823", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0fe8fc6abe853b1ea6aa4f4b4490bcd94ffd3532c1d7cce36d059ac8f29cd67", + "result" : "valid" + }, + { + "tcId" : 361, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004924fe3439d35427e2ad9b1f6e67877ed3441d74bdd0eb9f82ae360434bc20624537e3400007cd2d140f2caa0f7b61c7118abb9ac5c766ecab3f8f72ea5d96cdf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4fdc7cc04b2459f73c856023e892699b9018baca1b8e3b040ec74324607c97c5", + "result" : "valid" + }, + { + "tcId" : 362, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fb0e48a3815a2b80e9e725036a239757e9c5987850a941c5f5d2b89b776aac683adb5481fcd85f0013feb20505ebbaff27edf8474a7cf4d985ec567365ecbc1d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "561138979956fe6a1aeae06277456c7e5e7e7d643910e247fb248dd7435691a0", + "result" : "valid" + }, + { + "tcId" : 363, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e669915ee160694e8559d7965f7cff945c1cb076f194ec9894b1a38b10726fb0389675e3155b069b3862da3d1112179a04accbe7dbb70b3cc48bedb7591d2eac", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "06c06abb603bff68f356ce496c17fcd0662fa040eb0cd45a98112e6c1eea11db", + "result" : "valid" + }, + { + "tcId" : 364, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b760dfff4c5c200aec18b930b18df34297bb421b96017ef902139fe6b12349f6ccb8cf83d2837c7520300f197b491c0368470ee86f74ca0381682bb6ad80344f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "319297f77a75381b65d73107e826eea0e69d85985db4568fea21d12dda696921", + "result" : "valid" + }, + { + "tcId" : 365, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b0e4de914fe71b61636e61391528efac8b6c11edcd41c9766af8693dbb6e41f2517293725552f22dd6e1db7c2c243f80c10713f6aa48fc5e395bd9ec51f1e9c5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c3ef6eb91aad69456ede5174b0e5e3d6863c024aef3185d2258946362903e576", + "result" : "valid" + }, + { + "tcId" : 366, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048eb6ee2ee9e061acb9312ad015b1954ea47ca304a2cebb77f3bf6c78678c1149d93fc6e80561f3110fd0e95fdc0ce8da2c3f32f7f581f9b666d74900b3760b9f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a18b1fba4d496419ede70cc23ceed674526f34299e5b09c0ee2dd1669693fef9", + "result" : "valid" + }, + { + "tcId" : 367, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000490121021546a96e7879d53e7b85c21f4047df49b9ad85020104f216d010f520d1bba6e765742395b4c894fd0eaaf87275d1c77494c01cce882de2805d1922c0b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9fc7fff3bb4d6e5a4d52eb0e3c513a3c9fa56014c030449546cda744aa126f6e", + "result" : "valid" + }, + { + "tcId" : 368, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000464c1712e3e9ef440c7ea8faf0540d2e6a05adccbd53a7fb24ff16a9502a818f747cfafd2209430eb7794f5da91d6c5e2db505ba287bc6ef397bf7f30c747536a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "61cb2fb99b695ecbaf91a95e6e0c7e24633bc7613ebf518c6f1c8161dc75ea5f", + "result" : "valid" + }, + { + "tcId" : 369, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "af306c993dee0dcfc441ebe53360b569e21f186052db8197f4a124fa77b98148", + "result" : "valid" + }, + { + "tcId" : 370, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000424800deac3fe4c765b6dec80ea299d771ada4f30e4e156b3acb720dba37394715fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "aa7fc9fe60445eac2451ec24c1a44909842fa14025f2a1d3dd7f31019f962be5", + "result" : "valid" + }, + { + "tcId" : 371, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048f33652f5bda2c32953ebf2d2eca95e05b17c8ab7d99601bee445df844d46a369cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "082a43a8417782a795c8d4c70f43edcabbc245a8820ac01be90c1acf0343ba91", + "result" : "valid" + }, + { + "tcId" : 372, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004146d3b65add9f54ccca28533c88e2cbc63f7443e1658783ab41f8ef97c2a10b50000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "70810b4780a63c860427d3a0269f6c9d3c2ea33494c50e58a20b9480034bc7a0", + "result" : "valid" + }, + { + "tcId" : 373, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b0344418a4504c07e7921ed9f00714b5d390e5cb5e793bb1465f73174f6c26fe5fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a7d34ee25fbb354f8638d31850dab41e4b086886f7ed3f2d6e035bceb8cab8a0", + "result" : "valid" + }, + { + "tcId" : 374, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048a98c1bc6be75c5796be4b29dd885c3485e75e37b4ccac9b37251e67175ff0d69cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3f09cbc12ed1701f59dd5aa83daef5e6676adf7fd235c53f69aeb5d5b67799e0", + "result" : "valid" + }, + { + "tcId" : 375, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff5070000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e04e881f416bb5aa3796407aa5ffddf8e1b2446b185f700f6953468384faaf76", + "result" : "valid" + }, + { + "tcId" : 376, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042b4badfc97b16781bcfff4a525cf4dd31194cb03bca56d9b0ce96c0c0d2040c05fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "adace71f40006c04557540c2ed8102d830c7f638e2201efeb47d732da79f13d9", + "result" : "valid" + }, + { + "tcId" : 377, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e633d914383e7775d402f5a8f3ad0deb1f00d91ccd99f348da96839ea3cb9d529cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b8cbf0968fb70d391059d090b30d1c4edcd2dad7abbf7aa4ad452f5a4644a7be", + "result" : "valid" + }, + { + "tcId" : 378, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1c1b509c9ddb76221a066a22a3c333fee5e1d2d1a4babde4a1d33ec247a7ea30162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "07257245da4bc26696e245531c7a97c2b529f1ca2d8c051626520e6b83d7faf2", + "result" : "valid" + }, + { + "tcId" : 379, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004755d8845e7b4fd270353f6999e97242224015527bf3f94cc2c693d1b6ba12298604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d6aa401b9ce17ecf7dd7b0861dfeb36bb1749d12533991e66c0d942281ae13ab", + "result" : "valid" + }, + { + "tcId" : 380, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c6f9fc8644ba5c9ea9beb12ce2cb911c5487e8b1be91d5a168318f4ae44d66807bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f43bfe4eccc24ebf6e36c5bcaca47b770c17bcb59ea788b15c74ae6c9dd055a1", + "result" : "valid" + }, + { + "tcId" : 381, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d3179fce5781d0c49ce8480a811f6f08e3f123d9f6010fbf619b5d868a8ea833ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "009bc3abb3cf0aca214f0e8db5088d520b3d4aadb1d44c4a2be7f031461c9420", + "result" : "valid" + }, + { + "tcId" : 382, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049e098095463c91ac7107a920ccb276d45e1f7240ef2b93b957ee09393d32e001503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8bcb07a3d0fa82af60c88a8d67810ebca0ea27548384e96d3483310212219312", + "result" : "valid" + }, + { + "tcId" : 383, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf3034a9935182da362570315011544ac2ce8a9c22777c2fc767ac9c5c0daeebcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a09ddc7cfe023acd9571ef0754010289c804678c043f900f2691dd801b942ed4", + "result" : "valid" + }, + { + "tcId" : 384, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004709c7179c2bb27ce3985ba42feb870f069dacead9294c80557be882fb57790481e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "da98054d51ac9615e9d4f5ceda1f1bad40302ac11603431efec13ab50e32fcf2", + "result" : "valid" + }, + { + "tcId" : 385, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004264c00a2d92514a6dbe655de3c71a5740cec4fcb251aa48ca6745dbea6f5f7cfc1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d60795d8f310b155726534b8be3d0b8a7bc2ced468c6e64c8b9ae087b33ee00b", + "result" : "valid" + }, + { + "tcId" : 386, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a12124606bcbbb33cecec7fc8d78b3897192ca851560c539e47dd276c63bd3c2f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "675fef8f5680bf76220e91362613944099046b0ba07e5824e93f3e3cc2cc2758", + "result" : "valid" + }, + { + "tcId" : 387, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004244b7afe7f31289f9d6aaeb7f70d29a7b49a228c7bb202764aba94daaaa3332270c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "76b439f8ea7b42f11cd59e6d91b2d2a72577c185386b6af6639be8e3864a7f27", + "result" : "valid" + }, + { + "tcId" : 388, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042ac29db2ebc4fa9473b42bd335a60226579cc186b2c676a3b01bc60e589616165aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "56e63fa788121d5efa0ce3caf4605af18d48c631496cdfa862c43ecf5e5fc127", + "result" : "valid" + }, + { + "tcId" : 389, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e62aee5205a8063e3ae401d53e9343001e55eb5f4e4d6b70e2b84159cf3157e64ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cff3b5e19ed67e5111dd76e310a1f11d7f99a93fbe9cc5c6f3384086cacd1142", + "result" : "valid" + }, + { + "tcId" : 390, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000431dce6de741f10267f2e8f3d572a4f49be5fe52ff7bff3c3b4646f38076c06752702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e29483884a74fb84f4601654885a0f574691394f064ea6937a846175ef081fc5", + "result" : "valid" + }, + { + "tcId" : 391, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046518cd66b1d841e689d5dc6674c7cc7d964574d1490fff7906bd373494791599104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9c6a4bcb2fc086aca8726d850fa79920214af4c151acea0fcf12a769ad1f3574", + "result" : "valid" + }, + { + "tcId" : 392, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004952a88ce31ad4cb086978e6c5621c3d8023b2c11418d6fd0dcef8de72123efc15d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "34b7abc3f3e36e37e2d5728a870a293a16403146ca67ff91cbabeee2bb2e038b", + "result" : "valid" + }, + { + "tcId" : 393, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042a43f33573b619719099cf54f6cccb28d16df3992239fadf79c7acb9c64f7af0f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9bd1284f1bcb1934d483834cae41a77db28cd9553869384755b6983f4f3848a0", + "result" : "valid" + }, + { + "tcId" : 394, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041b1b0c75408785e84727b0e55e4ba20d0f2599c4ed08482dc1f3b5df545691380162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "167e3db6a912ac6117644525911fc8872ed33b8e0bbd50073dd3c17a744e61e0", + "result" : "valid" + }, + { + "tcId" : 395, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044dd1283bccd36cc3402f3a81e2e9b0d6a2b2b1debbbd44ffc1f179bd49cf0a7e604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7c3020e279cb5af14184b4653cc87c1ddd7f49cd31cd371ae813681dd6617d0e", + "result" : "valid" + }, + { + "tcId" : 396, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a499dbf732e438be0eb084b9e6ad879dd7a2904bbb004b40027969a171f2d4267bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "acfdff566b8b55318869fa646f789f8036d40b90f0fc520ae2a5a27544f962c0", + "result" : "valid" + }, + { + "tcId" : 397, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004adcf0ffba9cb6ef0c8031c4291a434b18d78f42e45e62ba01fbe91f9273f0ad1ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5c6b01cff4e6ce81a630238b5db3662e77fb88bffdde61443a7d8554ba001ef2", + "result" : "valid" + }, + { + "tcId" : 398, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000421712725d9806acf54d3a6c82bf93c0fe249268ca9f42eceac19e93a5eab8056503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e7281d12b74b06eecb273ec3e0d8fe663e9ec1d5a50c2b6c68ec8b3693f23c4c", + "result" : "valid" + }, + { + "tcId" : 399, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041e02176824bd31eabdce03a9403c7d3c2ac631f9b0e88d9a924701c1b2f29b85cf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "80643ed8b9052a2e746a26d9178fe2ccff35edbb81f60cd78004fb8d5f143aae", + "result" : "valid" + }, + { + "tcId" : 400, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000463e7a1af36d6b540a49276aac3fec9cb45ed6bab167c06b0419a77b91399f6181e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "75873ac544ad69d3ddc5c9cffe384d275e9da2949d6982da4b990f8bf2b76474", + "result" : "valid" + }, + { + "tcId" : 401, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041e265ab5b7f7199470e532653d2a7b9a8b728970b838137c9692ed0692897b2ac1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "355c9faca29cf7cc968853ee29ffe62d1127fcc1dc57e9ddaf0e0f447146064e", + "result" : "valid" + }, + { + "tcId" : 402, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000454d2a4394c109fcbd3cb9886fec3add51ba4d2e44e1d5676e4b98f0c13655fc5f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "fc175a5ef18595b69e45be2cda8ae00d9c8bdbefbcf7f692f91cefdc560e4722", + "result" : "valid" + }, + { + "tcId" : 403, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000493f1459207fb09c6f0a88c398ac80d1052a4cd33e7eef5687da99ab97c6024b770c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "46559146a93aae904dbcaaaa07e6cd1bb450f1b37c83929a994b45792333d5f6", + "result" : "valid" + }, + { + "tcId" : 404, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041fa049a1892b679857c6dff08af19db70cbc99b6f2d7bc51a341fe79d1647f4a5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c64b07119054a37961c0a177158256081b38b0087b307e0cad7e30d790ceb0ce", + "result" : "valid" + }, + { + "tcId" : 405, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000484e0b192d60abf531e828e887d366d869e1033a16e9c7f1167458c8134c10fba4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bea8cfc0bee8571ccf0c525654ef26d1fc782bb22deccf67ea4ea0803dc15daf", + "result" : "valid" + }, + { + "tcId" : 406, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042f9707c67118724111efbbbbf06b623ab2ffd9259ddc354fcaaf81ba01f6fa7b2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "60451da4adfe5bb393109069efdc84415ec8a2c429955cbf22a4340f8fc48936", + "result" : "valid" + }, + { + "tcId" : 407, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ac1fbbe42293a9f9ae104ee2da0b0a9b3464d5d8b1e854df19d3c4456af8f9a6104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d68e746f3d43feac5fd4898de943dc38205af7e2631ed732079bbfc8ab52511c", + "result" : "valid" + }, + { + "tcId" : 408, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bae10cf93ff7b72d6ed98519602e9f03aa40303fa0674fb3ddee7d2db1c92bb25d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "28daeaadc609386d770dff4c7120b2a87cab3e21fdb8a6e4dc1240a51d12e55c", + "result" : "valid" + }, + { + "tcId" : 409, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004edb4288cf5567673d50a1cd9e6bea45317823f30383f60d9bc3b9ee42ac29871f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bb4110b734c8ef8a08bb6011acb35cbda9ae8e2ef6c4d0862576a68792667bb9", + "result" : "valid" + }, + { + "tcId" : 410, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000413233e80f59ac2b59737e87877782ab3027c490df8ac0bf3f3ef1633872eec540162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e25c50037ca1913851b9758752659fb61c02d2a7c6b6aae29bda301907d99f5d", + "result" : "valid" + }, + { + "tcId" : 411, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043cd14f7e4b779615bc7ccee47e7f2b07394bf8f98503263411a549264a8fcf19604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ad259f01e953263f40a39b14a538d076710c19207af936feabdf03bda7f067a5", + "result" : "valid" + }, + { + "tcId" : 412, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004946c278288616aa34790ca193686e745d3d58702866ddf1e95550711a9bfbdb87bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5ec6025ac7b25c0f095f3fdee3e2e508bd1437b9705c2543c0e5af1c1d363ffd", + "result" : "valid" + }, + { + "tcId" : 413, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047f195035feb2c04a9b149bb2ed3c5c458e95e7f7c418c4a07ea6107e4e32455addf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a2f93a84574a26b43880cde6ed440c7f7cc72c92504d5271999a8a78ffe3491d", + "result" : "valid" + }, + { + "tcId" : 414, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000440855844e04303843a24b01707544d1bbf97673266e03d77fbf80d8b64219bd8503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8d0cdb4977ba7661d41036aeb7a5f2dd207716d5d76eeb26629043c559ec2900", + "result" : "valid" + }, + { + "tcId" : 415, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000422cdb3ee47f14b3b0c0c8c256fb22e79126b436a2c9ff635a65151a0f0ffb1bfcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "defde4aa48f89b03f623ea1f946f1aa938c5aab879ca6319596926f085578edc", + "result" : "valid" + }, + { + "tcId" : 416, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042b7becd7066e22f121e7cf123d48c5445037c5a756ef314a66a7001636ee75cf1e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "afe0bfed69a600163865406127a8972b613232aa4c933a06b5a5b5bcff1596f8", + "result" : "valid" + }, + { + "tcId" : 417, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bb8da4a76ee3d1c4b33477bc8663def167a126c422ad47f6c2f8b539c6808936c1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f49bca7a6a5256ddf712775917c30e4873153469bae12fd5c5571031db7b1205", + "result" : "valid" + }, + { + "tcId" : 418, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040a0c37664823a5005d659f7c73c39ea172c862969c81e44f36c89e7c265ec8a8f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9c88b611b7f9aad33fabb09cff618bb1ca6fb904a289b1481da3d1e4e72589e4", + "result" : "valid" + }, + { + "tcId" : 419, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000447c33f6f78d3cd9971ecc50e7e2ac947f8c1103f9c5f0821379bd06ad8fca45670c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "42f634c06c4a0e7e956db6e86666603d26374cc74b11026f0318d1a25681a712", + "result" : "valid" + }, + { + "tcId" : 420, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b59d18ab8b0f9dd33484f43c3f6860229ba6a4c25a61cd0aaca23b76d60566cf5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e2ceb946e7993f27a4327abdf61d4f06577e89c63b62a24aefbd905710d18669", + "result" : "valid" + }, + { + "tcId" : 421, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000494f4601b244d3a6ea6996fa244364f794399e0ff4316157db6023222fc0d90be4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "71637a5da2412a921f1636c69a6ee81083ee2b0e13766ad122791ef6f771896d", + "result" : "valid" + }, + { + "tcId" : 422, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049e8c115b1ac87d986ee1b506b86a4e7b8ea041aa6a63d6ec80ec0f0cf69cfb3f2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bd265ed3078ca8c7788f594187c96c675aa623ecd01bfcad62d76a7881334f63", + "result" : "valid" + }, + { + "tcId" : 423, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004eec776b52b94141fc819d4b6b12d28e73555b5560507aba7df6f0484008de91f104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8d073fc592fb7aa6f7b908ed07148aa7be5a135c4b343ebe295198cba78e71ce", + "result" : "valid" + }, + { + "tcId" : 424, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aff46a388e5afc220a8eec7a49af9d245384a3af1e0b407b4521f4e92d12dceb5d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a26d698e4613595aa61c8e2907d5241d6d14909737df59895841d07727bf1348", + "result" : "valid" + }, + { + "tcId" : 425, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e807e43d96f3701a9a5c13d122749084170fcd36a586a446c9fcb4600eede4fdf4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a8edc6f9af6bf74122c11ca1a50afbc4a3c4987bd0d1f73284d2c1371e613405", + "result" : "valid" + }, + { + "tcId" : 426, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004798868a56916d341e7d6f96359ae3658836e221459f4f7b7b63694de18a5e9247713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "17963de078996eb8503c7cc3e1a2d5147d7f0bfb251a020b4392033063587c8d", + "result" : "valid" + }, + { + "tcId" : 427, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff419909d8a8ce0a9416051f4e256208c1dc035581a53312d566137e22104e9877421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "062799a19545d31b3ed72253bcde59762aa6104a88ac5e2fb68926b0f7146698", + "result" : "valid" + }, + { + "tcId" : 428, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048b48119d7089d3b95cd2eaf8c85584fa8f5e56c4c4ccee7037d74cdbf88e571714c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9f42dd8fce13f8103b3b2bc15e61242e6820fe1325a20ef460fe64d9eb12b231", + "result" : "valid" + }, + { + "tcId" : 429, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e2888119379b5b2151bd788505def1d6bd786329431caf39705d9cbf96a42ea43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d1b204e52d1fac6d504132c76ca233c87e377dcc79c893c970ddbb9f87b27fa0", + "result" : "valid" + }, + { + "tcId" : 430, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046dcc3971bd20913d59a91f20d912f56d07e7f014206bef4a653ddfe5d12842c39b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c8d6bd28c1e65ae7c7a5debe67a7dfaf92b429ede368efc9da7d578a539b7054", + "result" : "valid" + }, + { + "tcId" : 431, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047ebea45854569a1f7ea6b95b82d6befefbf6296ebc87c810b6cba93c0c1220b23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0d1f905cc74720bde67ae84f582728588c75444c273dae4106fa20d1d6946430", + "result" : "valid" + }, + { + "tcId" : 432, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ceab5937900d34fa88378d371f4acaa7c6a2028b6143213413f16ba2dc7147877713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3f014e309192588fa83e47d4ac9685d2041204e2eaf633a1312812e51ae74cbd", + "result" : "valid" + }, + { + "tcId" : 433, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a4ffea5e25f75e4f689c81084a35c1220e8e6b914c482f4a2e8f93cffca6964777421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "68b404d556c82004c6c4bba4518ec00b1d4f1161cafe6c89aeb8494a9ba09db5", + "result" : "valid" + }, + { + "tcId" : 434, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004de8809ea0ecce1d24a0431429510383a6f6e5a1c51cea32d830c6c353042603e14c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c331ade7a457df7f12a2f5c43d7ea9486c1563b81cd8a0f23f923c1a9fa612e3", + "result" : "valid" + }, + { + "tcId" : 435, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004566209f174d6bf79720b70edb27e51350beeb2b0bcd083bbae7214f71cf824d43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "17b5c7a311eea9d2ab7571f8b9f848d4705997cf3eaf9bdcbe0e34a670f81f45", + "result" : "valid" + }, + { + "tcId" : 436, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cc3181c0127137536ceec94fd45996657df72e0f97c44b9dad14763ce506e9dc9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2f0e4eccbc4518ace558e06604f9bff4787f5b019437b52195ecb6b82191a6ae", + "result" : "valid" + }, + { + "tcId" : 437, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d7052a1eeafc0e78d79e7f26003aa0a409287cf476007df28d281b142be1a0e23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7494d864cb6ea9c5d982d40a5f103700d02dc982637753cfc7d8afe1beafff70", + "result" : "valid" + }, + { + "tcId" : 438, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b7cc3e2306dbf7c38ff179658706feffb5efdb6044c7e71435d7ff7d0ae8c7b37713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a96873eef5d438b807853b6771c6a5197e6eef21efefca538b45e9e981c032e5", + "result" : "valid" + }, + { + "tcId" : 439, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045bbe7c98015fd3a6034d79d867a4dcd52f95911932129da2fc0a58afe149137f77421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9124618913f20cdffa642207f192e67eb80ade53ac5535469abe90036d4af7e2", + "result" : "valid" + }, + { + "tcId" : 440, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004962fe47880a94a745928e3c4a29a42cb01334f1ee9646e62451c46ecd72f410914c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9d8b74888d942870b221de7a642032892bc99e34bd8550195f6f5f097547334a", + "result" : "valid" + }, + { + "tcId" : 441, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c71574f5538de5653c37168d47a2bcf43698ea260012cd0ae1304e474c63a4e63bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "16983377c0f1a9c004495b3fd9658363116eea644787d059d1140fb907555d4a", + "result" : "valid" + }, + { + "tcId" : 442, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c60244ce306e376f3968178f5293742d7a20e1dc47cfc517edada9db49d0cbbf9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "081af40a81d48c6b530140db935e605bf4cc7b10885f5b148f95f1bc8ad2e52d", + "result" : "valid" + }, + { + "tcId" : 443, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aa3c3188c0ad5767a9bac77e7ceea05cfae1599ccd77b9fcbc0c3badc80c36ca3f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7e4b973e6d4a357c400243a648c8a0a6a35cf231754afdef312d2f4b6abb988f", + "result" : "valid" + }, + { + "tcId" : 444, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042cce8ddfe4827dc030ddf38f998b3f2ed5e0621d0b3805666daf48c8c31e75e5198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0f0235da2a06c8d408c27151f3f15342ed8c1945aaf84ed14993786d6ac5f570", + "result" : "valid" + }, + { + "tcId" : 445, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000414bfc3e5a46b69881a9a346d95894418614ed91476a1ddce48676b7cbab9ba02f334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5622c2fbe8af5ad6cef72a01be186e554847576106f8979772fa56114d1160ab", + "result" : "valid" + }, + { + "tcId" : 446, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd442fa5a2a8d72e13e44fd2222c85a006f03375e0211b272f555052b03db750be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bb95e0d0fbaad86c5bd87b95946c77ff1d65322a175ccf16419102c0a17f5a72", + "result" : "valid" + }, + { + "tcId" : 447, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040d7a3ff49bda6a587ed07691450425aa02d253ba573a16ad86c61af412dd3c770b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4510683c7bfa251f0cb56bba7e0ab74d90f5e2ca01e91e7ca99312ccff2d90b6", + "result" : "valid" + }, + { + "tcId" : 448, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bdea5d2a3adde7df2e839ff63f62534b3f27cb191bb54dfa1d39cbff713ba9ed307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "025485142ca1ced752289f772130fc10c75a4508c46bffdef9290ad3e7baf9ca", + "result" : "valid" + }, + { + "tcId" : 449, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d4c063e3c036f47c92f6f5470a26a835e1a24505b14d1b29279062a16cf6f489198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9067932150724965aa479c1ef1be55544bed9fa94500a3b67887ed91ae3b81e5", + "result" : "valid" + }, + { + "tcId" : 450, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043cb9f07997756859e9b9a85b681fa50ee20357f535c1b311c4637d16b76b9ebff334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f8084a89adccdc3aef89e5091a0f07d6160a66cb9575241100c1d39bf0549ae2", + "result" : "valid" + }, + { + "tcId" : 451, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004793412ff636c08a2d0f6d60cc608e9a9098349a2501f91c95f692010bc1238b2be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4462558c89902117051cb2c599ad66f00887b54cae3da9c04d317a5b2afb463b", + "result" : "valid" + }, + { + "tcId" : 452, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd1eb0849e2e6a13d54b76518f11ba8775c2d7634d85152534bc7c3af4161efa0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "30b4741a64f87d28ec0029bd196b5a74555f2c9a976a46d628572474466a631d", + "result" : "valid" + }, + { + "tcId" : 453, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004624b3b4ba993a8b938125689f6cf757392ee390d14a90fea6db944b5a8deb8d0307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3afc04ac92117e50b0913b09dbbb4e6c780c051500201fad512b79080bff39e2", + "result" : "valid" + }, + { + "tcId" : 454, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fe710e3c5b468dc33c2b17295c4e189b487d58dd437adf706ac05493cfea8df0198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "609637048586edc64cf5f28f1a505768c686471110070d783de499ffe6fe84da", + "result" : "valid" + }, + { + "tcId" : 455, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ae864ba0c41f2e1dfbac2337025716d8bcadcef6539c6f1ff335176b8ddaa36ef334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b1d4f27a6983c8ee417ef0f527d889d4a1ae41d3639244578c43d650c299fcd1", + "result" : "valid" + }, + { + "tcId" : 456, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c987bd5af9eb202f1b24da2117ca90b6ef8c82e7cfbf530f71418f9a93b0085cbe345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0007c9a27ac5067c9f0ad1a4d1e62110da1318893a658729713d82e333855b82", + "result" : "valid" + }, + { + "tcId" : 457, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000435670f86c5f72b93abe4131d2bea1fce876ad4e25b40d42d447d68cff90ca0be0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8a3b23a91f0d5db8074a6a886889ee3e19aaf09b66ac9aad2e15c8bdba68085c", + "result" : "valid" + }, + { + "tcId" : 458, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dfca678a1b8e6f67996a097fc9ce37412de9fbd9cfa1a21b750cef48e5e595a1307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c2af763f414cb2d7fd46257f0313b582c099b5e23b73e073b5ab7c230c45c883", + "result" : "valid" + }, + { + "tcId" : 459, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "03", + "shared" : "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", + "result" : "valid" + }, + { + "tcId" : 460, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "shared" : "5841acd3cff2d62861bbe11084738006d68ccf35acae615ee9524726e93d0da5", + "result" : "valid" + }, + { + "tcId" : 461, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "0100000000000000000000000000000000000000000000000000000000000000", + "shared" : "4348e4cba371ead03982018abc9aacecaebfd636dda82e609fd298947f907de8", + "result" : "valid" + }, + { + "tcId" : 462, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "shared" : "e56221c2b0dc33b98b90dfd3239a2c0cb1e4ad0399a3aaef3f9d47fb103daef0", + "result" : "valid" + }, + { + "tcId" : 463, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "008000000000000000000000000000000000000000000000000000000000000000", + "shared" : "5b34a29b1c4ddcb2101162d34bed9f0702361fe5af505df315eff7befd0e4719", + "result" : "valid" + }, + { + "tcId" : 464, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03abfd25e8cd0364141", + "shared" : "cece521b8b5a32bbee38936ba7d645824f238e561701a386fb888e010db54b2f", + "result" : "valid" + }, + { + "tcId" : 465, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfc25e8cd0364141", + "shared" : "829521b79d71f5011e079756b851a0d5c83557866189a6258c1e78a1700c6904", + "result" : "valid" + }, + { + "tcId" : 466, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfca5e8cd0364141", + "shared" : "8c5934793505a6a1f84d41283341680c4923f1f4d562989a11cc626fea5eda5a", + "result" : "valid" + }, + { + "tcId" : 467, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8bd0364141", + "shared" : "356caee7e7eee031a15e54c3a5c4e72f9c74bb287ce601619ef85eb96c289452", + "result" : "valid" + }, + { + "tcId" : 468, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c3", + "shared" : "09c7337df6c2b35edf3a21382511cc5add1a71a84cbf8d3396a5be548d92fa67", + "result" : "valid" + }, + { + "tcId" : 469, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364103", + "shared" : "d16caedd25793666f9e26f5331382106f54095b3d20d40c745b68ca76c0e6983", + "result" : "valid" + }, + { + "tcId" : 470, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364123", + "shared" : "b8ae1e21d8b34ce4caffed7167a26868ec80a7d4a6a98b639d4d05cd226504de", + "result" : "valid" + }, + { + "tcId" : 471, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133", + "shared" : "02776315fe147a36a4b0987492b6503acdea60f926450e5eddb9f88fc82178d3", + "result" : "valid" + }, + { + "tcId" : 472, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b", + "shared" : "3988c9c7050a28794934e5bd67629b556d97a4858d22812835f4a37dca351943", + "result" : "valid" + }, + { + "tcId" : 473, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "shared" : "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", + "result" : "valid" + }, + { + "tcId" : 474, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f", + "shared" : "4b52257d8b3ba387797fdf7a752f195ddc4f7d76263de61d0d52a5ec14a36cbf", + "result" : "valid" + }, + { + "tcId" : 475, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 476, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 477, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 478, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 479, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 480, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 481, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 482, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 483, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 484, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 485, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 486, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 487, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 488, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 489, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 490, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 491, + "comment" : "", + "flags" : [ + "InvalidEncoding" + ], + "public" : "3015301006072a8648ce3d020106052b8104000a030100", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 492, + "comment" : "public key has invalid point of order 2 on secp256r1. The point of the public key is a valid on secp256k1.", + "flags" : [ + "WrongCurve" + ], + "public" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004ffffffff00000001000000000000000000000000ffffffffffffffffffffffff32d98e0d77dd0e543770ec994c0ae837e7bb36eb1d910b58a14a2a08dc182f83", + "private" : "3b25129f3410ec89cc6dc539fd7601873ba6abf72a6d023f1aa9041765430ee6", + "shared" : "1d3fc2b2e48b3e96c6323380fadb467825e69f5b9078a9e02173b477bc232cc1", + "result" : "invalid" + }, + { + "tcId" : 493, + "comment" : "public key has invalid point of order 2 on FRP256v1. The point of the public key is a valid on secp256k1.", + "flags" : [ + "WrongCurve" + ], + "public" : "305b301506072a8648ce3d0201060a2a817a01815f6582000103420004f1fd178c0b3ad58f10126de8ce42435b3961adbcabc8ca6de8fcf353d86e9c03247e9edb2a633201dfc68fbd34556690db38ef76732f8a9052ee40d84e2ec35b", + "private" : "485dea32cd245db99d88e1852587c161b81abeabb151ad3fc1e4dd2f591e9936", + "shared" : "0a373d77057a50e3aad60b1e51bc017523dc2bdfef1c07cf4ed8393839224d0a", + "result" : "invalid" + }, + { + "tcId" : 494, + "comment" : "public point not on curve", + "flags" : [ + "ModifiedPublicPoint", + "InvalidPublic" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e4", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 495, + "comment" : "public point = (0,0)", + "flags" : [ + "ModifiedPublicPoint", + "InvalidPublic" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 496, + "comment" : "order = -115792089237316195423570985008687907852837564279074904382605163141518161494337", + "flags" : [ + "WrongOrder", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80221ff000000000000000000000000000000014551231950b75fc4402da1732fc9bebf0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 497, + "comment" : "order = 0", + "flags" : [ + "WrongOrder", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201000201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 498, + "comment" : "order = 1", + "flags" : [ + "WrongOrder", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201010201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 499, + "comment" : "order = 26959946667150639794667015087019630673536463705607434823784316690060", + "flags" : [ + "WrongOrder", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "3082012f3081e806072a8648ce3d02013081dc020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8021d00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8c0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 500, + "comment" : "generator = (0,0)", + "flags" : [ + "ModifiedGenerator", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 501, + "comment" : "generator not on curve", + "flags" : [ + "ModifiedGenerator", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4ba022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 502, + "comment" : "cofactor = -1", + "flags" : [ + "NegativeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 503, + "comment" : "cofactor = 0", + "flags" : [ + "NegativeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 504, + "comment" : "cofactor = 2", + "flags" : [ + "ModifiedCofactor", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201020342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 505, + "comment" : "cofactor = n", + "flags" : [ + "LargeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201553082010d06072a8648ce3d020130820100020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 506, + "comment" : "cofactor = None", + "flags" : [ + "ModifiedCofactor", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 507, + "comment" : "modified prime", + "flags" : [ + "ModifiedPrime", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fb524ac7055bebf603a4e216abaa6a9ef8eb2bbea2cd820e59d46d8501f6268b304404200000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000000070441040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101034200040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "c5956b8cf7244e3c0457658a214210b358205cab12374d523ecf57895cecfeb0", + "result" : "invalid" + }, + { + "tcId" : 508, + "comment" : "using secp224r1", + "flags" : [ + "ModifiedGroup", + "InvalidPublic" + ], + "public" : "304e301006072a8648ce3d020106052b81040021033a0004074f56dc2ea648ef89c3b72e23bbd2da36f60243e4d2067b70604af1c2165cec2f86603d60c8a611d5b84ba3d91dfe1a480825bcc4af3bcf", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 509, + "comment" : "using secp256r1", + "flags" : [ + "ModifiedGroup", + "InvalidPublic" + ], + "public" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cbf6606595a3ee50f9fceaa2798c2740c82540516b4e5a7d361ff24e9dd15364e5408b2e679f9d5310d1f6893b36ce16b4a507509175fcb52aea53b781556b39", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 510, + "comment" : "a = 0", + "flags" : [ + "Modified curve parameter", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 511, + "comment" : "public key of order 3", + "flags" : [ + "WeakPublicKey", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f304404209234b518bfe789f01e2389571299e39b4596c63a14d598659341dd313c65e08a04209d569a9efeeb4362b094d096024cba7b53d51dbc33818c8cdf37b9315d2e7bab044104fb6075d26c3501c014e48c79b3463cd768378c390d7e6eeb379717d490c4e63487fbca88e6867877e98f43ec02f4a0f45ef0f94310d8ee3d70a10280ce2ae6b3022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414102010103420004fb6075d26c3501c014e48c79b3463cd768378c390d7e6eeb379717d490c4e63478043577197987881670bc13fd0b5f0ba10f06bcef2711c28f5efd7e31d5157c", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 512, + "comment" : "Public key uses wrong curve: secp224r1", + "flags" : [ + "WrongCurve" + ], + "public" : "304e301006072a8648ce3d020106052b81040021033a000450eb062b54940a455719d523e1ec106525dda34c2fd95ace62b9b16d315d323f089173d10c45dceff155942431750c00ca36f463828e9fab", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 513, + "comment" : "Public key uses wrong curve: secp256r1", + "flags" : [ + "WrongCurve" + ], + "public" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000406372852584037722a7f9bfaad5661acb623162d45f70a552c617f4080e873aa43609275dff6dcaaa122a745d0f154681f9c7726867b43e7523b7f5ab5ea963e", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 514, + "comment" : "Public key uses wrong curve: secp384r1", + "flags" : [ + "WrongCurve" + ], + "public" : "3076301006072a8648ce3d020106052b81040022036200040ef5804731d918f037506ee00b8602b877c7d509ffa2c0847a86e7a2d358ba7c981c2a74b22401ac615307a6deb275402fa6c8218c3374f8a91752d2eff6bd14ad8cae596d2f37dae8aeec085760edf4fda9a7cf70253898a54183469072a561", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 515, + "comment" : "Public key uses wrong curve: secp521r1", + "flags" : [ + "WrongCurve" + ], + "public" : "30819b301006072a8648ce3d020106052b81040023038186000400921da57110db26c7838a69d574fc98588c5c07a792cb379f46664cc773c1e1f6fa16148667748ede232d1a1f1cea7f152c5d586172acbeaa48416bcbd70bb27f0f01b4477e1ae74bf4f093184a9f26f103712ccf6ceb45a0505b191606d897edaf872b37f0f90a933000a80fc3207048323c16883a3d67a90aa78bcc9c5e58d784b9b9", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 516, + "comment" : "Public key uses wrong curve: secp224k1", + "flags" : [ + "WrongCurve" + ], + "public" : "304e301006072a8648ce3d020106052b81040020033a000456dd09f8a8c19039286b6aa79d099ff3e35ff74400437d2072fd9faa7f2901db79d793f55268980f7d395055330a91b46bf4a62c3a528230", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 517, + "comment" : "Public key uses wrong curve: brainpoolP224r1", + "flags" : [ + "WrongCurve" + ], + "public" : "3052301406072a8648ce3d020106092b2403030208010105033a00042c9fdd1914cacdb28e39e6fc24b4c3c666cc0d438acc4529a6cc297a2d0fdecb3028d9e4d84c711db352379c080c78659969bdc5d3218901", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 518, + "comment" : "Public key uses wrong curve: brainpoolP256r1", + "flags" : [ + "WrongCurve" + ], + "public" : "305a301406072a8648ce3d020106092b240303020801010703420004120e4db849e5d960741c7d221aa80fe6e4fcd578191b7f845a68a6fcb8647719a6fffb6165d8ec39389eecc530839c321b2e9040027fba5d9cb9311df7cd3d4d", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 519, + "comment" : "Public key uses wrong curve: brainpoolP320r1", + "flags" : [ + "WrongCurve" + ], + "public" : "306a301406072a8648ce3d020106092b2403030208010109035200040efb1c104938f59a931fe6bf69f7ead4036d2336075a708e66b020e1bc5bb6d9cdc86d4e8fa181d7c7ea1af28353044e8cec12eec75a6dd87a5dc902024d93f8c8d9bf43b453fd919151f9bd7bb955c7", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 520, + "comment" : "Public key uses wrong curve: brainpoolP384r1", + "flags" : [ + "WrongCurve" + ], + "public" : "307a301406072a8648ce3d020106092b240303020801010b036200043e96d75b79214e69a4550e25375478bdc9c2a9d0178a77b5700bd5f12e3ce142f50c93dc1ee7268456d7eae2d44b718d6f159e896ae14fbe3aba397801a95e2bb6a9a761e865b289dd9db64aa07c794cedf77328543b94c9b54ce0cf04c60ac8", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 521, + "comment" : "Public key uses wrong curve: brainpoolP512r1", + "flags" : [ + "WrongCurve" + ], + "public" : "30819b301406072a8648ce3d020106092b240303020801010d03818200044f191130740f1b75ae13402960eb22ea801db80ed51a461e06a7b3ba60c9bddd132a6465bbee8afd70cfb4495efbda4f1567b958e6e305bfcb4ac8f05172688e0f2f175aa12425be3ab7271b42f258639e868677d1163c12e641229f1e6427761c9e294de51db564151b21a051d2f7a13661852799557a556a5f3c51d36d083a", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 522, + "comment" : "Public key uses wrong curve: brainpoolP224t1", + "flags" : [ + "WrongCurve" + ], + "public" : "3052301406072a8648ce3d020106092b2403030208010106033a00044964b948cefa39cd769e3480d4840a3c58e966161be80df02d9aab33b4a318a32f30130224edcefe0dd64342404e594aa334995b179f641f", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 523, + "comment" : "Public key uses wrong curve: brainpoolP256t1", + "flags" : [ + "WrongCurve" + ], + "public" : "305a301406072a8648ce3d020106092b24030302080101080342000411157979c08bcd175d34572209a85f3f5d602e35bdc3b553b0f19307672b31ba69d0556bce48c43e2e7e6177055221a4c4b7eb17ee9708f49216de76d6e92ab8", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 524, + "comment" : "Public key uses wrong curve: brainpoolP320t1", + "flags" : [ + "WrongCurve" + ], + "public" : "306a301406072a8648ce3d020106092b240303020801010a035200048bb517e198930eba57293419876a8793f711de37c27f200e6fb2c2b13e9fabd4fbc42ad61751ca583031ba76cbc6d745d115addc74eab63bf415c4fa20dbbecae98ac3c3da1a041705cf8959e2ccf453", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 525, + "comment" : "Public key uses wrong curve: brainpoolP384t1", + "flags" : [ + "WrongCurve" + ], + "public" : "307a301406072a8648ce3d020106092b240303020801010c036200045eb38d0261b744b03abef4ae7c17bc886b5b426bd910958f8a49ef62053048f869541b7a05d244315fc9cd74271ec3d518d94114b6006017f4ed5e3c06322baa1c75809a1057ba6fa46d1e1a9927a262e627940d5da538b5a3d1d794d9c866a4", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 526, + "comment" : "Public key uses wrong curve: brainpoolP512t1", + "flags" : [ + "WrongCurve" + ], + "public" : "30819b301406072a8648ce3d020106092b240303020801010e0381820004035fc238e57d980beae0215fb89108f9c6c4afda5d920f9d0583ee7d65f8778ecfff24a31d4f32deb6ea5f7e3adb6affb9327a5e62e09cba07c88b119fd104a83b7811e958e393971a5c9417412070b9f18b03be37e81e0bca5d3ff0873ed1f3113ed0fc57a0344321fb4d6c43f2f6e630a3d3883efe4c21df3e0f0b1208226b", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 527, + "comment" : "Public key uses wrong curve: FRP256v1", + "flags" : [ + "WrongCurve" + ], + "public" : "305b301506072a8648ce3d0201060a2a817a01815f6582000103420004375e9438d4ab14e298a75eab1e2d51a9248c8ee0bbb24397cbd4651517faedd26d4ded568d2348a473aa5a7570107dc6fc60a2ce0c4143446b5b09ab3fcc7bb4", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 528, + "comment" : "invalid public key", + "flags" : [ + "InvalidCompressedPublic", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a03220002977cb7fb9a0ec5b208e811d6a0795eb78d7642e3cac42a801bcc8fc0f06472d4", + "private" : "00d09182a4d0c94ba85f82eff9fc1bddb0b07d3f2af8632fc1c73a3604e8f0b335", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 529, + "comment" : "public key is a low order point on twist", + "flags" : [ + "WrongCurve", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a032200020000000000000000000000000000000000000000000000000000000000000000", + "private" : "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb300", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 530, + "comment" : "public key is a low order point on twist", + "flags" : [ + "WrongCurve", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a032200030000000000000000000000000000000000000000000000000000000000000000", + "private" : "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb2ff", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 531, + "comment" : "length of sequence uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "308156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 532, + "comment" : "length of sequence uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "305730811006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 533, + "comment" : "length of sequence contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "30820056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 534, + "comment" : "length of sequence contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583082001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 535, + "comment" : "length of sequence uses 87 instead of 86", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 536, + "comment" : "length of sequence uses 85 instead of 86", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 537, + "comment" : "uint32 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30850100000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 538, + "comment" : "uint32 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3085010000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 539, + "comment" : "uint64 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3089010000000000000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 540, + "comment" : "uint64 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f308901000000000000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 541, + "comment" : "length of sequence = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "30847fffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 542, + "comment" : "length of sequence = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a30847fffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 543, + "comment" : "length of sequence = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "3084ffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 544, + "comment" : "length of sequence = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a3084ffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 545, + "comment" : "length of sequence = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "3085ffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 546, + "comment" : "length of sequence = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3085ffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 547, + "comment" : "length of sequence = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "3088ffffffffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 548, + "comment" : "length of sequence = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3088ffffffffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 549, + "comment" : "incorrect length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30ff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 550, + "comment" : "incorrect length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305630ff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 551, + "comment" : "replaced sequence by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 552, + "comment" : "replaced sequence by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056308006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 553, + "comment" : "removing sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 554, + "comment" : "removing sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "304403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 555, + "comment" : "lonely sequence tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "30", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 556, + "comment" : "lonely sequence tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "30453003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 557, + "comment" : "appending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 558, + "comment" : "appending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 559, + "comment" : "prepending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30580000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 560, + "comment" : "prepending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012000006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 561, + "comment" : "appending unused 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 562, + "comment" : "appending unused 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 563, + "comment" : "appending null value to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 564, + "comment" : "appending null value to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 565, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b4981773056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 566, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a25003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 567, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3015498177301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 568, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a30142500301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 569, + "comment" : "appending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 570, + "comment" : "appending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3012301006072a8648ce3d020106052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 571, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305eaa00bb00cd003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 572, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3018aa00bb00cd00301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 573, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3018260faa00bb00cd0006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 574, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301806072a8648ce3d0201260daa00bb00cd0006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 575, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301006072a8648ce3d020106052b8104000a234aaa00bb00cd0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 576, + "comment" : "truncated length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3081", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 577, + "comment" : "truncated length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3046308103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 578, + "comment" : "including undefined tags to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305caa02aabb3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 579, + "comment" : "including undefined tags to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c3016aa02aabb301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 580, + "comment" : "Replacing sequence with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "0500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 581, + "comment" : "Replacing sequence with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "3046050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 582, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "2e56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 583, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "2f56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 584, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 585, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3256301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 586, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "ff56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 587, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30562e1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 588, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30562f1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 589, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056311006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 590, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056321006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 591, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056ff1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 592, + "comment" : "dropping value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 593, + "comment" : "dropping value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3046300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 594, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 595, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30551006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 596, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06072a8648ce3d020106052b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 597, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 598, + "comment" : "sequence of size 4183 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "30821057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 599, + "comment" : "indefinite length", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 600, + "comment" : "indefinite length", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058308006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 601, + "comment" : "indefinite length with truncated delimiter", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326700", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 602, + "comment" : "indefinite length with truncated delimiter", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057308006072a8648ce3d020106052b8104000a0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 603, + "comment" : "indefinite length with additional element", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326705000000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 604, + "comment" : "indefinite length with additional element", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a308006072a8648ce3d020106052b8104000a0500000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 605, + "comment" : "indefinite length with truncated element", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267060811220000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 606, + "comment" : "indefinite length with truncated element", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c308006072a8648ce3d020106052b8104000a06081122000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 607, + "comment" : "indefinite length with garbage", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000fe02beef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 608, + "comment" : "indefinite length with garbage", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c308006072a8648ce3d020106052b8104000a0000fe02beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 609, + "comment" : "indefinite length with nonempty EOC", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670002beef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 610, + "comment" : "indefinite length with nonempty EOC", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a308006072a8648ce3d020106052b8104000a0002beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 611, + "comment" : "prepend empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 612, + "comment" : "prepend empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012300006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 613, + "comment" : "append empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32673000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 614, + "comment" : "append empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000a300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 615, + "comment" : "append garbage with high tag number", + "flags" : [ + "InvalidAsn" + ], + "public" : "3059301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267bf7f00", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 616, + "comment" : "append garbage with high tag number", + "flags" : [ + "InvalidAsn" + ], + "public" : "3059301306072a8648ce3d020106052b8104000abf7f0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 617, + "comment" : "append null with explicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267a0020500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 618, + "comment" : "append null with explicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d020106052b8104000aa002050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 619, + "comment" : "append null with implicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267a000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 620, + "comment" : "append null with implicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000aa00003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 621, + "comment" : "sequence of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 622, + "comment" : "sequence of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 623, + "comment" : "truncated sequence: removed last 1 elements", + "flags" : [ + "InvalidAsn" + ], + "public" : "3012301006072a8648ce3d020106052b8104000a", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 624, + "comment" : "truncated sequence: removed last 1 elements", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f300906072a8648ce3d020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 625, + "comment" : "repeating element in sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30819a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 626, + "comment" : "repeating element in sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305d301706072a8648ce3d020106052b8104000a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 627, + "comment" : "length of sequence uses 17 instead of 16", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301106072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 628, + "comment" : "length of sequence uses 15 instead of 16", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056300f06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 629, + "comment" : "sequence of size 4113 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "308210593082101106072a8648ce3d020106052b8104000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 630, + "comment" : "length of oid uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "305730110681072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 631, + "comment" : "length of oid uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d02010681052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 632, + "comment" : "length of oid contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012068200072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 633, + "comment" : "length of oid contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d0201068200052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 634, + "comment" : "length of oid uses 8 instead of 7", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006082a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 635, + "comment" : "length of oid uses 6 instead of 7", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006062a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 636, + "comment" : "uint32 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3015068501000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 637, + "comment" : "uint32 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301506072a8648ce3d0201068501000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 638, + "comment" : "uint64 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906890100000000000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 639, + "comment" : "uint64 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906072a8648ce3d020106890100000000000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 640, + "comment" : "length of oid = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406847fffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 641, + "comment" : "length of oid = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d020106847fffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 642, + "comment" : "length of oid = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a30140684ffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 643, + "comment" : "length of oid = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d02010684ffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 644, + "comment" : "length of oid = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b30150685ffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 645, + "comment" : "length of oid = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301506072a8648ce3d02010685ffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 646, + "comment" : "length of oid = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e30180688ffffffffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 647, + "comment" : "length of oid = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301806072a8648ce3d02010688ffffffffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 648, + "comment" : "incorrect length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006ff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 649, + "comment" : "incorrect length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106ff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 650, + "comment" : "replaced oid by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006802a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 651, + "comment" : "replaced oid by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106802b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 652, + "comment" : "removing oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "304d300706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 653, + "comment" : "lonely oid tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "304e30080606052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 654, + "comment" : "lonely oid tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3050300a06072a8648ce3d02010603420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 655, + "comment" : "appending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206092a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 656, + "comment" : "appending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106072b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 657, + "comment" : "prepending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012060900002a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 658, + "comment" : "prepending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d0201060700002b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 659, + "comment" : "appending unused 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 660, + "comment" : "appending null value to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206092a8648ce3d0201050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 661, + "comment" : "appending null value to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106072b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 662, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3015260c49817706072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 663, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a3014260b250006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 664, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301506072a8648ce3d0201260a49817706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 665, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d02012609250006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 666, + "comment" : "appending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3018260906072a8648ce3d02010004deadbeef06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 667, + "comment" : "appending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301806072a8648ce3d0201260706052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 668, + "comment" : "truncated length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f3009068106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 669, + "comment" : "truncated length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3051300b06072a8648ce3d0201068103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 670, + "comment" : "including undefined tags to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c3016260daa02aabb06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 671, + "comment" : "including undefined tags to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c301606072a8648ce3d0201260baa02aabb06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 672, + "comment" : "Replacing oid with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f3009050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 673, + "comment" : "Replacing oid with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "3051300b06072a8648ce3d0201050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 674, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301004072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 675, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301005072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 676, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301007072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 677, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301008072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 678, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "30563010ff072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 679, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020104052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 680, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020105052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 681, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020107052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 682, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020108052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 683, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d0201ff052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 684, + "comment" : "dropping value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f3009060006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 685, + "comment" : "dropping value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3051300b06072a8648ce3d0201060003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 686, + "comment" : "modifying first byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305630100607288648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 687, + "comment" : "modifying first byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d02010605298104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 688, + "comment" : "modifying last byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d028106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 689, + "comment" : "modifying last byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104008a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 690, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06062a8648ce3d0206052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 691, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06068648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 692, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06072a8648ce3d020106042b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 693, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06072a8648ce3d020106048104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 694, + "comment" : "oid of size 4104 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082105b30821013068210082a8648ce3d0201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 695, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3054300e06052b0e03021a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 696, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012060960864801650304020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 697, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b0e03021a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 698, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d0201060960864801650304020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 699, + "comment" : "longer oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106082a8648ce3d02010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 700, + "comment" : "longer oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d020106062b8104000a0103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 701, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d021106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 702, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a3014060b2a8648ce3d02888080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 703, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104001a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 704, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d020106092b810400888080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 705, + "comment" : "large integer in oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906102a8648ce3d028280808080808080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 706, + "comment" : "large integer in oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906072a8648ce3d0201060e2b8104008280808080808080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 707, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106082a8648ce3d0201e006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 708, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106082a808648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 709, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d020106062b8104000ae003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 710, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d020106062b808104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 711, + "comment" : "oid with 263 nodes", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082015b30820113068201082a8648ce3d0201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 712, + "comment" : "length of oid uses 6 instead of 5", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106062b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 713, + "comment" : "length of oid uses 4 instead of 5", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106042b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 714, + "comment" : "oid of size 4102 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082105b3082101306072a8648ce3d0201068210062b8104000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 715, + "comment" : "oid with 262 nodes", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082015b3082011306072a8648ce3d0201068201062b8104000a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 716, + "comment" : "length of bit string uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301006072a8648ce3d020106052b8104000a0381420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 717, + "comment" : "length of bit string contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a038200420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 718, + "comment" : "length of bit string uses 67 instead of 66", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 719, + "comment" : "length of bit string uses 65 instead of 66", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 720, + "comment" : "uint32 overflow in length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301006072a8648ce3d020106052b8104000a038501000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 721, + "comment" : "uint64 overflow in length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301006072a8648ce3d020106052b8104000a03890100000000000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 722, + "comment" : "length of bit string = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a03847fffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 723, + "comment" : "length of bit string = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a0384ffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 724, + "comment" : "length of bit string = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301006072a8648ce3d020106052b8104000a0385ffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 725, + "comment" : "length of bit string = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301006072a8648ce3d020106052b8104000a0388ffffffffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 726, + "comment" : "incorrect length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03ff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 727, + "comment" : "replaced bit string by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03800004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 728, + "comment" : "lonely bit string tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3013301006072a8648ce3d020106052b8104000a03", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 729, + "comment" : "appending 0's to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 730, + "comment" : "prepending 0's to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a034400000004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 731, + "comment" : "appending null value to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 732, + "comment" : "prepending garbage to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301006072a8648ce3d020106052b8104000a234749817703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 733, + "comment" : "prepending garbage to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a2346250003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 734, + "comment" : "appending garbage to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301006072a8648ce3d020106052b8104000a234403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 735, + "comment" : "truncated length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3014301006072a8648ce3d020106052b8104000a0381", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 736, + "comment" : "including undefined tags to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c301006072a8648ce3d020106052b8104000a2348aa02aabb03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 737, + "comment" : "Replacing bit string with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "3014301006072a8648ce3d020106052b8104000a0500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 738, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a01420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 739, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a02420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 740, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a04420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 741, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a05420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 742, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000aff420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 743, + "comment" : "dropping value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3014301006072a8648ce3d020106052b8104000a0300", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 744, + "comment" : "modifying first byte of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420204e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 745, + "comment" : "modifying last byte of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32e7", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 746, + "comment" : "truncated bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 747, + "comment" : "truncated bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a034104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 748, + "comment" : "bit string of size 4163 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "30821059301006072a8648ce3d020106052b8104000a038210430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 749, + "comment" : "declaring bits as unused in bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 750, + "comment" : "unused bits in bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a03462004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326701020304", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 751, + "comment" : "unused bits in empty bit-string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3015301006072a8648ce3d020106052b8104000a030103", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 752, + "comment" : "128 unused bits", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03428004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + } + ] + } + ] +} diff --git a/test/wycheproof/ecdsa_secp256k1_sha256_test.json b/test/wycheproof/ecdsa_secp256k1_sha256_test.json new file mode 100644 index 0000000..4ef54ce --- /dev/null +++ b/test/wycheproof/ecdsa_secp256k1_sha256_test.json @@ -0,0 +1,6356 @@ +{ + "algorithm" : "ECDSA", + "schema" : "ecdsa_verify_schema.json", + "generatorVersion" : "0.9rc5", + "numberOfTests" : 463, + "header" : [ + "Test vectors of type EcdsaVerify are meant for the verification", + "of ASN encoded ECDSA signatures." + ], + "notes" : { + "ArithmeticError" : { + "bugType" : "EDGE_CASE", + "description" : "Some implementations of ECDSA have arithmetic errors that occur when intermediate results have extreme values. This test vector has been constructed to test such occurences.", + "cves" : [ + "CVE-2017-18146" + ] + }, + "BerEncodedSignature" : { + "bugType" : "BER_ENCODING", + "description" : "ECDSA signatures are usually DER encoded. This signature contains valid values for r and s, but it uses alternative BER encoding.", + "effect" : "Accepting alternative BER encodings may be benign in some cases, or be an issue if protocol requires signature malleability.", + "cves" : [ + "CVE-2020-14966", + "CVE-2020-13822", + "CVE-2019-14859", + "CVE-2016-1000342" + ] + }, + "EdgeCasePublicKey" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector uses a special case public key. " + }, + "EdgeCaseShamirMultiplication" : { + "bugType" : "EDGE_CASE", + "description" : "Shamir proposed a fast method for computing the sum of two scalar multiplications efficiently. This test vector has been constructed so that an intermediate result is the point at infinity if Shamir's method is used." + }, + "IntegerOverflow" : { + "bugType" : "CAN_OF_WORMS", + "description" : "The test vector contains an r and s that has been modified, so that the original value is restored if the implementation ignores the most significant bits.", + "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "InvalidEncoding" : { + "bugType" : "CAN_OF_WORMS", + "description" : "ECDSA signatures are encoded using ASN.1. This test vector contains an incorrectly encoded signature. The test vector itself was generated from a valid signature by modifying its encoding.", + "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "InvalidSignature" : { + "bugType" : "AUTH_BYPASS", + "description" : "The signature contains special case values such as r=0 and s=0. Buggy implementations may accept such values, if the implementation does not check boundaries and computes s^(-1) == 0.", + "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowning the message to sign.", + "cves" : [ + "CVE-2022-21449", + "CVE-2021-43572", + "CVE-2022-24884" + ] + }, + "InvalidTypesInSignature" : { + "bugType" : "AUTH_BYPASS", + "description" : "The signature contains invalid types. Dynamic typed languages sometime coerce such values of different types into integers. If an implementation is careless and has additional bugs, such as not checking integer boundaries then it may be possible that such signatures are accepted.", + "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowning the message to sign.", + "cves" : [ + "CVE-2022-21449" + ] + }, + "MissingZero" : { + "bugType" : "LEGACY", + "description" : "Some implementations of ECDSA and DSA incorrectly encode r and s by not including leading zeros in the ASN encoding of integers when necessary. Hence, some implementations (e.g. jdk) allow signatures with incorrect ASN encodings assuming that the signature is otherwise valid.", + "effect" : "While signatures are more malleable if such signatures are accepted, this typically leads to no vulnerability, since a badly encoded signature can be reencoded correctly." + }, + "ModifiedInteger" : { + "bugType" : "CAN_OF_WORMS", + "description" : "The test vector contains an r and s that has been modified. The goal is to check for arithmetic errors.", + "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "ModifiedSignature" : { + "bugType" : "CAN_OF_WORMS", + "description" : "The test vector contains an invalid signature that was generated from a valid signature by modifying it.", + "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "ModularInverse" : { + "bugType" : "EDGE_CASE", + "description" : "The test vectors contains a signature where computing the modular inverse of s hits an edge case.", + "effect" : "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", + "cves" : [ + "CVE-2019-0865" + ] + }, + "PointDuplication" : { + "bugType" : "EDGE_CASE", + "description" : "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission.", + "cves" : [ + "2020-12607", + "CVE-2015-2730" + ] + }, + "RangeCheck" : { + "bugType" : "CAN_OF_WORMS", + "description" : "The test vector contains an r and s that has been modified. By adding or subtracting the order of the group (or other values) the test vector checks whether signature verification verifies the range of r and s.", + "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "SmallRandS" : { + "bugType" : "EDGE_CASE", + "description" : "The test vectors contains a signature where both r and s are small integers. Some libraries cannot verify such signatures.", + "effect" : "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", + "cves" : [ + "2020-13895" + ] + }, + "SpecialCaseHash" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains a signature where the hash of the message is a special case, e.g., contains a long run of 0 or 1 bits." + }, + "ValidSignature" : { + "bugType" : "BASIC", + "description" : "The test vector contains a valid signature that was generated pseudorandomly. Such signatures should not fail to verify unless some of the parameters (e.g. curve or hash function) are not supported." + } + }, + "testGroups" : [ + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "wx" : "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", + "wy" : "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 1, + "comment" : "pseudorandom signature", + "flags" : [ + "ValidSignature" + ], + "msg" : "", + "sig" : "3046022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", + "result" : "valid" + }, + { + "tcId" : 2, + "comment" : "pseudorandom signature", + "flags" : [ + "ValidSignature" + ], + "msg" : "4d7367", + "sig" : "30450220109cd8ae0374358984a8249c0a843628f2835ffad1df1a9a69aa2fe72355545c022100ac6f00daf53bd8b1e34da329359b6e08019c5b037fed79ee383ae39f85a159c6", + "result" : "valid" + }, + { + "tcId" : 3, + "comment" : "pseudorandom signature", + "flags" : [ + "ValidSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100d035ee1f17fdb0b2681b163e33c359932659990af77dca632012b30b27a057b302201939d9f3b2858bc13e3474cb50e6a82be44faa71940f876c1cba4c3e989202b6", + "result" : "valid" + }, + { + "tcId" : 4, + "comment" : "pseudorandom signature", + "flags" : [ + "ValidSignature" + ], + "msg" : "0000000000000000000000000000000000000000", + "sig" : "304402204f053f563ad34b74fd8c9934ce59e79c2eb8e6eca0fef5b323ca67d5ac7ed23802204d4b05daa0719e773d8617dce5631c5fd6f59c9bdc748e4b55c970040af01be5", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", + "wx" : "00b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6f", + "wy" : "00f0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 5, + "comment" : "signature malleability", + "flags" : [ + "ValidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647db37c21f4afd3203ae8dc4ae7794b0f87", + "result" : "valid" + }, + { + "tcId" : 6, + "comment" : "Legacy: ASN encoding of r misses leading 0", + "flags" : [ + "MissingZero" + ], + "msg" : "313233343030", + "sig" : "30440220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 7, + "comment" : "valid", + "flags" : [ + "ValidSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "valid" + }, + { + "tcId" : 8, + "comment" : "length of sequence [r, s] uses long form encoding", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "308145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 9, + "comment" : "length of sequence [r, s] contains a leading 0", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "30820045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 10, + "comment" : "length of sequence [r, s] uses 70 instead of 69", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 11, + "comment" : "length of sequence [r, s] uses 68 instead of 69", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 12, + "comment" : "uint32 overflow in length of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30850100000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 13, + "comment" : "uint64 overflow in length of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3089010000000000000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 14, + "comment" : "length of sequence [r, s] = 2**31 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30847fffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 15, + "comment" : "length of sequence [r, s] = 2**31", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "308480000000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 16, + "comment" : "length of sequence [r, s] = 2**32 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3084ffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 17, + "comment" : "length of sequence [r, s] = 2**40 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3085ffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 18, + "comment" : "length of sequence [r, s] = 2**64 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3088ffffffffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 19, + "comment" : "incorrect length of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30ff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 20, + "comment" : "replaced sequence [r, s] by an indefinite length tag without termination", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 21, + "comment" : "removing sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "", + "result" : "invalid" + }, + { + "tcId" : 22, + "comment" : "lonely sequence tag", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30", + "result" : "invalid" + }, + { + "tcId" : 23, + "comment" : "appending 0's to sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 24, + "comment" : "prepending 0's to sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30470000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 25, + "comment" : "appending unused 0's to sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 26, + "comment" : "appending null value to sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", + "result" : "invalid" + }, + { + "tcId" : 27, + "comment" : "prepending garbage to sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a4981773045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 28, + "comment" : "prepending garbage to sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304925003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 29, + "comment" : "appending garbage to sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", + "result" : "invalid" + }, + { + "tcId" : 30, + "comment" : "including undefined tags", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "304daa00bb00cd003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 31, + "comment" : "including undefined tags", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304d2229aa00bb00cd00022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 32, + "comment" : "including undefined tags", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652228aa00bb00cd0002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 33, + "comment" : "truncated length of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3081", + "result" : "invalid" + }, + { + "tcId" : 34, + "comment" : "including undefined tags to sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "304baa02aabb3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 35, + "comment" : "using composition with indefinite length for sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30803045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 36, + "comment" : "using composition with wrong tag for sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30803145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 37, + "comment" : "Replacing sequence [r, s] with NULL", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "0500", + "result" : "invalid" + }, + { + "tcId" : 38, + "comment" : "changing tag value of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "2e45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 39, + "comment" : "changing tag value of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "2f45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 40, + "comment" : "changing tag value of sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 41, + "comment" : "changing tag value of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3245022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 42, + "comment" : "changing tag value of sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "ff45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 43, + "comment" : "dropping value of sequence [r, s]", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3000", + "result" : "invalid" + }, + { + "tcId" : 44, + "comment" : "using composition for sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304930010230442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 45, + "comment" : "truncated sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", + "result" : "invalid" + }, + { + "tcId" : 46, + "comment" : "truncated sequence [r, s]", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 47, + "comment" : "sequence [r, s] of size 4166 to check for overflows", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30821046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid" + }, + { + "tcId" : 48, + "comment" : "indefinite length", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 49, + "comment" : "indefinite length with truncated delimiter", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba00", + "result" : "invalid" + }, + { + "tcId" : 50, + "comment" : "indefinite length with additional element", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba05000000", + "result" : "invalid" + }, + { + "tcId" : 51, + "comment" : "indefinite length with truncated element", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba060811220000", + "result" : "invalid" + }, + { + "tcId" : 52, + "comment" : "indefinite length with garbage", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000fe02beef", + "result" : "invalid" + }, + { + "tcId" : 53, + "comment" : "indefinite length with nonempty EOC", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0002beef", + "result" : "invalid" + }, + { + "tcId" : 54, + "comment" : "prepend empty sequence", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30473000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 55, + "comment" : "append empty sequence", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba3000", + "result" : "invalid" + }, + { + "tcId" : 56, + "comment" : "append zero", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba020100", + "result" : "invalid" + }, + { + "tcId" : 57, + "comment" : "append garbage with high tag number", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31babf7f00", + "result" : "invalid" + }, + { + "tcId" : 58, + "comment" : "append null with explicit tag", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31baa0020500", + "result" : "invalid" + }, + { + "tcId" : 59, + "comment" : "append null with implicit tag", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31baa000", + "result" : "invalid" + }, + { + "tcId" : 60, + "comment" : "sequence of sequence", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 61, + "comment" : "truncated sequence: removed last 1 elements", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3023022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365", + "result" : "invalid" + }, + { + "tcId" : 62, + "comment" : "repeating element in sequence", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3067022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 63, + "comment" : "flipped bit 0 in r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 64, + "comment" : "flipped bit 32 in r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccac983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 65, + "comment" : "flipped bit 48 in r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5133ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 66, + "comment" : "flipped bit 64 in r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc08b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 67, + "comment" : "length of r uses long form encoding", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "304602812100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 68, + "comment" : "length of r contains a leading 0", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "30470282002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 69, + "comment" : "length of r uses 34 instead of 33", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 70, + "comment" : "length of r uses 32 instead of 33", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 71, + "comment" : "uint32 overflow in length of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a0285010000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 72, + "comment" : "uint64 overflow in length of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304e028901000000000000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 73, + "comment" : "length of r = 2**31 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304902847fffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 74, + "comment" : "length of r = 2**31", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304902848000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 75, + "comment" : "length of r = 2**32 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30490284ffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 76, + "comment" : "length of r = 2**40 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a0285ffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 77, + "comment" : "length of r = 2**64 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304d0288ffffffffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 78, + "comment" : "incorrect length of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304502ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 79, + "comment" : "replaced r by an indefinite length tag without termination", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045028000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 80, + "comment" : "removing r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "302202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 81, + "comment" : "lonely integer tag", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30230202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 82, + "comment" : "lonely integer tag", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3024022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502", + "result" : "invalid" + }, + { + "tcId" : 83, + "comment" : "appending 0's to r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 84, + "comment" : "prepending 0's to r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30470223000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 85, + "comment" : "appending unused 0's to r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 86, + "comment" : "appending null value to r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 87, + "comment" : "prepending garbage to r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a2226498177022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 88, + "comment" : "prepending garbage to r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304922252500022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 89, + "comment" : "appending garbage to r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304d2223022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650004deadbeef02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 90, + "comment" : "truncated length of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3024028102206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 91, + "comment" : "including undefined tags to r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304b2227aa02aabb022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 92, + "comment" : "using composition with indefinite length for r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30492280022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 93, + "comment" : "using composition with wrong tag for r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "30492280032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 94, + "comment" : "Replacing r with NULL", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3024050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 95, + "comment" : "changing tag value of r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 96, + "comment" : "changing tag value of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045012100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 97, + "comment" : "changing tag value of r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 98, + "comment" : "changing tag value of r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045042100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 99, + "comment" : "changing tag value of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045ff2100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 100, + "comment" : "dropping value of r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3024020002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 101, + "comment" : "using composition for r", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304922250201000220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 102, + "comment" : "modifying first byte of r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045022102813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 103, + "comment" : "modifying last byte of r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323e502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 104, + "comment" : "truncated r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3044022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832302206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 105, + "comment" : "r of size 4130 to check for overflows", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "308210480282102200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 106, + "comment" : "leading ff in r", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30460222ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 107, + "comment" : "replaced r by infinity", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "302509018002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 108, + "comment" : "replacing r with zero", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "302502010002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 109, + "comment" : "flipped bit 0 in s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31bb", + "result" : "invalid" + }, + { + "tcId" : 110, + "comment" : "flipped bit 32 in s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a456eb31ba", + "result" : "invalid" + }, + { + "tcId" : 111, + "comment" : "flipped bit 48 in s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f713a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 112, + "comment" : "flipped bit 64 in s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758001d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 113, + "comment" : "length of s uses long form encoding", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 114, + "comment" : "length of s contains a leading 0", + "flags" : [ + "BerEncodedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028200206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 115, + "comment" : "length of s uses 33 instead of 32", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 116, + "comment" : "length of s uses 31 instead of 32", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 117, + "comment" : "uint32 overflow in length of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028501000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 118, + "comment" : "uint64 overflow in length of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304e022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502890100000000000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 119, + "comment" : "length of s = 2**31 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502847fffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 120, + "comment" : "length of s = 2**31", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284800000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 121, + "comment" : "length of s = 2**32 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284ffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 122, + "comment" : "length of s = 2**40 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650285ffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 123, + "comment" : "length of s = 2**64 - 1", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650288ffffffffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 124, + "comment" : "incorrect length of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 125, + "comment" : "replaced s by an indefinite length tag without termination", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502806ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 126, + "comment" : "appending 0's to s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 127, + "comment" : "prepending 0's to s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022200006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 128, + "comment" : "appending null value to s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", + "result" : "invalid" + }, + { + "tcId" : 129, + "comment" : "prepending garbage to s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222549817702206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 130, + "comment" : "prepending garbage to s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652224250002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 131, + "comment" : "appending garbage to s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", + "result" : "invalid" + }, + { + "tcId" : 132, + "comment" : "truncated length of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281", + "result" : "invalid" + }, + { + "tcId" : 133, + "comment" : "including undefined tags to s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "304b022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652226aa02aabb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 134, + "comment" : "using composition with indefinite length for s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 135, + "comment" : "using composition with wrong tag for s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228003206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result" : "invalid" + }, + { + "tcId" : 136, + "comment" : "Replacing s with NULL", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650500", + "result" : "invalid" + }, + { + "tcId" : 137, + "comment" : "changing tag value of s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236500206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 138, + "comment" : "changing tag value of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236501206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 139, + "comment" : "changing tag value of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236503206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 140, + "comment" : "changing tag value of s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236504206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 141, + "comment" : "changing tag value of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365ff206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 142, + "comment" : "dropping value of s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650200", + "result" : "invalid" + }, + { + "tcId" : 143, + "comment" : "using composition for s", + "flags" : [ + "InvalidEncoding" + ], + "msg" : "313233343030", + "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222402016f021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 144, + "comment" : "modifying first byte of s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206df18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 145, + "comment" : "modifying last byte of s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb313a", + "result" : "invalid" + }, + { + "tcId" : 146, + "comment" : "truncated s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", + "result" : "invalid" + }, + { + "tcId" : 147, + "comment" : "truncated s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 148, + "comment" : "s of size 4129 to check for overflows", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "30821048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028210216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid" + }, + { + "tcId" : 149, + "comment" : "leading ff in s", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 150, + "comment" : "replaced s by infinity", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365090180", + "result" : "invalid" + }, + { + "tcId" : 151, + "comment" : "replacing s with zero", + "flags" : [ + "ModifiedSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365020100", + "result" : "invalid" + }, + { + "tcId" : 152, + "comment" : "replaced r by r + n", + "flags" : [ + "RangeCheck" + ], + "msg" : "313233343030", + "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478583b90deabca4b05c4574e49b5899b964a602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 153, + "comment" : "replaced r by r - n", + "flags" : [ + "RangeCheck" + ], + "msg" : "313233343030", + "sig" : "30440220813ef79ccefa9a56f7ba805f0e47858643b030ef461f1bcdf53fde3ef94ce22402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 154, + "comment" : "replaced r by r + 256 * n", + "flags" : [ + "RangeCheck" + ], + "msg" : "313233343030", + "sig" : "304602220100813ef79ccefa9a56f7ba805f0e47843fad3bf4853e07f7c98770c99bffc4646502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 155, + "comment" : "replaced r by -r", + "flags" : [ + "ModifiedInteger" + ], + "msg" : "313233343030", + "sig" : "30450221ff7ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 156, + "comment" : "replaced r by n - r", + "flags" : [ + "ModifiedInteger" + ], + "msg" : "313233343030", + "sig" : "304402207ec10863310565a908457fa0f1b87a79bc4fcf10b9e0e4320ac021c106b31ddc02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 157, + "comment" : "replaced r by -n - r", + "flags" : [ + "ModifiedInteger" + ], + "msg" : "313233343030", + "sig" : "30450221fe7ec10863310565a908457fa0f1b87a7c46f215435b4fa3ba8b1b64a766469b5a02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 158, + "comment" : "replaced r by r + 2**256", + "flags" : [ + "IntegerOverflow" + ], + "msg" : "313233343030", + "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 159, + "comment" : "replaced r by r + 2**320", + "flags" : [ + "IntegerOverflow" + ], + "msg" : "313233343030", + "sig" : "304d0229010000000000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 160, + "comment" : "replaced s by s + n", + "flags" : [ + "RangeCheck" + ], + "msg" : "313233343030", + "sig" : "30450221016ff18a52dcc0336f7af62400a6dd9b7fc1e197d8aebe203c96c87232272172fb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 161, + "comment" : "replaced s by s - n", + "flags" : [ + "RangeCheck" + ], + "msg" : "313233343030", + "sig" : "30450221ff6ff18a52dcc0336f7af62400a6dd9b824c83de0b502cdfc51723b51886b4f07902206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 162, + "comment" : "replaced s by s + 256 * n", + "flags" : [ + "RangeCheck" + ], + "msg" : "313233343030", + "sig" : "3046022201006ff18a52dcc0336f7af62400a6dd9a3bb60fa1a14815bbc0a954a0758d2c72ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 163, + "comment" : "replaced s by -s", + "flags" : [ + "ModifiedInteger" + ], + "msg" : "313233343030", + "sig" : "30440220900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce4602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 164, + "comment" : "replaced s by -n - s", + "flags" : [ + "ModifiedInteger" + ], + "msg" : "313233343030", + "sig" : "30450221fe900e75ad233fcc908509dbff592264803e1e68275141dfc369378dcdd8de8d0502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 165, + "comment" : "replaced s by s + 2**256", + "flags" : [ + "IntegerOverflow" + ], + "msg" : "313233343030", + "sig" : "30450221016ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 166, + "comment" : "replaced s by s - 2**256", + "flags" : [ + "IntegerOverflow" + ], + "msg" : "313233343030", + "sig" : "30450221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 167, + "comment" : "replaced s by s + 2**320", + "flags" : [ + "IntegerOverflow" + ], + "msg" : "313233343030", + "sig" : "304d02290100000000000000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result" : "invalid" + }, + { + "tcId" : 168, + "comment" : "Signature with special case values r=0 and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3006020100020100", + "result" : "invalid" + }, + { + "tcId" : 169, + "comment" : "Signature with special case values r=0 and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3006020100020101", + "result" : "invalid" + }, + { + "tcId" : 170, + "comment" : "Signature with special case values r=0 and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30060201000201ff", + "result" : "invalid" + }, + { + "tcId" : 171, + "comment" : "Signature with special case values r=0 and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 172, + "comment" : "Signature with special case values r=0 and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 173, + "comment" : "Signature with special case values r=0 and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 174, + "comment" : "Signature with special case values r=0 and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 175, + "comment" : "Signature with special case values r=0 and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 176, + "comment" : "Signature with special case values r=1 and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3006020101020100", + "result" : "invalid" + }, + { + "tcId" : 177, + "comment" : "Signature with special case values r=1 and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3006020101020101", + "result" : "invalid" + }, + { + "tcId" : 178, + "comment" : "Signature with special case values r=1 and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30060201010201ff", + "result" : "invalid" + }, + { + "tcId" : 179, + "comment" : "Signature with special case values r=1 and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 180, + "comment" : "Signature with special case values r=1 and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 181, + "comment" : "Signature with special case values r=1 and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 182, + "comment" : "Signature with special case values r=1 and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 183, + "comment" : "Signature with special case values r=1 and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 184, + "comment" : "Signature with special case values r=-1 and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff020100", + "result" : "invalid" + }, + { + "tcId" : 185, + "comment" : "Signature with special case values r=-1 and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff020101", + "result" : "invalid" + }, + { + "tcId" : 186, + "comment" : "Signature with special case values r=-1 and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff0201ff", + "result" : "invalid" + }, + { + "tcId" : 187, + "comment" : "Signature with special case values r=-1 and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 188, + "comment" : "Signature with special case values r=-1 and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 189, + "comment" : "Signature with special case values r=-1 and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 190, + "comment" : "Signature with special case values r=-1 and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 191, + "comment" : "Signature with special case values r=-1 and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 192, + "comment" : "Signature with special case values r=n and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020100", + "result" : "invalid" + }, + { + "tcId" : 193, + "comment" : "Signature with special case values r=n and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101", + "result" : "invalid" + }, + { + "tcId" : 194, + "comment" : "Signature with special case values r=n and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff", + "result" : "invalid" + }, + { + "tcId" : 195, + "comment" : "Signature with special case values r=n and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 196, + "comment" : "Signature with special case values r=n and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 197, + "comment" : "Signature with special case values r=n and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 198, + "comment" : "Signature with special case values r=n and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 199, + "comment" : "Signature with special case values r=n and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 200, + "comment" : "Signature with special case values r=n - 1 and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020100", + "result" : "invalid" + }, + { + "tcId" : 201, + "comment" : "Signature with special case values r=n - 1 and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020101", + "result" : "invalid" + }, + { + "tcId" : 202, + "comment" : "Signature with special case values r=n - 1 and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400201ff", + "result" : "invalid" + }, + { + "tcId" : 203, + "comment" : "Signature with special case values r=n - 1 and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 204, + "comment" : "Signature with special case values r=n - 1 and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 205, + "comment" : "Signature with special case values r=n - 1 and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 206, + "comment" : "Signature with special case values r=n - 1 and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 207, + "comment" : "Signature with special case values r=n - 1 and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 208, + "comment" : "Signature with special case values r=n + 1 and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020100", + "result" : "invalid" + }, + { + "tcId" : 209, + "comment" : "Signature with special case values r=n + 1 and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020101", + "result" : "invalid" + }, + { + "tcId" : 210, + "comment" : "Signature with special case values r=n + 1 and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420201ff", + "result" : "invalid" + }, + { + "tcId" : 211, + "comment" : "Signature with special case values r=n + 1 and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 212, + "comment" : "Signature with special case values r=n + 1 and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 213, + "comment" : "Signature with special case values r=n + 1 and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 214, + "comment" : "Signature with special case values r=n + 1 and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 215, + "comment" : "Signature with special case values r=n + 1 and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 216, + "comment" : "Signature with special case values r=p and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020100", + "result" : "invalid" + }, + { + "tcId" : 217, + "comment" : "Signature with special case values r=p and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020101", + "result" : "invalid" + }, + { + "tcId" : 218, + "comment" : "Signature with special case values r=p and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0201ff", + "result" : "invalid" + }, + { + "tcId" : 219, + "comment" : "Signature with special case values r=p and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 220, + "comment" : "Signature with special case values r=p and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 221, + "comment" : "Signature with special case values r=p and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 222, + "comment" : "Signature with special case values r=p and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 223, + "comment" : "Signature with special case values r=p and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 224, + "comment" : "Signature with special case values r=p + 1 and s=0", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020100", + "result" : "invalid" + }, + { + "tcId" : 225, + "comment" : "Signature with special case values r=p + 1 and s=1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020101", + "result" : "invalid" + }, + { + "tcId" : 226, + "comment" : "Signature with special case values r=p + 1 and s=-1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300201ff", + "result" : "invalid" + }, + { + "tcId" : 227, + "comment" : "Signature with special case values r=p + 1 and s=n", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result" : "invalid" + }, + { + "tcId" : 228, + "comment" : "Signature with special case values r=p + 1 and s=n - 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result" : "invalid" + }, + { + "tcId" : 229, + "comment" : "Signature with special case values r=p + 1 and s=n + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result" : "invalid" + }, + { + "tcId" : 230, + "comment" : "Signature with special case values r=p + 1 and s=p", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result" : "invalid" + }, + { + "tcId" : 231, + "comment" : "Signature with special case values r=p + 1 and s=p + 1", + "flags" : [ + "InvalidSignature" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result" : "invalid" + }, + { + "tcId" : 232, + "comment" : "Signature encoding contains incorrect types: r=0, s=0.25", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3008020100090380fe01", + "result" : "invalid" + }, + { + "tcId" : 233, + "comment" : "Signature encoding contains incorrect types: r=0, s=nan", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006020100090142", + "result" : "invalid" + }, + { + "tcId" : 234, + "comment" : "Signature encoding contains incorrect types: r=0, s=True", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006020100010101", + "result" : "invalid" + }, + { + "tcId" : 235, + "comment" : "Signature encoding contains incorrect types: r=0, s=False", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006020100010100", + "result" : "invalid" + }, + { + "tcId" : 236, + "comment" : "Signature encoding contains incorrect types: r=0, s=Null", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201000500", + "result" : "invalid" + }, + { + "tcId" : 237, + "comment" : "Signature encoding contains incorrect types: r=0, s=empyt UTF-8 string", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201000c00", + "result" : "invalid" + }, + { + "tcId" : 238, + "comment" : "Signature encoding contains incorrect types: r=0, s=\"0\"", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060201000c0130", + "result" : "invalid" + }, + { + "tcId" : 239, + "comment" : "Signature encoding contains incorrect types: r=0, s=empty list", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201003000", + "result" : "invalid" + }, + { + "tcId" : 240, + "comment" : "Signature encoding contains incorrect types: r=0, s=list containing 0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30080201003003020100", + "result" : "invalid" + }, + { + "tcId" : 241, + "comment" : "Signature encoding contains incorrect types: r=1, s=0.25", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3008020101090380fe01", + "result" : "invalid" + }, + { + "tcId" : 242, + "comment" : "Signature encoding contains incorrect types: r=1, s=nan", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006020101090142", + "result" : "invalid" + }, + { + "tcId" : 243, + "comment" : "Signature encoding contains incorrect types: r=1, s=True", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006020101010101", + "result" : "invalid" + }, + { + "tcId" : 244, + "comment" : "Signature encoding contains incorrect types: r=1, s=False", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006020101010100", + "result" : "invalid" + }, + { + "tcId" : 245, + "comment" : "Signature encoding contains incorrect types: r=1, s=Null", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201010500", + "result" : "invalid" + }, + { + "tcId" : 246, + "comment" : "Signature encoding contains incorrect types: r=1, s=empyt UTF-8 string", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201010c00", + "result" : "invalid" + }, + { + "tcId" : 247, + "comment" : "Signature encoding contains incorrect types: r=1, s=\"0\"", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060201010c0130", + "result" : "invalid" + }, + { + "tcId" : 248, + "comment" : "Signature encoding contains incorrect types: r=1, s=empty list", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201013000", + "result" : "invalid" + }, + { + "tcId" : 249, + "comment" : "Signature encoding contains incorrect types: r=1, s=list containing 0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30080201013003020100", + "result" : "invalid" + }, + { + "tcId" : 250, + "comment" : "Signature encoding contains incorrect types: r=-1, s=0.25", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30080201ff090380fe01", + "result" : "invalid" + }, + { + "tcId" : 251, + "comment" : "Signature encoding contains incorrect types: r=-1, s=nan", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff090142", + "result" : "invalid" + }, + { + "tcId" : 252, + "comment" : "Signature encoding contains incorrect types: r=-1, s=True", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff010101", + "result" : "invalid" + }, + { + "tcId" : 253, + "comment" : "Signature encoding contains incorrect types: r=-1, s=False", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff010100", + "result" : "invalid" + }, + { + "tcId" : 254, + "comment" : "Signature encoding contains incorrect types: r=-1, s=Null", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201ff0500", + "result" : "invalid" + }, + { + "tcId" : 255, + "comment" : "Signature encoding contains incorrect types: r=-1, s=empyt UTF-8 string", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201ff0c00", + "result" : "invalid" + }, + { + "tcId" : 256, + "comment" : "Signature encoding contains incorrect types: r=-1, s=\"0\"", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060201ff0c0130", + "result" : "invalid" + }, + { + "tcId" : 257, + "comment" : "Signature encoding contains incorrect types: r=-1, s=empty list", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050201ff3000", + "result" : "invalid" + }, + { + "tcId" : 258, + "comment" : "Signature encoding contains incorrect types: r=-1, s=list containing 0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30080201ff3003020100", + "result" : "invalid" + }, + { + "tcId" : 259, + "comment" : "Signature encoding contains incorrect types: r=n, s=0.25", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090380fe01", + "result" : "invalid" + }, + { + "tcId" : 260, + "comment" : "Signature encoding contains incorrect types: r=n, s=nan", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090142", + "result" : "invalid" + }, + { + "tcId" : 261, + "comment" : "Signature encoding contains incorrect types: r=n, s=True", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141010101", + "result" : "invalid" + }, + { + "tcId" : 262, + "comment" : "Signature encoding contains incorrect types: r=n, s=False", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141010100", + "result" : "invalid" + }, + { + "tcId" : 263, + "comment" : "Signature encoding contains incorrect types: r=n, s=Null", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410500", + "result" : "invalid" + }, + { + "tcId" : 264, + "comment" : "Signature encoding contains incorrect types: r=n, s=empyt UTF-8 string", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410c00", + "result" : "invalid" + }, + { + "tcId" : 265, + "comment" : "Signature encoding contains incorrect types: r=n, s=\"0\"", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410c0130", + "result" : "invalid" + }, + { + "tcId" : 266, + "comment" : "Signature encoding contains incorrect types: r=n, s=empty list", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641413000", + "result" : "invalid" + }, + { + "tcId" : 267, + "comment" : "Signature encoding contains incorrect types: r=n, s=list containing 0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641413003020100", + "result" : "invalid" + }, + { + "tcId" : 268, + "comment" : "Signature encoding contains incorrect types: r=p, s=0.25", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090380fe01", + "result" : "invalid" + }, + { + "tcId" : 269, + "comment" : "Signature encoding contains incorrect types: r=p, s=nan", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090142", + "result" : "invalid" + }, + { + "tcId" : 270, + "comment" : "Signature encoding contains incorrect types: r=p, s=True", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f010101", + "result" : "invalid" + }, + { + "tcId" : 271, + "comment" : "Signature encoding contains incorrect types: r=p, s=False", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f010100", + "result" : "invalid" + }, + { + "tcId" : 272, + "comment" : "Signature encoding contains incorrect types: r=p, s=Null", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0500", + "result" : "invalid" + }, + { + "tcId" : 273, + "comment" : "Signature encoding contains incorrect types: r=p, s=empyt UTF-8 string", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0c00", + "result" : "invalid" + }, + { + "tcId" : 274, + "comment" : "Signature encoding contains incorrect types: r=p, s=\"0\"", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0c0130", + "result" : "invalid" + }, + { + "tcId" : 275, + "comment" : "Signature encoding contains incorrect types: r=p, s=empty list", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3000", + "result" : "invalid" + }, + { + "tcId" : 276, + "comment" : "Signature encoding contains incorrect types: r=p, s=list containing 0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3003020100", + "result" : "invalid" + }, + { + "tcId" : 277, + "comment" : "Signature encoding contains incorrect types: r=0.25, s=0.25", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "300a090380fe01090380fe01", + "result" : "invalid" + }, + { + "tcId" : 278, + "comment" : "Signature encoding contains incorrect types: r=nan, s=nan", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006090142090142", + "result" : "invalid" + }, + { + "tcId" : 279, + "comment" : "Signature encoding contains incorrect types: r=True, s=True", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006010101010101", + "result" : "invalid" + }, + { + "tcId" : 280, + "comment" : "Signature encoding contains incorrect types: r=False, s=False", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006010100010100", + "result" : "invalid" + }, + { + "tcId" : 281, + "comment" : "Signature encoding contains incorrect types: r=Null, s=Null", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "300405000500", + "result" : "invalid" + }, + { + "tcId" : 282, + "comment" : "Signature encoding contains incorrect types: r=empyt UTF-8 string, s=empyt UTF-8 string", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30040c000c00", + "result" : "invalid" + }, + { + "tcId" : 283, + "comment" : "Signature encoding contains incorrect types: r=\"0\", s=\"0\"", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060c01300c0130", + "result" : "invalid" + }, + { + "tcId" : 284, + "comment" : "Signature encoding contains incorrect types: r=empty list, s=empty list", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "300430003000", + "result" : "invalid" + }, + { + "tcId" : 285, + "comment" : "Signature encoding contains incorrect types: r=list containing 0, s=list containing 0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "300a30030201003003020100", + "result" : "invalid" + }, + { + "tcId" : 286, + "comment" : "Signature encoding contains incorrect types: r=0.25, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3008090380fe01020100", + "result" : "invalid" + }, + { + "tcId" : 287, + "comment" : "Signature encoding contains incorrect types: r=nan, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006090142020100", + "result" : "invalid" + }, + { + "tcId" : 288, + "comment" : "Signature encoding contains incorrect types: r=True, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006010101020100", + "result" : "invalid" + }, + { + "tcId" : 289, + "comment" : "Signature encoding contains incorrect types: r=False, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "3006010100020100", + "result" : "invalid" + }, + { + "tcId" : 290, + "comment" : "Signature encoding contains incorrect types: r=Null, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050500020100", + "result" : "invalid" + }, + { + "tcId" : 291, + "comment" : "Signature encoding contains incorrect types: r=empyt UTF-8 string, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30050c00020100", + "result" : "invalid" + }, + { + "tcId" : 292, + "comment" : "Signature encoding contains incorrect types: r=\"0\", s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30060c0130020100", + "result" : "invalid" + }, + { + "tcId" : 293, + "comment" : "Signature encoding contains incorrect types: r=empty list, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30053000020100", + "result" : "invalid" + }, + { + "tcId" : 294, + "comment" : "Signature encoding contains incorrect types: r=list containing 0, s=0", + "flags" : [ + "InvalidTypesInSignature" + ], + "msg" : "313233343030", + "sig" : "30083003020100020100", + "result" : "invalid" + }, + { + "tcId" : 295, + "comment" : "Edge case for Shamir multiplication", + "flags" : [ + "EdgeCaseShamirMultiplication" + ], + "msg" : "3235353835", + "sig" : "3045022100dd1b7d09a7bd8218961034a39a87fecf5314f00c4d25eb58a07ac85e85eab516022035138c401ef8d3493d65c9002fe62b43aee568731b744548358996d9cc427e06", + "result" : "valid" + }, + { + "tcId" : 296, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "343236343739373234", + "sig" : "304502210095c29267d972a043d955224546222bba343fc1d4db0fec262a33ac61305696ae02206edfe96713aed56f8a28a6653f57e0b829712e5eddc67f34682b24f0676b2640", + "result" : "valid" + }, + { + "tcId" : 297, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "37313338363834383931", + "sig" : "3045022028f94a894e92024699e345fe66971e3edcd050023386135ab3939d550898fb25022100cd69c1a42be05a6ee1270c821479251e134c21858d800bda6f4e98b37196238e", + "result" : "valid" + }, + { + "tcId" : 298, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3130333539333331363638", + "sig" : "3046022100be26b18f9549f89f411a9b52536b15aa270b84548d0e859a1952a27af1a77ac60221008f3e2b05632fc33715572af9124681113f2b84325b80154c044a544dc1a8fa12", + "result" : "valid" + }, + { + "tcId" : 299, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33393439343031323135", + "sig" : "3046022100b1a4b1478e65cc3eafdf225d1298b43f2da19e4bcff7eacc0a2e98cd4b74b114022100e8655ce1cfb33ebd30af8ce8e8ae4d6f7b50cd3e22af51bf69e0a2851760d52b", + "result" : "valid" + }, + { + "tcId" : 300, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31333434323933303739", + "sig" : "30440220325332021261f1bd18f2712aa1e2252da23796da8a4b1ff6ea18cafec7e171f2022040b4f5e287ee61fc3c804186982360891eaa35c75f05a43ecd48b35d984a6648", + "result" : "valid" + }, + { + "tcId" : 301, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33373036323131373132", + "sig" : "3046022100a23ad18d8fc66d81af0903890cbd453a554cb04cdc1a8ca7f7f78e5367ed88a0022100dc1c14d31e3fb158b73c764268c8b55579734a7e2a2c9b5ee5d9d0144ef652eb", + "result" : "valid" + }, + { + "tcId" : 302, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "333433363838373132", + "sig" : "304502202bdea41cda63a2d14bf47353bd20880a690901de7cd6e3cc6d8ed5ba0cdb1091022100c31599433036064073835b1e3eba8335a650c8fd786f94fe235ad7d41dc94c7a", + "result" : "valid" + }, + { + "tcId" : 303, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31333531353330333730", + "sig" : "3046022100d7cd76ec01c1b1079eba9e2aa2a397243c4758c98a1ba0b7404a340b9b00ced6022100ca8affe1e626dd192174c2937b15bc48f77b5bdfe01f073a8aeaf7f24dc6c85b", + "result" : "valid" + }, + { + "tcId" : 304, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "36353533323033313236", + "sig" : "3045022100a872c744d936db21a10c361dd5c9063355f84902219652f6fc56dc95a7139d960220400df7575d9756210e9ccc77162c6b593c7746cfb48ac263c42750b421ef4bb9", + "result" : "valid" + }, + { + "tcId" : 305, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31353634333436363033", + "sig" : "30460221009fa9afe07752da10b36d3afcd0fe44bfc40244d75203599cf8f5047fa3453854022100af1f583fec4040ae7e68c968d2bb4b494eec3a33edc7c0ccf95f7f75bc2569c7", + "result" : "valid" + }, + { + "tcId" : 306, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "34343239353339313137", + "sig" : "3045022100885640384d0d910efb177b46be6c3dc5cac81f0b88c3190bb6b5f99c2641f2050220738ed9bff116306d9caa0f8fc608be243e0b567779d8dab03e8e19d553f1dc8e", + "result" : "valid" + }, + { + "tcId" : 307, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3130393533323631333531", + "sig" : "304502202d051f91c5a9d440c5676985710483bc4f1a6c611b10c95a2ff0363d90c2a45802210092206b19045a41a797cc2f3ac30de9518165e96d5b86341ecb3bcff231b3fd65", + "result" : "valid" + }, + { + "tcId" : 308, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "35393837333530303431", + "sig" : "3045022100f3ac2523967482f53d508522712d583f4379cd824101ff635ea0935117baa54f022027f10812227397e02cea96fb0e680761636dab2b080d1fc5d11685cbe8500cfe", + "result" : "valid" + }, + { + "tcId" : 309, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33343633303036383738", + "sig" : "304602210096447cf68c3ab7266ed7447de3ac52fed7cc08cbdfea391c18a9b8ab370bc913022100f0a1878b2c53f16e70fe377a5e9c6e86f18ae480a22bb499f5b32e7109c07385", + "result" : "valid" + }, + { + "tcId" : 310, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "39383137333230323837", + "sig" : "30450220530a0832b691da0b5619a0b11de6877f3c0971baaa68ed122758c29caaf46b7202210093761bb0a14ccf9f15b4b9ce73c6ec700bd015b8cb1cfac56837f4463f53074e", + "result" : "valid" + }, + { + "tcId" : 311, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33323232303431303436", + "sig" : "30460221009c54c25500bde0b92d72d6ec483dc2482f3654294ca74de796b681255ed58a77022100988bac394a90ad89ce360984c0c149dcbd2684bb64498ace90bcf6b6af1c170e", + "result" : "valid" + }, + { + "tcId" : 312, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "36363636333037313034", + "sig" : "3045022100e7909d41439e2f6af29136c7348ca2641a2b070d5b64f91ea9da7070c7a2618b022042d782f132fa1d36c2c88ba27c3d678d80184a5d1eccac7501f0b47e3d205008", + "result" : "valid" + }, + { + "tcId" : 313, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31303335393531383938", + "sig" : "304502205924873209593135a4c3da7bb381227f8a4b6aa9f34fe5bb7f8fbc131a039ffe022100e0e44ee4bbe370155bf0bbdec265bf9fe31c0746faab446de62e3631eacd111f", + "result" : "valid" + }, + { + "tcId" : 314, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31383436353937313935", + "sig" : "3045022100eeb692c9b262969b231c38b5a7f60649e0c875cd64df88f33aa571fa3d29ab0e0220218b3a1eb06379c2c18cf51b06430786d1c64cd2d24c9b232b23e5bac7989acd", + "result" : "valid" + }, + { + "tcId" : 315, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33313336303436313839", + "sig" : "3045022100a40034177f36091c2b653684a0e3eb5d4bff18e4d09f664c2800e7cafda1daf802203a3ec29853704e52031c58927a800a968353adc3d973beba9172cbbeab4dd149", + "result" : "valid" + }, + { + "tcId" : 316, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "32363633373834323534", + "sig" : "3046022100b5d795cc75cea5c434fa4185180cd6bd21223f3d5a86da6670d71d95680dadbf022100ab1b277ef5ffe134460835e3d1402461ba104cb50b16f397fdc7a9abfefef280", + "result" : "valid" + }, + { + "tcId" : 317, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31363532313030353234", + "sig" : "3044022007dc2478d43c1232a4595608c64426c35510051a631ae6a5a6eb1161e57e42e102204a59ea0fdb72d12165cea3bf1ca86ba97517bd188db3dbd21a5a157850021984", + "result" : "valid" + }, + { + "tcId" : 318, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "35373438303831363936", + "sig" : "3046022100ddd20c4a05596ca868b558839fce9f6511ddd83d1ccb53f82e5269d559a01552022100a46e8cb8d626cf6c00ddedc3b5da7e613ac376445ee260743f06f79054c7d42a", + "result" : "valid" + }, + { + "tcId" : 319, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "36333433393133343638", + "sig" : "30450221009cde6e0ede0a003f02fda0a01b59facfe5dec063318f279ce2de7a9b1062f7b702202886a5b8c679bdf8224c66f908fd6205492cb70b0068d46ae4f33a4149b12a52", + "result" : "valid" + }, + { + "tcId" : 320, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31353431313033353938", + "sig" : "3046022100c5771016d0dd6357143c89f684cd740423502554c0c59aa8c99584f1ff38f609022100ab4bfa0bb88ab99791b9b3ab9c4b02bd2a57ae8dde50b9064063fcf85315cfe5", + "result" : "valid" + }, + { + "tcId" : 321, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3130343738353830313238", + "sig" : "3045022100a24ebc0ec224bd67ae397cbe6fa37b3125adbd34891abe2d7c7356921916dfe6022034f6eb6374731bbbafc4924fb8b0bdcdda49456d724cdae6178d87014cb53d8c", + "result" : "valid" + }, + { + "tcId" : 322, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3130353336323835353638", + "sig" : "304502202557d64a7aee2e0931c012e4fea1cd3a2c334edae68cdeb7158caf21b68e5a2402210080f93244956ffdc568c77d12684f7f004fa92da7e60ae94a1b98c422e23eda34", + "result" : "valid" + }, + { + "tcId" : 323, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "393533393034313035", + "sig" : "3046022100c4f2eccbb6a24350c8466450b9d61b207ee359e037b3dcedb42a3f2e6dd6aeb5022100cd9c394a65d0aa322e391eb76b2a1a687f8620a88adef3a01eb8e4fb05b6477a", + "result" : "valid" + }, + { + "tcId" : 324, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "393738383438303339", + "sig" : "3046022100eff04781c9cbcd162d0a25a6e2ebcca43506c523385cb515d49ea38a1b12fcad022100ea5328ce6b36e56ab87acb0dcfea498bcec1bba86a065268f6eff3c41c4b0c9c", + "result" : "valid" + }, + { + "tcId" : 325, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33363130363732343432", + "sig" : "3046022100f58b4e3110a64bf1b5db97639ee0e5a9c8dfa49dc59b679891f520fdf0584c87022100d32701ae777511624c1f8abbf02b248b04e7a9eb27938f524f3e8828ba40164a", + "result" : "valid" + }, + { + "tcId" : 326, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31303534323430373035", + "sig" : "3045022100f8abecaa4f0c502de4bf5903d48417f786bf92e8ad72fec0bd7fcb7800c0bbe302204c7f9e231076a30b7ae36b0cebe69ccef1cd194f7cce93a5588fd6814f437c0e", + "result" : "valid" + }, + { + "tcId" : 327, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "35313734343438313937", + "sig" : "304402205d5b38bd37ad498b2227a633268a8cca879a5c7c94a4e416bd0a614d09e606d2022012b8d664ea9991062ecbb834e58400e25c46007af84f6007d7f1685443269afe", + "result" : "valid" + }, + { + "tcId" : 328, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31393637353631323531", + "sig" : "304402200c1cd9fe4034f086a2b52d65b9d3834d72aebe7f33dfe8f976da82648177d8e3022013105782e3d0cfe85c2778dec1a848b27ac0ae071aa6da341a9553a946b41e59", + "result" : "valid" + }, + { + "tcId" : 329, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33343437323533333433", + "sig" : "3045022100ae7935fb96ff246b7b5d5662870d1ba587b03d6e1360baf47988b5c02ccc1a5b02205f00c323272083782d4a59f2dfd65e49de0693627016900ef7e61428056664b3", + "result" : "valid" + }, + { + "tcId" : 330, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "333638323634333138", + "sig" : "3045022000a134b5c6ccbcefd4c882b945baeb4933444172795fa6796aae149067547098022100a991b9efa2db276feae1c115c140770901839d87e60e7ec45a2b81cf3b437be6", + "result" : "valid" + }, + { + "tcId" : 331, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33323631313938363038", + "sig" : "304502202e4721363ad3992c139e5a1c26395d2c2d777824aa24fde075e0d7381171309d0221008bf083b6bbe71ecff22baed087d5a77eaeaf726bf14ace2c03fd6e37ba6c26f2", + "result" : "valid" + }, + { + "tcId" : 332, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "39363738373831303934", + "sig" : "304502206852e9d3cd9fe373c2d504877967d365ab1456707b6817a042864694e1960ccf022100f9b4d815ebd4cf77847b37952334d05b2045cb398d4c21ba207922a7a4714d84", + "result" : "valid" + }, + { + "tcId" : 333, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "34393538383233383233", + "sig" : "30440220188a8c5648dc79eace158cf886c62b5468f05fd95f03a7635c5b4c31f09af4c5022036361a0b571a00c6cd5e686ccbfcfa703c4f97e48938346d0c103fdc76dc5867", + "result" : "valid" + }, + { + "tcId" : 334, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "383234363337383337", + "sig" : "3045022100a74f1fb9a8263f62fc4416a5b7d584f4206f3996bb91f6fc8e73b9e92bad0e1302206815032e8c7d76c3ab06a86f33249ce9940148cb36d1f417c2e992e801afa3fa", + "result" : "valid" + }, + { + "tcId" : 335, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3131303230383333373736", + "sig" : "3045022007244865b72ff37e62e3146f0dc14682badd7197799135f0b00ade7671742bfe022100f27f3ddc7124b1b58579573a835650e7a8bad5eeb96e9da215cd7bf9a2a039ed", + "result" : "valid" + }, + { + "tcId" : 336, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "313333383731363438", + "sig" : "3045022100da7fdd05b5badabd619d805c4ee7d9a84f84ddd5cf9c5bf4d4338140d689ef08022028f1cf4fa1c3c5862cfa149c0013cf5fe6cf5076cae000511063e7de25bb38e5", + "result" : "valid" + }, + { + "tcId" : 337, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "333232313434313632", + "sig" : "3046022100d3027c656f6d4fdfd8ede22093e3c303b0133c340d615e7756f6253aea927238022100f6510f9f371b31068d68bfeeaa720eb9bbdc8040145fcf88d4e0b58de0777d2a", + "result" : "valid" + }, + { + "tcId" : 338, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3130363836363535353436", + "sig" : "304402200bf6c0188dc9571cd0e21eecac5fbb19d2434988e9cc10244593ef3a98099f6902204864a562661f9221ec88e3dd0bc2f6e27ac128c30cc1a80f79ec670a22b042ee", + "result" : "valid" + }, + { + "tcId" : 339, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "3632313535323436", + "sig" : "3045022100ae459640d5d1179be47a47fa538e16d94ddea5585e7a244804a51742c686443a02206c8e30e530a634fae80b3ceb062978b39edbe19777e0a24553b68886181fd897", + "result" : "valid" + }, + { + "tcId" : 340, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "37303330383138373734", + "sig" : "304402201cf3517ba3bf2ab8b9ead4ebb6e866cb88a1deacb6a785d3b63b483ca02ac4950220249a798b73606f55f5f1c70de67cb1a0cff95d7dc50b3a617df861bad3c6b1c9", + "result" : "valid" + }, + { + "tcId" : 341, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "35393234353233373434", + "sig" : "3045022100e69b5238265ea35d77e4dd172288d8cea19810a10292617d5976519dc5757cb802204b03c5bc47e826bdb27328abd38d3056d77476b2130f3df6ec4891af08ba1e29", + "result" : "valid" + }, + { + "tcId" : 342, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31343935353836363231", + "sig" : "304402205f9d7d7c870d085fc1d49fff69e4a275812800d2cf8973e7325866cb40fa2b6f02206d1f5491d9f717a597a15fd540406486d76a44697b3f0d9d6dcef6669f8a0a56", + "result" : "valid" + }, + { + "tcId" : 343, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "34303035333134343036", + "sig" : "304402200a7d5b1959f71df9f817146ee49bd5c89b431e7993e2fdecab6858957da685ae02200f8aad2d254690bdc13f34a4fec44a02fd745a422df05ccbb54635a8b86b9609", + "result" : "valid" + }, + { + "tcId" : 344, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "33303936343537353132", + "sig" : "3044022079e88bf576b74bc07ca142395fda28f03d3d5e640b0b4ff0752c6d94cd553408022032cea05bd2d706c8f6036a507e2ab7766004f0904e2e5c5862749c0073245d6a", + "result" : "valid" + }, + { + "tcId" : 345, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "32373834303235363230", + "sig" : "30450221009d54e037a00212b377bc8874798b8da080564bbdf7e07591b861285809d01488022018b4e557667a82bd95965f0706f81a29243fbdd86968a7ebeb43069db3b18c7f", + "result" : "valid" + }, + { + "tcId" : 346, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "32363138373837343138", + "sig" : "304402202664f1ffa982fedbcc7cab1b8bc6e2cb420218d2a6077ad08e591ba9feab33bd022049f5c7cb515e83872a3d41b4cdb85f242ad9d61a5bfc01debfbb52c6c84ba728", + "result" : "valid" + }, + { + "tcId" : 347, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "31363432363235323632", + "sig" : "304502205827518344844fd6a7de73cbb0a6befdea7b13d2dee4475317f0f18ffc81524b022100b0a334b1f4b774a5a289f553224d286d239ef8a90929ed2d91423e024eb7fa66", + "result" : "valid" + }, + { + "tcId" : 348, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "36383234313839343336", + "sig" : "304602210097ab19bd139cac319325869218b1bce111875d63fb12098a04b0cd59b6fdd3a3022100bce26315c5dbc7b8cfc31425a9b89bccea7aa9477d711a4d377f833dcc28f820", + "result" : "valid" + }, + { + "tcId" : 349, + "comment" : "special case hash", + "flags" : [ + "SpecialCaseHash" + ], + "msg" : "343834323435343235", + "sig" : "3044022052c683144e44119ae2013749d4964ef67509278f6d38ba869adcfa69970e123d02203479910167408f45bda420a626ec9c4ec711c1274be092198b4187c018b562ca", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", + "wx" : "07310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc362", + "wy" : "26a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEBzEPkKnq4UmghAL1QZSg97SsQnv42b1s\ndoEHHcR9w2ImptN6xG1h/WAMC/G/+HaJ7RF92msOWTGK4BChl6JsoA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 350, + "comment" : "k*G has a large x-coordinate", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "30360211014551231950b75fc4402da1722fc9baeb022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result" : "valid" + }, + { + "tcId" : 351, + "comment" : "r too large", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", + "wx" : "00bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22", + "wy" : "705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvJfnWF7srUjhZoO8QJFwjhqTDGg/xHAB\n1LODWU8sTiJwWYnPadrq3U5OS4FR7YiN/sIPsBco2J1Ws/OPKunIxQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 352, + "comment" : "r,s are large", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", + "wx" : "44ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252", + "wy" : "00b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERK0zmvvCHpq/e2AqXKU16jeBNbbRDYEx\nC92Ck9HfMlK2P/fQd0dw+P4dFyL6g6zQL0NOT8EQoMyPbd3TfVbEYw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 353, + "comment" : "r and s^-1 have a large Hamming weight", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203e9a7582886089c62fb840cf3b83061cd1cff3ae4341808bb5bdee6191174177", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", + "wx" : "1260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c", + "wy" : "5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT\n7rrSHzfdh4xcmgwamt52c3qIEb1qf5KHyXjuOWqonBHkcinSzLVS8A==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 354, + "comment" : "r and s^-1 have a large Hamming weight", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022024238e70b431b1a64efdf9032669939d4b77f249503fc6905feb7540dea3e6d2", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", + "wx" : "1877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce", + "wy" : "00821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGHcEW+JdNKHQYA+dXADQZFoqVDebbO76\n0ua/XCozUs6CGlMswXUe4dNtQcPWq06bFD5E7EbXNHjqanmlwOVBWQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 355, + "comment" : "small r and s", + "flags" : [ + "SmallRandS", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3006020101020101", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", + "wx" : "455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50", + "wy" : "00aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERVQ5/MPS3uzt3q7OYOe9FzBPNuu2Aq31\noi4Ljx20alCuw4+yuvIh6ajRiHx79iIt0YNGNOdyYzFa9tI2CdBPdw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 356, + "comment" : "small r and s", + "flags" : [ + "SmallRandS", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3006020101020102", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", + "wx" : "2e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece718", + "wy" : "0449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELh9GawJMDDrOJDfeCRJ/7QS3BvlLGaIb\nscKs81zs5xgESa41I9clNOlklyz9OzivC93ZYZ5a8iPk0aQPNM+fHQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 357, + "comment" : "small r and s", + "flags" : [ + "SmallRandS", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3006020101020103", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", + "wx" : "008e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a23373", + "wy" : "26ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjnq9u9GN50UjdMGHmhw7AdEyYefUVxw7\nR6HHbFWiM3Mm7Yl81Rek9TSduAl4D20vK59imdi1qJB38RGacY/Xsw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 358, + "comment" : "small r and s", + "flags" : [ + "SmallRandS", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3006020102020101", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", + "wx" : "7b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af19", + "wy" : "42117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEezM9Q0DT1xjdPmr/fee7+Lcr/WFshCAF\nYFKEI3a5rxlCEXxa/qx1XW83b8Yymn12BRuHEjpKXQvEpTk4DwPeew==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 359, + "comment" : "small r and s", + "flags" : [ + "SmallRandS", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3006020102020102", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", + "wx" : "00d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e5", + "wy" : "03a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0wykoN22YWyFHTDO1oLED4PGJ1ih8nWZ\niNZ2OojxwOUDqA1UFWUNQSOXhOji+xI16f6ZHREuu4EYbL8Not46/w==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 360, + "comment" : "small r and s", + "flags" : [ + "SmallRandS", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3006020102020103", + "result" : "valid" + }, + { + "tcId" : 361, + "comment" : "r is larger than n", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143020103", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", + "wx" : "48969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24", + "wy" : "00b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESJabOZkSl7MyplLT7m4B6QmzmQTnH6I1\nSngwx3ULryS0AS0bgw0ZnMsfyXKzK/3tVfCc1i0lfl6ETiflehWU7A==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 362, + "comment" : "s is larger than n", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3026020102022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd04917c8", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", + "wx" : "02ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee77", + "wy" : "7eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAu9NbWz9WpTx13hCJuPipsCkNsVYOWGf\nOPtEcrX57nd+tKzU7r2lzXKHX/0qLyYinC3GtGUAkZpDLIZznzroZg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 363, + "comment" : "small r and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "302702020101022100c58b162c58b162c58b162c58b162c58a1b242973853e16db75c8a1a71da4d39d", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", + "wx" : "464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584", + "wy" : "00b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERk9P9xVynK5Qcso72AHTGVtnrsZemwGq\n0gopQ9y8tYSxr9KdMaOaEdVwqhWXQ5s7LRlxvy8avxVDLQIHsQ0dCA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 364, + "comment" : "smallish r and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "302c02072d9b4d347952cc022100fcbc5103d0da267477d1791461cf2aa44bf9d43198f79507bd8779d69a13108e", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", + "wx" : "157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4c", + "wy" : "00deadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFX+P3fNz619Jz88Q2LhTz5HLzX1mXDUi\nun3XON23mkzerfGlxEjqPJ9BkaiZmr/MdXrG1kVn7wcsR/7GE0Q7jw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 365, + "comment" : "100-bit r and small s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3032020d1033e67e37b32b445580bf4efc022100906f906f906f906f906f906f906f906ed8e426f7b1968c35a204236a579723d2", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", + "wx" : "0934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0", + "wy" : "00d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECTSlN0ZsB0MOLEj+uZC7Gft4zsyc7kJO\npNEwKRqiN/DU+S0jtGKAS1toxSVYwByZltv3J/zKu+7bliGkAFNa+g==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 366, + "comment" : "small r and 100 bit s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3026020201010220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", + "wx" : "00d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c65", + "wy" : "4a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1u8gvmbIk/dBqb+Q2bdGddHCoxKWOXrL\nPvF0/QswDGVKDJVHjKADmRYtfw8tyJ79wrKKMPur4oWFcpWksMTiZQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 367, + "comment" : "100-bit r and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3031020d062522bbd3ecbe7c39e93e7c260220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", + "wx" : "00b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee06", + "wy" : "29c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEtykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5U\nTZUUVFup7gYpyaY9XjCHacww7CdqQQ5kZKJ+6v2eWZ2xDwU6T+SoKQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 368, + "comment" : "r and s^-1 are close to n", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c1022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", + "wx" : "6e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8", + "wy" : "186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbigwMwXWQsy5I7ci6oayoLyONzXssm6E\nmxnJ92sv27gYboDWTYyrFk9SOPUxhGG/idTZbuZUTIFsdWaUd3Tg9g==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 369, + "comment" : "r and s are 64-bit integer", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "30160209009c44febf31c3594d020900839ed28247c2b06b", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", + "wx" : "375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9", + "wy" : "00a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEN1vak/avkvtfj0sbXwU047r6s0y3rZ+5\n0Lci5KXDAqmgC584elo5YJeqIWL8W7z0pSYzcvaByU2lHpeZEgmQ/Q==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 370, + "comment" : "r and s are 100-bit integer", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "301e020d09df8b682430beef6f5fd7c7cf020d0fd0a62e13778f4222a0d61c8a", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", + "wx" : "00d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197", + "wy" : "00da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE11toIWur4DriV+lLTjvxxS9E498mbRUk\n/4xepp2nMZfaS/+e0cU/RJF6Z9e5eFmOid81nj1ZE+rqJPOuJZq8RA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 371, + "comment" : "r and s are 128-bit integer", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "30260211008a598e563a89f526c32ebec8de26367a02110084f633e2042630e99dd0f1e16f7a04bf", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", + "wx" : "78bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653", + "wy" : "118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeLzaFArtI9QwyyPD3A0B9CPbE07pSjqM\ntIPy3qwqxlMRgRT28zBF1OntkQcIUAe/vd+PWP56GiRF1mqZAEVHbg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 372, + "comment" : "r and s are 160-bit integer", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "302e021500aa6eeb5823f7fa31b466bb473797f0d0314c0bdf021500e2977c479e6d25703cebbc6bd561938cc9d1bfb9", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", + "wx" : "00bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c", + "wy" : "1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEu3n2GFf3Q7+htucRHOQJQ3claWnk4VFZ\nEj2VSKzDvmwfnZ+IYNz/0+s23Wwx/y5yJsIAnEyU2NfStWhr96vWdw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 373, + "comment" : "s == 1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020101", + "result" : "valid" + }, + { + "tcId" : 374, + "comment" : "s == 0", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020100", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", + "wx" : "0093591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36", + "wy" : "073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEk1kYJ9nmcTtOn66mLHKyjf76aODAUWC1\n1qroj9LjbDYHP1VFrVr0EK8mr/9oZUz3LUXkk0iTESAyRzR6iQ9FGA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 375, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220419d981c515af8cc82545aac0c85e9e308fbb2eab6acd7ed497e0b4145a18fd9", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", + "wx" : "31ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0da", + "wy" : "00da01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMe0wga7+AB62QCBp7izMGGKTe4WZUUTb\nqVA5Q1h78NraAbjMTfNPWrOxo1lhUgiUbl7jX5jud1uMzs2GzMFlDw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 376, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102201b21717ad71d23bbac60a9ad0baf75b063c9fdf52a00ebf99d022172910993c9", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", + "wx" : "7dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea8", + "wy" : "54c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEff9m+phQn/Pi5RBF9DkFI9zNpDo7wohe\nWMJICQmQ7qhUx2wrmt62u1cYI+B/18ZchjnPnZBSYAZMjnZ1zm2YtA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 377, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102202f588f66018f3dd14db3e28e77996487e32486b521ed8e5a20f06591951777e9", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", + "wx" : "4280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a", + "wy" : "2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEQoBQmqtk7fwLSiln5MvOhJy1ROSncxPI\n5uzlefvXQgouif5cwZJ9VU5qO7FAM+p8kizXXLosdBX9q1LyCxhg8Q==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 378, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220091a08870ff4daf9123b30c20e8c4fc8505758dcf4074fcaff2170c9bfcf74f4", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", + "wx" : "4f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb", + "wy" : "2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAET43xRRlOPE/D7qJtQ851tALWsXRy3cuy\nVLinmwvz2csqog2ChEyyZjROccp48q0np1oJ5bwPpX5O/Z1GWgiI2w==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 379, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102207c370dc0ce8c59a8b273cba44a7c1191fc3186dc03cab96b0567312df0d0b250", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", + "wx" : "009598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14", + "wy" : "122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElZilfdZ+w+FrWHoziqOhCjo5E7QaOvMu\nPtP/ATWMaxQSKBnt+AdLvFIffUzc6C/velFnBq/7odk9neqcyuGiBw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 380, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022070b59a7d1ee77a2f9e0491c2a7cfcd0ed04df4a35192f6132dcc668c79a6160e", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", + "wx" : "009171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e", + "wy" : "634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkXH+w8oggGvAhPEvB2CRG2CZC9gOWypx\nygOgSLIPg35jT9F4Y3YbKVjSvk4Un409ervcGL4D9FGrbBf6Ch+DMA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 381, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102202736d76e412246e097148e2bf62915614eb7c428913a58eb5e9cd4674a9423de", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", + "wx" : "777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9", + "wy" : "00ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEd3yJMLbh0nEQD+aM6T8WP6N2EsX/9n9K\nYvw7r689F6ntc9hvYKUbXtkTU6OwVO3AqpLJ68vQt10Yj9yIJ5HWjQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 382, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102204a1e12831fbe93627b02d6e7f24bccdd6ef4b2d0f46739eaf3b1eaf0ca117770", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", + "wx" : "00eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf470", + "wy" : "0603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE6rwkj2JuCmPh64HEPUYaOaHbqIHrbuIV\nKwfDLXG89HAGA8qoudM9sTr0TG777IoZjtYSSsnrF+qv0oJKVF7AAA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 383, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022006c778d4dfff7dee06ed88bc4e0ed34fc553aad67caf796f2a1c6487c1b2e877", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", + "wx" : "009f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001", + "wy" : "00f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEn3oTraFYpV+d3xpF8ETwc9m4ADDv3Pyf\nn1hBj7zq8AH4raAXUJD4DUcifWcTtnQPmgCR2IqDfQoc13tYqPKNcw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 384, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102204de459ef9159afa057feb3ec40fef01c45b809f4ab296ea48c206d4249a2b451", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", + "wx" : "11c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4db", + "wy" : "00bbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEcTz5GHNAZtcBuoM6kxAkMPMPjxdnzxt\nZbQ2gm2ptNu763p35Mv9ogcJfENCNwX3LIBHbaPaxApIOwqw8urRyw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 385, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220745d294978007302033502e1acc48b63ae6500be43adbea1b258d6b423dbb416", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", + "wx" : "00e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4", + "wy" : "161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE4uGGgtUxI6oBpsXQCwxiPWcbRi6oC93W\nUif9UQWYiqQWGQez/SUESpSepByOLqhFncbxZUhWuLYbMVQ7sbRb2w==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 386, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102207b2a785e3896f59b2d69da57648e80ad3c133a750a2847fd2098ccd902042b6c", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", + "wx" : "0090f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197da", + "wy" : "00fadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkPjUynPeCKZWSq8AUke28P/peFBNzlJg\nX0a3w+Vhl9r62+Uo63DZ7n6g5wcC21T3IVFMe4YErCyyFPHey344PQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 387, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022071ae94a72ca896875e7aa4a4c3d29afdb4b35b6996273e63c47ac519256c5eb1", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", + "wx" : "00824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e", + "wy" : "3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEgkwZXHPP/fA40QG84Wh7XDthRvOVyIWX\nb3dTsjdrlI483vpvw0fRPk3LxjoLA6FlGAzSvhQxoM90zh6iUILSvA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 388, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102200fa527fa7343c0bc9ec35a6278bfbff4d83301b154fc4bd14aee7eb93445b5f9", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", + "wx" : "2788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f", + "wy" : "30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJ4ilLweOs/ICxPpz4NM4b6899r6FYANj\nb1mZItT1Jo8wtPIHyRm7315nqL5CZagXR1Szq6jxbldbd/9NWn62Tw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 389, + "comment" : "edge case modular inverse", + "flags" : [ + "ModularInverse", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102206539c0adadd0525ff42622164ce9314348bd0863b4c80e936b23ca0414264671", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", + "wx" : "00d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b4150874", + "wy" : "01b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1TO3iaSviQ+nqCofrljEBPmmKlC0mtr6\ns0nFE7QVCHQBtBcbgD52s0qYYeEPe8KJoGb9Ab0p+EyYehCl+xjC1A==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 390, + "comment" : "point at infinity during verify", + "flags" : [ + "PointDuplication", + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", + "wx" : "3a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4", + "wy" : "221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOjFQeYyK9p0ebpgfOkVAK6HXMvS+gzDF\nFk9J4Q7FVbQiG9hCvF5Nl+/zcWX2DjmYpCTXKkUM+V6kd8eCh9A0Og==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 391, + "comment" : "edge case for signature malleability", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", + "wx" : "3b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e80", + "wy" : "0de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9\nD8/IEB6FHoAN48CQtsohulQ1FzMMBLEvlIxrrfFKY6v/3074x1NwJg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 392, + "comment" : "edge case for signature malleability", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", + "wx" : "00feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82c", + "wy" : "00e87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/rUWOw7OMP8+A8fVXEOA+i+oHuLANUlC\n/28IyZ0M2CzofeBe4b2gidPk4kj6D3IRAqz//fUOZUvigUM5md+Jfg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 393, + "comment" : "u1 == 1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", + "wx" : "238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd4149228976", + "wy" : "40683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEI4ztABzyK4hT4C7cicvspQULp+BCp6d/\nk4LNQUkiiXZAaD0wlGQ4QPKViQqkwYqjm0HXfdD7O7JwDk+ewoT/wg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 394, + "comment" : "u1 == n - 1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", + "wx" : "00961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35e", + "wy" : "00d2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElhz2SBfAbA5Rs8JzbJIv3hi9jEkG/Nf1\n72bEZ4UI817SxdGBaM++cPLxI710GSMruS3WkRPilBBhiJSBxaAnvw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 395, + "comment" : "u2 == 1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", + "wx" : "13681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b10288", + "wy" : "16528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEE2gerhaM1Op88uKkXQUnQtEKn2TnloZ9\nvcuCn+CxAogWUodg0Xc3bAnfed45VXwynMF1NRes/+j6LsKYAmuDhA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 396, + "comment" : "u2 == n - 1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b89", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", + "wx" : "5aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c2", + "wy" : "0091c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWqer/ba0CG1UMyXl15xulc5C+GbSu4SQ\nljOgS7GqMcKRyACIeUkF4dozM22HTi+RzPRcxZGFvt5d1vP3rKrhiw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 397, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e91e1ba6ba898620a46bcb51dc0b8b4ad1dc35dad892c4552d1847b2ce444637", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", + "wx" : "277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e4", + "wy" : "64108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtU\nASDg9cIGw+RkEIIz+wuMOsiS15744Pv5LtEzrdtFVCcBMlhNxS7vQQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 398, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e36bf0cec06d9b841da81332812f74f30bbaec9f202319206c6f0b8a0a400ff7", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", + "wx" : "6efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1a", + "wy" : "00c75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbvoJK2jelGDwvMkZAFpfboDhnemJaL48\n0sdwqZSb+xrHXm5Qh9ZVDV+b6x555QKTB7wlUjXi1dyZJBrDq4hsSQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 399, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ea26b57af884b6c06e348efe139c1e4e9ec9518d60c340f6bac7d278ca08d8a6", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", + "wx" : "72d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058", + "wy" : "00e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEctShnE+dLPWEjqQERbcNRpa18C1jLAxl\nTMfX7rDG0FjoxM2ZQ+RZF0x6wB+nQhmOR+bBmmvbDE9sI3gxwbP5Qg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 400, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205b1d27a7694c146244a5ad0bd0636d9d9ef3b9fb58385418d9c982105077d1b7", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", + "wx" : "2a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e7402", + "wy" : "58f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKo6i9Q3M7QwhdXW9+nzUfRxvEABB7A41\nUSeUwb5+dAJY+MFxIu0wP9pxQ+tYvt5wKVtlMmYBOwsOvT8FMTf27A==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 401, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d27a7694c146244a5ad0bd0636d9e12abe687897e8e9998ddbd4e59a78520d0f", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", + "wx" : "0088de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b8", + "wy" : "0c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiN5onOmvHpS+aiCJyKixJT/9u2yOnIYk\nm6IgABpK07gMSZjlSEL0E7ntsYJay7YzXoHk0YSysByL69yF0fKJRg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 402, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100a4f4ed29828c4894b5a17a0c6db3c256c2221449228a92dff7d76ca8206dd8dd", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", + "wx" : "00fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7", + "wy" : "00b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/qLTH3D5DV+z4A4YasQqs8FhXO5xTgtO\nETGz1NgiW/ewN6GN8qwVND8w90Bn3fKegX1fd/jc4FcU2lnAlPDNqQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 403, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220694c146244a5ad0bd0636d9e12bc9e09e60e68b90d0b5e6c5dddd0cb694d8799", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", + "wx" : "7258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db", + "wy" : "17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDt\nzLNrbO6lo9sXrCuJknkRKPo7ltwvvUyjv6eC7ygy/GZWlD2xjnNGsA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 404, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203d7f487c07bfc5f30846938a3dcef696444707cf9677254a92b06c63ab867d22", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", + "wx" : "4f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914", + "wy" : "00c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyhGHepkR01rs00Umcl9N7npVjPfHO7q\nrNRQFsmLORTIgYgQuMwG3bQOihJhxSj6pYlFXVpt+Tt3vF4OSTx0cA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 405, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206c7648fc0fbf8a06adb8b839f97b4ff7a800f11b1e37c593b261394599792ba4", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", + "wx" : "74f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66", + "wy" : "00eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEdPKoFPtdjsqRppteYHEnMrOTfeMoKb6X\nTte2jFwvXWbv8PB8VvmHplf0IZYgX1iMDx2W/YpjpfI4tI9Hh4j+Ow==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 406, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0221009be363a286f23f6322c205449d320baad417953ecb70f6214e90d49d7d1f26a8", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", + "wx" : "195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6a", + "wy" : "00b2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGVtRp8xKIbgnSnCpDed5gUw8jKNYMoII\nwJop8za4LWqyQWt8kv/9wpw7EoLdKnek0E3390UgRzk9hJmJxc7prQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 407, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022029798c5c45bdf58b4a7b2fdc2c46ab4af1218c7eeb9f0f27a88f1267674de3b0", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", + "wx" : "622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa", + "wy" : "736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYi/HRzIDS+wt3zvBbTSz0fejJ90qjBm6\ntLtP46JLWKpzay8vrnb0367MkJYzOwEyjVHrP9qckifpDQtEmYPE8A==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 408, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02200b70f22ca2bb3cefadca1a5711fa3a59f4695385eb5aedf3495d0b6d00f8fd85", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", + "wx" : "1f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c7", + "wy" : "0827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH3+FyvLXVQ56+bZQI+u03ONFAxFpIwnb\nJplpuDS2EccIJ/RbeAIOy7r0hP3Vv6rmhw8RhMIVgbr274K9e1MPkw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 409, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022016e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", + "wx" : "49c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377a", + "wy" : "00efc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEScGX3ICtHaR6Q0K5OJPo4fsLuU/DOoPn\ng8ALJMeBN3rvwg2pK6x2KVH3JHS+zHNNTMIrqBuJXigv2sTfevDzfQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 410, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202252d685e831b6cf095e4f0535eeaf0ddd3bfa91c210c9d9dc17224702eaf88f", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", + "wx" : "00d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe", + "wy" : "7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2MtoUXthalZACqOGhjXlS29plZii9hZ3\nV2VJgLr2rL5+yM9EnISaoDRhow762kFFPFfG5vvJO7xvpJrabcBVXA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 411, + "comment" : "edge case for u1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022075135abd7c425b60371a477f09ce0f274f64a8c6b061a07b5d63e93c65046c53", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", + "wx" : "030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3", + "wy" : "00b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAwcT+2Pyqm/iyt8bIO/CWcd0Rdr6h9rD\nmLhAZco0ffOyJ4GN4aObWJywcdg+UxfMzcIzjlHjEv4x2Nw0pIAXUA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 412, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d55555555555555555555555555555547c74934474db157d2a8c3f088aced62a", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", + "wx" : "00babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7", + "wy" : "252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEurs2d7CVWALY6SmkE1VkDq8eoTU/incT\nMcSUbjSAr6clLxlsh+09KlnTsbVZE3/tABP+zvwZ+1qSaCubylG5UA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 413, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100c1777c8853938e536213c02464a936000ba1e21c0fc62075d46c624e23b52f31", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", + "wx" : "1aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60", + "wy" : "00bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGqsgGHk0cREaig6bFD/eAvyVkgeW06Y9\n4ym0JDlvumC75BMHBRdHkkQbMY06ox3+hXeCHptEbsVz0nLgNsTr6Q==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 414, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022030bbb794db588363b40679f6c182a50d3ce9679acdd3ffbe36d7813dacbdc818", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", + "wx" : "008cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff", + "wy" : "47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjLC5CUmcg+qAbNiFsd1GegEZ8GqIoCdu\nsM/aJ0U1qP9HtUKIM7w/LIv52QQRWM8zcYpplhzQFym8ABHR5YardQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 415, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202c37fd995622c4fb7fffffffffffffffc7cee745110cb45ab558ed7c90c15a2f", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", + "wx" : "008f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d", + "wy" : "3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjwPPGkInK7FTJyMJP3Lm/urIXhcA6fvp\npqLdZC10v107iacYna2M91/CL28ViqJ/nCygDaynhb4zWPK9o4YsoA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 416, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02207fd995622c4fb7ffffffffffffffffff5d883ffab5b32652ccdcaa290fccb97d", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", + "wx" : "44de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8ace", + "wy" : "00a2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERN47nHpXqMnoIJUnU0IefZh7s9efcfAT\ngFyJfgGPis6iRgdYyPmNP9zhIalDZZ43LDJv/y5fwq5/o/edquE8Eg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 417, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ffb32ac4589f6ffffffffffffffffffebb107ff56b664ca599b954521f9972fa", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", + "wx" : "6fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a", + "wy" : "0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEb7iytI4zAxJorWpRdITciDnqkPZmnqDH\nrDIz4qwxOUoKyLvn9zwv9N+ZeHJ6wd/C/VhkfSDzH5kQUxa2RnHyBA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 418, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205622c4fb7fffffffffffffffffffffff928a8f1c7ac7bec1808b9f61c01ec327", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", + "wx" : "00bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6", + "wy" : "00f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvqcRIqBIaT6QX/YCs8+d0Yr2m5/J2EMd\nKx3Sa5Qsleb0PHuLletiCCwS2529p/445Fy+SkiGkH+4G9sMXqkkbA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 419, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022044104104104104104104104104104103b87853fd3b7d3f8e175125b4382f25ed", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", + "wx" : "00da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156", + "wy" : "00e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2pGMcxugaiDLlO8zt3jpgaQEowXxlB/j\nNma0WwM1MVbiuyaU9XW0UYO+eOXJtSEL879Ij9TIKUUW2JVyyk9TkQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 420, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202739ce739ce739ce739ce739ce739ce705560298d1f2f08dc419ac273a5b54d9", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", + "wx" : "3007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d", + "wy" : "5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMAfpLDk32t55ZN+jWw7/Ax9+sCrtCgMU\nQREGzetw/j1adUb8BVKZeyDj1vQT514stm4RYyJpcRS3m6xzS/xNxQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 421, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100b777777777777777777777777777777688e6a1fe808a97a348671222ff16b863", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", + "wx" : "60e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9b", + "wy" : "00d2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ\n/fmNvc0YzpvS2Qs6wx8TmvgyzM9sy7ssbqEfqXNw3JkG2kdNfYp1Zw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 422, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206492492492492492492492492492492406dd3a19b8d5fb875235963c593bd2d3", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", + "wx" : "0085a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba337", + "wy" : "69744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEhakA6XhY9pPAt9+iYeOA2tbqBG0fZd3u\n7dX32K8LozdpdE0VrdT2wLw7DaKuyTs0y4xl+TQN33TnsACe7szOPA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 423, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100955555555555555555555555555555547c74934474db157d2a8c3f088aced62c", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", + "wx" : "38066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046", + "wy" : "00a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOAZvddiO/EyT3jb0ngN7I0zBix3lYIdQ\npiyrA0VAEEaj6EvtjPy4Ge9NVQRE8s5LZRdmtp4uKQH4iDb/kANP7Q==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 424, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", + "wx" : "0098f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabf", + "wy" : "00a33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmPaBd9yVwbTL+lJFSIylI6fVYpRw0DXW\nIaRDxy85qr+jPSlUb6HGSPLH1cz3DPHOSrebXbGsBZ2+zQaNvf8biQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 425, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100bffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", + "wx" : "5c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277", + "wy" : "00e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEXCu/ojybmtB/A4qom0kwvyZ9lAHkJV3p\n6NoKUHjsgnfj6IKjHV5qN54Hk5g8ze05uVxDU6sv8B6lNpukewwxkQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 426, + "comment" : "edge case for u2", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220185ddbca6dac41b1da033cfb60c152869e74b3cd66e9ffdf1b6bc09ed65ee40c", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", + "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", + "wy" : "3547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4U1R4CCmESO215wGt6EzV+xrJVnul6Ptoprkz7EtcyEzA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 427, + "comment" : "point duplication during verification", + "flags" : [ + "PointDuplication" + ], + "msg" : "313233343030", + "sig" : "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", + "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", + "wy" : "00cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4XKuH99Z7txJKGP5SF7MqBOU2qYRaFwSXWUbME6SjN3Yw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 428, + "comment" : "duplication bug", + "flags" : [ + "PointDuplication" + ], + "msg" : "313233343030", + "sig" : "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", + "wx" : "008aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e", + "wy" : "1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiqLGT6nGQ3Vjq/vL0AsgSNSMGMFSoqb0\nkDbedkfr6C4c5kOHmVxooGD6O8A5mwXMBu7H1Zj3UEGkkX5pK39R/w==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 429, + "comment" : "comparison with point at infinity ", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0022033333333333333333333333333333332f222f8faefdb533f265d461c29a47373", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", + "wx" : "391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71f", + "wy" : "00dd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEORQn/37ngBPBSux9lqigYiCSmKeDg16U\n/WVJ1QL/9x/dZiTsNDrZ/PTZhyGB5Z+EL5ukzMrgmmwJcvtqxrTGvQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 430, + "comment" : "extreme value for k and edgecase s", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", + "wx" : "00e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138e", + "wy" : "00c1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4\nnHo0uJ6ME47BUz7wQZu3N24L/ekxnRCgaWh5HZ6g7tnBzmNFrtl1ng==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 431, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", + "wx" : "009aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952", + "wy" : "00fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmu2w0oHbFk4TAADFaX+uDzBe+Ei+b/+0\nOsWT+7lQ6VL6b2MzWb3NgrVrC5+WWwN3idRrmoFBt5GyrvpxP5bBdQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 432, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", + "wx" : "008ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee", + "wy" : "1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEitRF22KBYmDk5of9GITki5/AY20DFUfW\nMxXnkuGb+u4d5k+Z1fHNi27Jyw94emVK6GmTuj2xAI70PP8GhMsivQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 433, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", + "wx" : "1f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32", + "wy" : "00e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH1eZyVvokGOyTybkDLkowahop2+wCUYH\n6AQ9tAnJHDLnVyToE6QZHjqDkAfwji6Jc4iwbUoA3m3mDlNtkfq1Zg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 434, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", + "wx" : "00a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc", + "wy" : "28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEozMaThtCI+wsAn7dSCySihTtNY2T8dQh\nfTmr9p/LXMwo1oTSqqvNY4N3XKpiOd4m1MaTe7YD7LQZYIL0z/1QnQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 435, + "comment" : "extreme value for k", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", + "wx" : "3f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb24818", + "wy" : "5ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPzlSGZd0x885s4tmyxBCpiYNhoCAOEXk\n1DOtujuySBhepJW2jLx+1Bc+5jyQQtxQJiXH634h+wLKmpEU4KOhjQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 436, + "comment" : "extreme value for k and edgecase s", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", + "wx" : "00cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e", + "wy" : "054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzfuMD0IuFE4TfCQSyGwXH1/j+j9bu1RO\nkHYojzzteG4FT9ByG3fBHHm+rLPJQhGwoZvaCGUu/q+SUTo7ChY2mA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 437, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", + "wx" : "73598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3", + "wy" : "00cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc1mKahxoJ4+mv9DOQGTmgjW8HA9rIKko\nEIvjNnMPh+PLrmElGbUDLsyFrtgRJxqV/nk51dNGAUC6MY9NFKujHQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 438, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", + "wx" : "58debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a1", + "wy" : "6773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWN69mn7iydWRMkeKVECuTV1+1Dcwg2n5\nLqhsghg/EKFnc+dvXtv02g5PG9/6wPVyV+HfpGWEKTEwmiQkX9pqXQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 439, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", + "wx" : "008b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b", + "wy" : "00950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEi5BN5HlnNAxfjDVypyCSTvdXhjf+qxlJ\nrLJBpaasP1uVCQRJb5gksdY/MxO64huJ+uia/fyBG17OA/1aowGGTw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 440, + "comment" : "extreme value for k and s^-1", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", + "wx" : "00f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a", + "wy" : "346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9IkrbVJcdx4DXyolJwjzeE5II4YEtPlN\nxW6qHlRtlBo0axqgvOaLHFDltS9Qn7VSLlwl4Ci8j4Y0Au23vK2LGw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 441, + "comment" : "extreme value for k", + "flags" : [ + "ArithmeticError" + ], + "msg" : "313233343030", + "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "wy" : "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuA==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 442, + "comment" : "public key shares x-coordinate with generator", + "flags" : [ + "PointDuplication" + ], + "msg" : "313233343030", + "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result" : "invalid" + }, + { + "tcId" : 443, + "comment" : "public key shares x-coordinate with generator", + "flags" : [ + "PointDuplication" + ], + "msg" : "313233343030", + "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", + "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "wy" : "00b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5i3xSWI2Vw7mqJbBAPx7vdXAuhLt1l6q+ZjuC9vBO8ndw==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 444, + "comment" : "public key shares x-coordinate with generator", + "flags" : [ + "PointDuplication" + ], + "msg" : "313233343030", + "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result" : "invalid" + }, + { + "tcId" : 445, + "comment" : "public key shares x-coordinate with generator", + "flags" : [ + "PointDuplication" + ], + "msg" : "313233343030", + "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result" : "invalid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", + "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", + "wy" : "01060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv8AAAABBgSS1aVnPg8l2NUPt+WMSdhtRtQhaVXgqj1A4Q==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 446, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "304402206d6a4f556ccce154e7fb9f19e76c3deca13d59cc2aeb4ecad968aab2ded45965022053b9fa74803ede0fc4441bf683d56c564d3e274e09ccf47390badd1471c05fb7", + "result" : "valid" + }, + { + "tcId" : 447, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100aad503de9b9fd66b948e9acf596f0a0e65e700b28b26ec56e6e45e846489b3c4022100fff223c5d0765447e8447a3f9d31fd0696e89d244422022ff61a110b2a8c2f04", + "result" : "valid" + }, + { + "tcId" : 448, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "30460221009182cebd3bb8ab572e167174397209ef4b1d439af3b200cdf003620089e43225022100abb88367d15fe62d1efffb6803da03109ee22e90bc9c78e8b4ed23630b82ea9d", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", + "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", + "wy" : "00fffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv/////++fttKlqYwfDaJyrwSBpztieSuSvelqoeVcK7Tg==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 449, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "304502203854a3998aebdf2dbc28adac4181462ccac7873907ab7f212c42db0e69b56ed8022100c12c09475c772fd0c1b2060d5163e42bf71d727e4ae7c03eeba954bf50b43bb3", + "result" : "valid" + }, + { + "tcId" : 450, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100e94dbdc38795fe5c904d8f16d969d3b587f0a25d2de90b6d8c5c53ff887e3607022100856b8c963e9b68dade44750bf97ec4d11b1a0a3804f4cb79aa27bdea78ac14e4", + "result" : "valid" + }, + { + "tcId" : 451, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3044022049fc102a08ca47b60e0858cd0284d22cddd7233f94aaffbb2db1dd2cf08425e102205b16fca5a12cdb39701697ad8e39ffd6bdec0024298afaa2326aea09200b14d6", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", + "wx" : "013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0", + "wy" : "00f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAAAAAT/SIkjWTZX3PCm0irSGMYUL5QP9\nAPhGi18PcOD27nqkO8LG/SWx2CaSQcvdnbsNrJbcliMfQwcF+DhxfQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 452, + "comment" : "x-coordinate of the public key is small", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3045022041efa7d3f05a0010675fcb918a45c693da4b348df21a59d6f9cd73e0d831d67a022100bbab52596c1a1d9484296cdc92cbf07e665259a13791a8fe8845e2c07cf3fc67", + "result" : "valid" + }, + { + "tcId" : 453, + "comment" : "x-coordinate of the public key is small", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100b615698c358b35920dd883eca625a6c5f7563970cdfc378f8fe0cee17092144c022100da0b84cd94a41e049ef477aeac157b2a9bfa6b7ac8de06ed3858c5eede6ddd6d", + "result" : "valid" + }, + { + "tcId" : 454, + "comment" : "x-coordinate of the public key is small", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "304602210087cf8c0eb82d44f69c60a2ff5457d3aaa322e7ec61ae5aecfd678ae1c1932b0e022100c522c4eea7eafb82914cbf5c1ff76760109f55ddddcf58274d41c9bc4311e06e", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "0425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", + "wx" : "25afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dffffffff", + "wy" : "00fa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJa/WiayrrtZ8Hylt5ZQG+MVQ9XFGoLTs\nLJeHbf/////6RqduUgMi37xJHsTwzBl0IPxOpYg9j23VPDVLxPZ8NQ==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 455, + "comment" : "x-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3045022062f48ef71ace27bf5a01834de1f7e3f948b9dce1ca1e911d5e13d3b104471d82022100a1570cc0f388768d3ba7df7f212564caa256ff825df997f21f72f5280d53011f", + "result" : "valid" + }, + { + "tcId" : 456, + "comment" : "x-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100f6b0e2f6fe020cf7c0c20137434344ed7add6c4be51861e2d14cbda472a6ffb40221009be93722c1a3ad7d4cf91723700cb5486de5479d8c1b38ae4e8e5ba1638e9732", + "result" : "valid" + }, + { + "tcId" : 457, + "comment" : "x-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3045022100db09d8460f05eff23bc7e436b67da563fa4b4edb58ac24ce201fa8a358125057022046da116754602940c8999c8d665f786c50f5772c0a3cdbda075e77eabc64df16", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "04d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", + "wx" : "00d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb9", + "wy" : "3f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0S5sZrZ3NMPITSYBz1013Al+J2N/CspK\nT9t0tqrdO7k/W9/4i9VzbfiY5pkAbtdQ8RzwfFhmzXrXDHEh/////w==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 458, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "30450220592c41e16517f12fcabd98267674f974b588e9f35d35406c1a7bb2ed1d19b7b8022100c19a5f942607c3551484ff0dc97281f0cdc82bc48e2205a0645c0cf3d7f59da0", + "result" : "valid" + }, + { + "tcId" : 459, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100be0d70887d5e40821a61b68047de4ea03debfdf51cdf4d4b195558b959a032b20221008266b4d270e24414ecacb14c091a233134b918d37320c6557d60ad0a63544ac4", + "result" : "valid" + }, + { + "tcId" : 460, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100fae92dfcb2ee392d270af3a5739faa26d4f97bfd39ed3cbee4d29e26af3b206a02210093645c80605595e02c09a0dc4b17ac2a51846a728b3e8d60442ed6449fd3342b", + "result" : "valid" + } + ] + }, + { + "type" : "EcdsaVerify", + "publicKey" : { + "type" : "EcPublicKey", + "curve" : "secp256k1", + "keySize" : 256, + "uncompressed" : "046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", + "wx" : "6d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000", + "wy" : "00e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb" + }, + "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbUp/YNR3Sk8KqLve25U8fup5CUB+MWR1\nVmS8KAAAAADmWdNOTfONnoyeqt+6NmEsdpGVvobHeqw/NueLU4aA+w==\n-----END PUBLIC KEY-----\n", + "sha" : "SHA-256", + "tests" : [ + { + "tcId" : 461, + "comment" : "x-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "30450220176a2557566ffa518b11226694eb9802ed2098bfe278e5570fe1d5d7af18a943022100ed6e2095f12a03f2eaf6718f430ec5fe2829fd1646ab648701656fd31221b97d", + "result" : "valid" + }, + { + "tcId" : 462, + "comment" : "x-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3045022060be20c3dbc162dd34d26780621c104bbe5dace630171b2daef0d826409ee5c2022100bd8081b27762ab6e8f425956bf604e332fa066a99b59f87e27dc1198b26f5caa", + "result" : "valid" + }, + { + "tcId" : 463, + "comment" : "x-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCasePublicKey" + ], + "msg" : "4d657373616765", + "sig" : "3046022100edf03cf63f658883289a1a593d1007895b9f236d27c9c1f1313089aaed6b16ae022100e5b22903f7eb23adc2e01057e39b0408d495f694c83f306f1216c9bf87506074", + "result" : "valid" + } + ] + } + ] +} From e34780a147de05d9f3d743cfae680a8426f832ef Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 11 Apr 2023 22:33:37 +0000 Subject: [PATCH 081/145] README --- README.md | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 4a01c29..fc58c83 100644 --- a/README.md +++ b/README.md @@ -165,25 +165,24 @@ export declare const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; randomPrivateKey: () => Bytes; isValidPrivateKey: (key: Hex) => boolean; - precompute(p: Point, windowSize?: number): Point; + precompute(p: ProjectivePoint, windowSize?: number): ProjectivePoint; }; class ProjectivePoint { - readonly px: bigint; - readonly py: bigint; - readonly pz: bigint; constructor(px: bigint, py: bigint, pz: bigint); - static readonly BASE: Point; - static readonly ZERO: Point; - static fromHex(hex: Hex): Point; - static fromPrivateKey(n: PrivKey): Point; + static readonly BASE: ProjectivePoint; + static readonly ZERO: ProjectivePoint; + static fromAffine(point: AffinePoint): ProjectivePoint; + static fromHex(hex: Hex): ProjectivePoint; + static fromPrivateKey(n: PrivKey): ProjectivePoint; get x(): bigint; get y(): bigint; - equals(other: Point): boolean; - add(other: Point): Point; - multiply(n: bigint): Point; - negate(): Point; + add(other: ProjectivePoint): ProjectivePoint; + assertValidity(): void; + equals(other: ProjectivePoint): boolean; + multiply(n: bigint): ProjectivePoint; + negate(): ProjectivePoint; + subtract(other: ProjectivePoint): ProjectivePoint; toAffine(): AffinePoint; - assertValidity(): Point; toHex(isCompressed?: boolean): string; toRawBytes(isCompressed?: boolean): Uint8Array; } From fc8cfe0222ee9ac99cbd00ace62ea216f69ef2d1 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 12 Apr 2023 04:26:48 +0200 Subject: [PATCH 082/145] readme --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc58c83..4531eec 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # noble-secp256k1 -[Fastest](#speed) 4KB JS implementation of [secp256k1](https://www.secg.org/sec2-v2.pdf) -elliptic curve. Auditable, high-security, 0-dependency ECDH & ECDSA signatures compliant with RFC6979. +[Fastest](#speed) 4KB JS implementation of +secp256k1 [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman) & +[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) +signatures compliant with [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). The library is a tiny single-feature version of [noble-curves](https://github.com/paulmillr/noble-curves), with some features From bf2a25531ac0984706ccb89075e5f27a1e362adb Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 12 Apr 2023 04:28:15 +0200 Subject: [PATCH 083/145] pkg.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56584ec..f8c6cf0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@noble/secp256k1", "version": "2.0.0", - "description": "Fastest 4KB JS implementation of secp256k1 elliptic curve. Auditable, high-security, 0-dependency ECDH & ECDSA signatures compliant with RFC6979", + "description": "Fastest 4KB JS implementation of secp256k1 ECDH & ECDSA signatures compliant with RFC6979", "files": [ "index.js", "index.d.ts", From eddf00273f8f8649a7e11b925c6ad7c3e7f5433b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 22 Apr 2023 00:24:18 +0000 Subject: [PATCH 084/145] test: remove mjs extension from files --- package.json | 2 +- test/{secp256k1.helpers.mjs => secp256k1.helpers.js} | 12 +++++++----- test/{secp256k1.helpers.mts => secp256k1.helpers.ts} | 10 +++++++--- test/{secp256k1.test.mjs => secp256k1.test.js} | 5 ++++- 4 files changed, 19 insertions(+), 10 deletions(-) rename test/{secp256k1.helpers.mjs => secp256k1.helpers.js} (83%) rename test/{secp256k1.helpers.mts => secp256k1.helpers.ts} (84%) rename test/{secp256k1.test.mjs => secp256k1.test.js} (99%) diff --git a/package.json b/package.json index f8c6cf0..f6c9b28 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "scripts": { "build": "tsc", "build:release": "rollup -c rollup.config.js", - "test": "node test/secp256k1.test.mjs", + "test": "node test/secp256k1.test.js", "bench": "node test/benchmark.js", "min": "cd test/build; npm install; npm run terser", "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts` LOC, `npm run --silent min | gzip -c8 | wc -c`B gzipped\"" diff --git a/test/secp256k1.helpers.mjs b/test/secp256k1.helpers.js similarity index 83% rename from test/secp256k1.helpers.mjs rename to test/secp256k1.helpers.js index 79b3ee7..d8ab72e 100644 --- a/test/secp256k1.helpers.mjs +++ b/test/secp256k1.helpers.js @@ -22,11 +22,13 @@ export const DER = { throw new E('Invalid signature integer tag'); const len = data[1]; const res = data.subarray(2, len + 2); - if (!len || res.length !== len) - throw new E('Invalid signature integer: wrong length'); - if (res[0] === 0x00 && res[1] <= 0x7f) - throw new E('Invalid signature integer: trailing length'); - // ^ Weird condition: not about length, but about first bytes of number. + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative'); + if (res[0] === 0x00 && !(res[1] & 0b10000000)) + throw new E('Invalid signature integer: unnecessary leading zero'); return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left }, toSig(hex) { diff --git a/test/secp256k1.helpers.mts b/test/secp256k1.helpers.ts similarity index 84% rename from test/secp256k1.helpers.mts rename to test/secp256k1.helpers.ts index 52f526e..35964c3 100644 --- a/test/secp256k1.helpers.mts +++ b/test/secp256k1.helpers.ts @@ -23,9 +23,13 @@ export const DER = { const len = data[1]; const res = data.subarray(2, len + 2); if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length'); - if (res[0] === 0x00 && res[1] <= 0x7f) - throw new E('Invalid signature integer: trailing length'); - // ^ Weird condition: not about length, but about first bytes of number. + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative'); + if (res[0] === 0x00 && !(res[1] & 0b10000000)) + throw new E('Invalid signature integer: unnecessary leading zero'); return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left }, toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { diff --git a/test/secp256k1.test.mjs b/test/secp256k1.test.js similarity index 99% rename from test/secp256k1.test.mjs rename to test/secp256k1.test.js index 618488f..7ad7d68 100644 --- a/test/secp256k1.test.mjs +++ b/test/secp256k1.test.js @@ -6,7 +6,7 @@ import { should, describe } from 'micro-should'; // prettier-ignore import { secp, sigFromDER, sigToDER, selectHash, normVerifySig, mod, bytesToNumberBE, numberToBytesBE -} from './secp256k1.helpers.mjs'; +} from './secp256k1.helpers.js'; import { default as ecdsa } from './vectors/secp256k1/ecdsa.json' assert { type: 'json' }; import { default as ecdh } from './wycheproof/ecdh_secp256k1_test.json' assert { type: 'json' }; @@ -14,6 +14,9 @@ import { default as privates } from './vectors/secp256k1/privates.json' assert { import { default as points } from './vectors/secp256k1/points.json' assert { type: 'json' }; import { default as wp } from './wycheproof/ecdsa_secp256k1_sha256_test.json' assert { type: 'json' }; +// Any changes to the file will need to be aware of the fact +// the file is shared between noble-curves and noble-secp256k1. + const Point = secp.ProjectivePoint; const privatesTxt = readFileSync('./test/vectors/secp256k1/privates-2.txt', 'utf-8'); From 1b6dd71a263b714b9324a6c70dd498cb9309a00b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 22 Apr 2023 01:13:45 +0000 Subject: [PATCH 085/145] benchmarks --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4531eec..40e9d8c 100644 --- a/README.md +++ b/README.md @@ -235,14 +235,14 @@ be downloading malware with every `npm install`. Our goal is to minimize this at Use [noble-curves](https://github.com/paulmillr/noble-curves) if you need even higher performance. -Benchmarks measured with Apple M2 on MacOS 13 with node.js 19. - - getPublicKey(utils.randomPrivateKey()) x 5,540 ops/sec @ 180μs/op - sign x 3,301 ops/sec @ 302μs/op - verify x 517 ops/sec @ 1ms/op - getSharedSecret x 433 ops/sec @ 2ms/op - recoverPublicKey x 526 ops/sec @ 1ms/op - Point.fromHex (decompression) x 8,415 ops/sec @ 118μs/op +Benchmarks measured with Apple M2 on MacOS 13 with node.js 20. + + getPublicKey(utils.randomPrivateKey()) x 6,430 ops/sec @ 155μs/op + sign x 3,367 ops/sec @ 296μs/op + verify x 600 ops/sec @ 1ms/op + getSharedSecret x 505 ops/sec @ 1ms/op + recoverPublicKey x 612 ops/sec @ 1ms/op + Point.fromHex (decompression) x 9,185 ops/sec @ 108μs/op Compare to other libraries on M1 (`openssl` uses native bindings, not JS): From 3bab8c1f0bd26710697b26a5329e3f3c91f70073 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 23 Apr 2023 17:22:00 +0000 Subject: [PATCH 086/145] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 40e9d8c..fd23416 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ signatures compliant with [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). The library is a tiny single-feature version of [noble-curves](https://github.com/paulmillr/noble-curves), with some features -removed. Check out curves as a drop-in replacement with +removed. Check out curves as a drop-in replacement with common.js, Schnorr signatures, DER encoding and support for different hash functions. Take a look at: [Upgrading](#upgrading) section for v1 to v2 transition instructions, From 52e1f994ca74fe1a0f68813f16bc6e1d66bf0d4e Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 23 Apr 2023 20:32:58 +0200 Subject: [PATCH 087/145] ci: upgrade nodejs to v20 --- .github/workflows/nodejs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 2528878..d269133 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -3,14 +3,14 @@ name: Node CI on: [push, pull_request] jobs: test: - name: v19 @ ubuntu-latest + name: v20 @ ubuntu-latest runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@v3 with: - node-version: 19 + node-version: 20 - run: npm install - run: npm run build --if-present - run: npm test From 3e2a7e0c0787e976b477322bf72684cb314456ad Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 26 Apr 2023 22:17:07 +0000 Subject: [PATCH 088/145] Add secp256k1 compatibility layer URL to readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fd23416..a411231 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,9 @@ removed. Check out curves as a drop-in replacement with common.js, Schnorr signatures, DER encoding and support for different hash functions. Take a look at: [Upgrading](#upgrading) section for v1 to v2 transition instructions, -[the online demo](https://paulmillr.com/noble/) and blog post +[the online demo](https://paulmillr.com/noble/), +[secp256k1-node compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts) +and blog post [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). ### This library belongs to _noble_ crypto From 474c7c90bf8a7cb5848103e6cb748c34bb3f3b55 Mon Sep 17 00:00:00 2001 From: Micah Zoltu Date: Sat, 29 Apr 2023 03:07:30 +0800 Subject: [PATCH 089/145] Corrects type of `sign` and `signAsync` The only place that `priv` is used in `signAsync` and `sign` is when it is passed to `prepSig`. The only place `priv` is used in `prepSig` is when it is passed to `toPriv`. `toPriv` takes a `PrivKey`, so that means `prepSig`, `sign`, and `signAsync` can also take a `PrivKey`. Functionally, this means that `bigint` is now allowed as a private key. This will make it so users who are storing private keys in memory as bigints will not have to first convert to hex. Node: Currently if you naively convert your bigint private key to hex using `0x${privateKey.toString(16)}` this library will throw an error complaining about the hex for the private key being the wrong length. Arguably this library should accept an odd length hex value for the private key, but in my case just accepting bigints directly would fix the issue and allowing odd length hex strings would require an actual code change rather than just a type change. --- index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.ts b/index.ts index 3f8288b..302477c 100644 --- a/index.ts +++ b/index.ts @@ -217,7 +217,7 @@ let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don const optS: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() const optV: { lowS?: boolean } = { lowS: true }; // standard opts for verify() type BC = { seed: Bytes, k2sig : (kb: Bytes) => Signature | undefined }; // Bytes+predicate checker -function prepSig(msgh: Hex, priv: Hex, opts = optS): BC { // prepare for RFC6979 sig generation +function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC6979 sig generation if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); let { lowS } = opts; // generates low-s sigs by default @@ -313,11 +313,11 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async } } // ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k -async function signAsync(msgh: Hex, priv: Hex, opts = optS): Promise { +async function signAsync(msgh: Hex, priv: PrivKey, opts = optS): Promise { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } -function sign(msgh: Hex, priv: Hex, opts = optS): Signature { +function sign(msgh: Hex, priv: PrivKey, opts = optS): Signature { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } From 7f4621331086e915b440a1d8d06cc734d3ceabaf Mon Sep 17 00:00:00 2001 From: Micah Zoltu Date: Tue, 2 May 2023 21:55:21 +0800 Subject: [PATCH 090/145] Narrows return type for sign and signAsync. (#101) --- index.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/index.ts b/index.ts index 302477c..8b0160e 100644 --- a/index.ts +++ b/index.ts @@ -173,6 +173,7 @@ const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bi function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output } +type SignatureWithRecovery = Signature & { recovery: number } class Signature { // ECDSA Signature class constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { this.assertValidity(); // recovery bit is optional when @@ -216,7 +217,7 @@ type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it const optS: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() const optV: { lowS?: boolean } = { lowS: true }; // standard opts for verify() -type BC = { seed: Bytes, k2sig : (kb: Bytes) => Signature | undefined }; // Bytes+predicate checker +type BC = { seed: Bytes, k2sig : (kb: Bytes) => SignatureWithRecovery | undefined }; // Bytes+predicate checker function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC6979 sig generation if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); @@ -234,7 +235,7 @@ function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC seed.push(e); } const m = h1i; // convert msg to bigint - const k2sig = (kBytes: Bytes): Signature | undefined => { // Transform k into Signature. + const k2sig = (kBytes: Bytes): SignatureWithRecovery | undefined => { // Transform k into Signature. const k = bits2int(kBytes); // RFC6979 method. if (!ge(k)) return; // Check 0 < k < CURVE.n const ik = inv(k, N); // k^-1 mod n, NOT mod P @@ -249,7 +250,7 @@ function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC normS = mod(-s, N); // in the bottom half of CURVE.n rec ^= 1; } - return new Signature(r, normS, rec); // use normS, not s + return new Signature(r, normS, rec) as SignatureWithRecovery; // use normS, not s }; return { seed: concatB(...seed), k2sig } } @@ -313,13 +314,13 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async } } // ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k -async function signAsync(msgh: Hex, priv: PrivKey, opts = optS): Promise { +async function signAsync(msgh: Hex, priv: PrivKey, opts = optS): Promise { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg - return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok + return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } -function sign(msgh: Hex, priv: PrivKey, opts = optS): Signature { +function sign(msgh: Hex, priv: PrivKey, opts = optS): SignatureWithRecovery { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg - return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok + return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok } type SigLike = { r: bigint, s: bigint }; function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { From 63066e8fcd7d5af9695119522bc7048bd030dfad Mon Sep 17 00:00:00 2001 From: legobt <6wbvkn0j@anonaddy.me> Date: Wed, 3 May 2023 14:06:06 +0000 Subject: [PATCH 091/145] test: fix filename in test/tsconfig.json The helpers file was renamed in eddf00273f8f8649a7e11b925c6ad7c3e7f5433b but the test tsconfig was left configured with the old filename. This updates the definition file accordingly. --- test/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tsconfig.json b/test/tsconfig.json index 12e568c..bf701d8 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -8,6 +8,6 @@ "preserveConstEnums": true, "resolveJsonModule": true }, - "include": ["secp256k1.helpers.mts"], + "include": ["secp256k1.helpers.ts"], "exclude": ["node_modules"] } From 6113de13ada1d14ff49039a6adcd50e440998ab2 Mon Sep 17 00:00:00 2001 From: legobeat <109787230+legobeat@users.noreply.github.com> Date: Wed, 3 May 2023 17:01:48 +0000 Subject: [PATCH 092/145] ci: test nodejs v16/v18/v20 (#105) and polyfill --- .github/workflows/nodejs.yml | 23 +++++++++++++++++++++-- package.json | 1 + test/secp256k1.helpers.js | 13 ++++++------- test/secp256k1.helpers.ts | 5 ----- test/secp256k1.webcrypto.test.js | 9 +++++++++ 5 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 test/secp256k1.webcrypto.test.js diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index d269133..10806fa 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -3,15 +3,34 @@ name: Node CI on: [push, pull_request] jobs: test: - name: v20 @ ubuntu-latest + name: node @ ubuntu-latest runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@v3 with: - node-version: 20 + node-version: ${{ matrix.node-version }} - run: npm install - run: npm run build --if-present - run: npm test - run: npm run lint --if-present + test-polyfill: + name: node+webcrypto @ ubuntu-latest + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [16.x, 18.x, 20.x] + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm run build --if-present + - run: npm run test:webcrypto + - run: npm run lint --if-present diff --git a/package.json b/package.json index f6c9b28..548e07e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "build": "tsc", "build:release": "rollup -c rollup.config.js", "test": "node test/secp256k1.test.js", + "test:webcrypto": "node test/secp256k1.webcrypto.test.js", "bench": "node test/benchmark.js", "min": "cd test/build; npm install; npm run terser", "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts` LOC, `npm run --silent min | gzip -c8 | wc -c`B gzipped\"" diff --git a/test/secp256k1.helpers.js b/test/secp256k1.helpers.js index d8ab72e..92f8b7b 100644 --- a/test/secp256k1.helpers.js +++ b/test/secp256k1.helpers.js @@ -1,9 +1,5 @@ -import { webcrypto } from 'node:crypto'; -// @ts-ignore -if (!globalThis.crypto) globalThis.crypto = webcrypto; // @ts-ignore -// @ts-ignore -export * as secp from '../index.js'; -// @ts-ignore +import * as secp_1 from '../index.js'; +export { secp_1 as secp }; import * as secp256k1 from '../index.js'; import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; @@ -22,11 +18,14 @@ export const DER = { throw new E('Invalid signature integer tag'); const len = data[1]; const res = data.subarray(2, len + 2); + if (!len || res.length !== len) + throw new E('Invalid signature integer: wrong length'); // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, // since we always use positive integers here. It must always be empty: // - add zero byte if exists // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative'); + if (res[0] & 0b10000000) + throw new E('Invalid signature integer: negative'); if (res[0] === 0x00 && !(res[1] & 0b10000000)) throw new E('Invalid signature integer: unnecessary leading zero'); return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left diff --git a/test/secp256k1.helpers.ts b/test/secp256k1.helpers.ts index 35964c3..5265484 100644 --- a/test/secp256k1.helpers.ts +++ b/test/secp256k1.helpers.ts @@ -1,9 +1,4 @@ -import { webcrypto } from 'node:crypto'; -// @ts-ignore -if (!globalThis.crypto) globalThis.crypto = webcrypto; // @ts-ignore -// @ts-ignore export * as secp from '../index.js'; -// @ts-ignore import * as secp256k1 from '../index.js'; import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; diff --git a/test/secp256k1.webcrypto.test.js b/test/secp256k1.webcrypto.test.js new file mode 100644 index 0000000..2dd0cd0 --- /dev/null +++ b/test/secp256k1.webcrypto.test.js @@ -0,0 +1,9 @@ +import { webcrypto } from 'node:crypto'; +// @ts-ignore +if (!globalThis.crypto) globalThis.crypto = webcrypto; + +import './secp256k1.test.js'; + +// Force ESM import to execute +import { should } from 'micro-should'; +should.run(); From 6901705ef6fffd1244a3f5bdc97de819652e2170 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 3 May 2023 17:06:49 +0000 Subject: [PATCH 093/145] Adjust return type of addRecoveryBit --- index.d.ts | 13 ++++++++----- index.js | 10 ++++++---- index.ts | 16 +++++++++------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/index.d.ts b/index.d.ts index d5ce689..f17f615 100644 --- a/index.d.ts +++ b/index.d.ts @@ -40,6 +40,9 @@ declare class Point { toRawBytes(isCompressed?: boolean): Uint8Array; } declare function getPublicKey(privKey: PrivKey, isCompressed?: boolean): Uint8Array; +type SignatureWithRecovery = Signature & { + recovery: number; +}; declare class Signature { readonly r: bigint; readonly s: bigint; @@ -47,21 +50,21 @@ declare class Signature { constructor(r: bigint, s: bigint, recovery?: number | undefined); static fromCompact(hex: Hex): Signature; assertValidity(): this; - addRecoveryBit(rec: number): Signature; + addRecoveryBit(rec: number): SignatureWithRecovery; hasHighS(): boolean; recoverPublicKey(msgh: Hex): Point; toCompactRawBytes(): Uint8Array; toCompactHex(): string; } type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); -declare function signAsync(msgh: Hex, priv: Hex, opts?: { +declare function signAsync(msgh: Hex, priv: PrivKey, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; -}): Promise; -declare function sign(msgh: Hex, priv: Hex, opts?: { +}): Promise; +declare function sign(msgh: Hex, priv: PrivKey, opts?: { lowS?: boolean | undefined; extraEntropy?: boolean | Hex | undefined; -}): Signature; +}): SignatureWithRecovery; type SigLike = { r: bigint; s: bigint; diff --git a/index.js b/index.js index 60b4464..f7bdaa4 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy }; // exported variables incl. a, b const fLen = 32; // field / group byte length -const crv = (x) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; no a +const crv = (x) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n) => typeof n === 'bigint'; // is big integer const str = (s) => typeof s === 'string'; // is string @@ -225,7 +225,9 @@ class Signature { return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } assertValidity() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n - addRecoveryBit(rec) { return new Signature(this.r, this.s, rec); } + addRecoveryBit(rec) { + return new Signature(this.r, this.s, rec); + } hasHighS() { return moreThanHalfN(this.s); } recoverPublicKey(msgh) { const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 @@ -368,11 +370,11 @@ function hmacDrbg(asynchronous) { // ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k async function signAsync(msgh, priv, opts = optS) { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg - return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok + return hmacDrbg(true)(seed, k2sig); // Re-run drbg until k2sig returns ok } function sign(msgh, priv, opts = optS) { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg - return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok + return hmacDrbg(false)(seed, k2sig); // Re-run drbg until k2sig returns ok } function verify(sig, msgh, pub, opts = optV) { let { lowS } = opts; // ECDSA signature verification diff --git a/index.ts b/index.ts index 8b0160e..0659218 100644 --- a/index.ts +++ b/index.ts @@ -7,7 +7,7 @@ const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy};// exported variables incl. a, b const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; -const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; no a +const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: unknown): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: unknown): s is string => typeof s === 'string'; // is string @@ -174,7 +174,7 @@ function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output } type SignatureWithRecovery = Signature & { recovery: number } -class Signature { // ECDSA Signature class +class Signature { // ECDSA Signature class constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) { this.assertValidity(); // recovery bit is optional when } // constructed outside. @@ -183,7 +183,9 @@ class Signature { // ECDSA Signature class return new Signature(slcNum(hex, 0, fLen), slcNum(hex, fLen, 2 * fLen)); } assertValidity() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n - addRecoveryBit(rec: number) { return new Signature(this.r, this.s, rec); } + addRecoveryBit(rec: number): SignatureWithRecovery { + return new Signature(this.r, this.s, rec) as SignatureWithRecovery; + } hasHighS() { return moreThanHalfN(this.s); } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 @@ -235,7 +237,7 @@ function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC seed.push(e); } const m = h1i; // convert msg to bigint - const k2sig = (kBytes: Bytes): SignatureWithRecovery | undefined => { // Transform k into Signature. + const k2sig = (kBytes: Bytes): SignatureWithRecovery | undefined => { // Transform k => Signature. const k = bits2int(kBytes); // RFC6979 method. if (!ge(k)) return; // Check 0 < k < CURVE.n const ik = inv(k, N); // k^-1 mod n, NOT mod P @@ -250,7 +252,7 @@ function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC normS = mod(-s, N); // in the bottom half of CURVE.n rec ^= 1; } - return new Signature(r, normS, rec) as SignatureWithRecovery; // use normS, not s + return new Signature(r, normS, rec) as SignatureWithRecovery; // use normS, not s }; return { seed: concatB(...seed), k2sig } } @@ -316,11 +318,11 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async // ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k async function signAsync(msgh: Hex, priv: PrivKey, opts = optS): Promise { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg - return hmacDrbg(true)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok + return hmacDrbg(true)(seed, k2sig); // Re-run drbg until k2sig returns ok } function sign(msgh: Hex, priv: PrivKey, opts = optS): SignatureWithRecovery { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg - return hmacDrbg(false)(seed, k2sig); // Re-run hmac-drbg until k2sig returns ok + return hmacDrbg(false)(seed, k2sig); // Re-run drbg until k2sig returns ok } type SigLike = { r: bigint, s: bigint }; function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { From f3e7df4b60a497766aa45e70c2205099d54fdb61 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 5 May 2023 22:29:00 +0000 Subject: [PATCH 094/145] line-up --- index.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/index.ts b/index.ts index 0659218..8ba2ef9 100644 --- a/index.ts +++ b/index.ts @@ -4,7 +4,7 @@ const P = B256 - 0x1000003d1n; // curve's field prime const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n; // base point x const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; // base point y -const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy};// exported variables incl. a, b +const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy}; // exported variables incl. a, b const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 @@ -59,7 +59,7 @@ class Point { // Point in 3d xyz proje const { px: X1, py: Y1, pz: Z1 } = this; // free formula from Renes-Costello-Batina const { px: X2, py: Y2, pz: Z2 } = isPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 const { a, b } = CURVE; // Cost: 12M + 0S + 3*a + 3*b3 + 23add - let X3 = 0n, Y3 = 0n, Z3 = 0n; + let X3 = 0n, Y3 = 0n, Z3 = 0n; const b3 = mod(b * 3n); let t0 = mod(X1 * X2), t1 = mod(Y1 * Y2), t2 = mod(Z1 * Z2), t3 = mod(X1 + Y1); // step 1 let t4 = mod(X2 + Y2); // step 5 @@ -79,7 +79,7 @@ class Point { // Point in 3d xyz proje Z3 = mod(Z3 + t0); // step 40 return new Point(X3, Y3, Z3); } - mul(n: bigint, safe = true) { // Point scalar multiplication. + mul(n: bigint, safe = true) { // Point scalar multiplication. if (!safe && n === 0n) return I; // in unsafe mode, allow zero if (!ge(n)) err('invalid scalar'); // must be 0 < n < CURVE.n if (this.equals(G)) return wNAF(n).p; // use precomputes for base point @@ -169,7 +169,7 @@ const toPriv = (p: PrivKey): bigint => { // normalize private key if (!big(p)) p = b2n(toU8(p, fLen)); // convert to bigint when bytes return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; -const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n) // if a number is bigger than CURVE.n/2 +const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n); // if a number is bigger than CURVE.n/2 function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output } @@ -208,8 +208,8 @@ const bits2int = (bytes: Uint8Array): bigint => { // RFC6979: ensure ECDSA const num = b2n(bytes); // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which return delta > 0 ? num >> BigInt(delta) : num; // matches bits2int. bits2int can produce res>N. }; -const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be used; pads small msgs - return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors +const bits2int_modN = (bytes: Uint8Array): bigint => { // int2octets can't be used; pads small msgs + return mod(bits2int(bytes), N); // with 0: BAD for trunc as per RFC vectors }; const i2o = (num: bigint): Bytes => n2b(num); // int to octets declare const globalThis: Record | undefined; // Typescript symbol present in browsers @@ -281,8 +281,8 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async }; return async (seed: Bytes, pred: Pred): Promise => { // Even though it feels safe to reuse reset(); // the returned fn, don't, it's: 1. slower (JIT). 2. unsafe (async race conditions) - await reseed(seed); // Steps D-G - let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] + await reseed(seed); // Steps D-G + let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] while (!(res = pred(await gen()))) await reseed();// test predicate until it returns ok reset(); return res!; @@ -307,9 +307,9 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async }; return (seed: Bytes, pred: Pred): T => { reset(); - reseed(seed); // Steps D-G - let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] - while (!(res = pred(gen()))) reseed(); // test predicate until it returns ok + reseed(seed); // Steps D-G + let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed(); // test predicate until it returns ok reset(); return res!; }; @@ -362,7 +362,7 @@ function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compli const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); } -const etc = { // Not placed in utils because they +const etc = { // Not placed in utils because they hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, // math utilities From cfcb1fa6dc19dfa8883718fcfca3cc493d2930c7 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 7 May 2023 23:56:47 +0000 Subject: [PATCH 095/145] readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a411231..b1f3710 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ secp256k1 [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman) [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) signatures compliant with [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). -The library is a tiny single-feature version of -[noble-curves](https://github.com/paulmillr/noble-curves), with some features -removed. Check out curves as a drop-in replacement with common.js, -Schnorr signatures, DER encoding and support for different hash functions. +If you're looking for additional features, +check out [noble-curves](https://github.com/paulmillr/noble-curves): +a drop-in replacement with common.js, Schnorr signatures, DER encoding and +support for different hash functions. -Take a look at: [Upgrading](#upgrading) section for v1 to v2 transition instructions, +Check out [Upgrading](#upgrading) section for v1 to v2 transition instructions, [the online demo](https://paulmillr.com/noble/), [secp256k1-node compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts) and blog post From 3347ae472535d3bea94dc7b9685ffaf2b1942072 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 12 May 2023 17:03:31 +0000 Subject: [PATCH 096/145] readme --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b1f3710..0a07d80 100644 --- a/README.md +++ b/README.md @@ -46,17 +46,17 @@ import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js const privKey = secp.utils.randomPrivateKey(); // Secure random private key // sha256 of 'hello world' const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; - const pubKey = secp.getPublicKey(privKey); // Make pubkey from the private key - const signature = await secp.signAsync(msgHash, privKey); // sign - const isValid = secp.verify(signature, msgHash, pubKey); // verify + const pubKey = secp.getPublicKey(privKey); + const signature = await secp.signAsync(msgHash, privKey); // sync methods below + const isValid = secp.verify(signature, msgHash, pubKey); - const pubKey2 = getPublicKey(secp.utils.randomPrivateKey()); // Key of user 2 + const alicesPubkey = secp.getPublicKey(secp.utils.randomPrivateKey()); secp.getSharedSecret(privKey, alicesPubkey); // Elliptic curve diffie-hellman signature.recoverPublicKey(msgHash); // Public key recovery })(); ``` -Advanced examples: +Note that node.js <= 18 requires `global.crypto` polyfill. Advanced examples: ```ts // 1. Use the shim to enable synchronous methods. @@ -66,9 +66,9 @@ import { sha256 } from '@noble/hashes/sha256'; secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) const signature2 = secp.sign(msgHash, privKey); // Can be used now -// 2. Use the shim only for node.js <= 18 BEFORE importing noble-secp256k1. -// The library depends on global variable crypto to work. It is available in -// all browsers and many environments, but node.js <= 18 don't have it. +// 2. Use the shim only in node.js <= 18 BEFORE importing noble. +// `crypto` global variable is already present in all browsers and node.js 19+. +// It is necessary for the library to work. import { webcrypto } from 'node:crypto'; // @ts-ignore if (!globalThis.crypto) globalThis.crypto = webcrypto; @@ -155,7 +155,7 @@ type Bytes = Uint8Array; export declare const etc: { hexToBytes: (hex: string) => Bytes; bytesToHex: (b: Bytes) => string; - concatBytes: (...arrs: Bytes[]) => Uint8Array; + concatBytes: (...arrs: Bytes[]) => Bytes; bytesToNumberBE: (b: Bytes) => bigint; numberToBytesBE: (num: bigint) => Bytes; mod: (a: bigint, b?: bigint) => bigint; @@ -188,7 +188,7 @@ class ProjectivePoint { subtract(other: ProjectivePoint): ProjectivePoint; toAffine(): AffinePoint; toHex(isCompressed?: boolean): string; - toRawBytes(isCompressed?: boolean): Uint8Array; + toRawBytes(isCompressed?: boolean): Bytes; } class Signature { readonly r: bigint; @@ -199,7 +199,7 @@ class Signature { static fromCompact(hex: Hex): Signature; hasHighS(): boolean; recoverPublicKey(msgh: Hex): Point; - toCompactRawBytes(): Uint8Array; + toCompactRawBytes(): Bytes; toCompactHex(): string; } CURVE // curve prime; order; equation params, generator coordinates From ed5621d7f7b5e95548e3e670c9be397880ef46a9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 12 May 2023 18:53:33 +0000 Subject: [PATCH 097/145] CI: auto-publish to NPM on GH release --- .github/workflows/publish-npm.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/publish-npm.yml diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 0000000..3438a7f --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,23 @@ +name: Publish Package to npm +on: + release: + types: [created] +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 + - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install -g npm + - run: npm ci + - run: npm run build + - run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} From 7512bf4df514c13f05a8b6c55854968c19507082 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 20 May 2023 10:34:45 +0000 Subject: [PATCH 098/145] readme --- README.md | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 0a07d80..fbeedbd 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,12 @@ and blog post ## Usage -Browser, deno, node.js and unpkg are supported: - > npm install @noble/secp256k1 +We support all major platforms and runtimes. +For node.js <= 18, a polyfill for `globalThis.crypto` is needed, see below. +For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values). + ```js import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js // import * as secp from "https://deno.land/x/secp256k1/mod.ts"; // Deno @@ -56,33 +58,30 @@ import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js })(); ``` -Note that node.js <= 18 requires `global.crypto` polyfill. Advanced examples: +Advanced examples: ```ts -// 1. Use the shim to enable synchronous methods. -// Only async methods are available by default to keep library dependency-free. +// Enable synchronous methods. +// Only async methods are available by default, to keep the library dependency-free. import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) const signature2 = secp.sign(msgHash, privKey); // Can be used now -// 2. Use the shim only in node.js <= 18 BEFORE importing noble. -// `crypto` global variable is already present in all browsers and node.js 19+. -// It is necessary for the library to work. +// node.js 18 and earlier requires globalThis.crypto polyfill. import { webcrypto } from 'node:crypto'; // @ts-ignore if (!globalThis.crypto) globalThis.crypto = webcrypto; -// Other stuff -// Malleable signatures, incompatible with BTC/ETH, but compatible with openssl -// `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) because of -// malleability +// Enable OpenSSL compatibility. +// OpenSSL allows to create malleable signatures, which are not compatible with BTC/ETH. +// By default, `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n). const signatureMalleable = secp.sign(msgHash, privKey, { lowS: false }); -// Signatures with improved security: adds additional entropy `k` for -// deterministic signature, follows section 3.6 of RFC6979. When `true`, it -// would be filled with 32b from CSPRNG. **Strongly recommended** to pass `true` -// to improve security: +// Signatures with improved security, containing additional entropy. +// Adds entropy to deterministic signature, follows section 3.6 of RFC6979. +// When `true`, it would be filled with 32b from CSPRNG. +// **Strongly recommended** to use, to improve security: // - No disadvantage: if an entropy generator is broken, sigs would be the same // as they are without the option // - It would help a lot in case there is an error somewhere in `k` gen. @@ -152,7 +151,7 @@ A bunch of useful **utilities** are also exposed: ```typescript type Bytes = Uint8Array; -export declare const etc: { +const etc: { hexToBytes: (hex: string) => Bytes; bytesToHex: (b: Bytes) => string; concatBytes: (...arrs: Bytes[]) => Bytes; @@ -165,7 +164,7 @@ export declare const etc: { hashToPrivateKey: (hash: Hex) => Bytes; randomBytes: (len: number) => Bytes; }; -export declare const utils: { +const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; randomPrivateKey: () => Bytes; isValidPrivateKey: (key: Hex) => boolean; @@ -191,12 +190,12 @@ class ProjectivePoint { toRawBytes(isCompressed?: boolean): Bytes; } class Signature { + constructor(r: bigint, s: bigint, recovery?: number | undefined); + static fromCompact(hex: Hex): Signature; readonly r: bigint; readonly s: bigint; readonly recovery?: number | undefined; - constructor(r: bigint, s: bigint, recovery?: number | undefined); ok(): Signature; - static fromCompact(hex: Hex): Signature; hasHighS(): boolean; recoverPublicKey(msgh: Hex): Point; toCompactRawBytes(): Bytes; From cfa347b666aa89cc71e3a17cad78d29565b7ac47 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 20 May 2023 10:57:40 +0000 Subject: [PATCH 099/145] readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fbeedbd..400c7c8 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ For node.js <= 18, a polyfill for `globalThis.crypto` is needed, see below. For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values). ```js -import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js +import * as secp from '@noble/secp256k1'; // import * as secp from "https://deno.land/x/secp256k1/mod.ts"; // Deno // import * as secp from "https://unpkg.com/@noble/secp256k1"; // Unpkg (async () => { @@ -49,7 +49,7 @@ import * as secp from '@noble/secp256k1'; // ESM-only. Use bundler for common.js // sha256 of 'hello world' const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; const pubKey = secp.getPublicKey(privKey); - const signature = await secp.signAsync(msgHash, privKey); // sync methods below + const signature = await secp.signAsync(msgHash, privKey); // Sync methods below const isValid = secp.verify(signature, msgHash, pubKey); const alicesPubkey = secp.getPublicKey(secp.utils.randomPrivateKey()); @@ -66,7 +66,8 @@ Advanced examples: import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) -const signature2 = secp.sign(msgHash, privKey); // Can be used now +// const signature2 = secp.sign(msgHash, privKey); // Can be used now +// secp.sign(msgHash, privKey); // sync methods can be used now // node.js 18 and earlier requires globalThis.crypto polyfill. import { webcrypto } from 'node:crypto'; From 30624746b04711c2de02640c2bae191dbd2fa536 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 20 May 2023 10:58:27 +0000 Subject: [PATCH 100/145] readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 400c7c8..0303a3c 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ Advanced examples: import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) -// const signature2 = secp.sign(msgHash, privKey); // Can be used now // secp.sign(msgHash, privKey); // sync methods can be used now // node.js 18 and earlier requires globalThis.crypto polyfill. From 458128c45e4d1efb59be907e0d108dc9d875a3b1 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 26 May 2023 11:09:47 +0000 Subject: [PATCH 101/145] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0303a3c..107392a 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ and blog post We support all major platforms and runtimes. For node.js <= 18, a polyfill for `globalThis.crypto` is needed, see below. -For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values). +For React Native, which doesn't implement webcrypto, you may need a [polyfill for crypto.getRandomValues](https://github.com/LinusU/react-native-get-random-values) and either a polyfill for webcrypto, or simply enabling synchronous methods. ```js import * as secp from '@noble/secp256k1'; From 21270b74003901b395ff8f66158f99c376bc57ef Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 26 May 2023 11:24:18 +0000 Subject: [PATCH 102/145] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 107392a..95f30e5 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ const etc: { }; const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; - randomPrivateKey: () => Bytes; + randomPrivateKey: () => Bytes; // Uses CSPRNG https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues isValidPrivateKey: (key: Hex) => boolean; precompute(p: ProjectivePoint, windowSize?: number): ProjectivePoint; }; From 73a0696b8a8a3319f619bc7ef8bf17f324755b75 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 26 May 2023 11:27:16 +0000 Subject: [PATCH 103/145] readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 95f30e5..9f579e9 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,10 @@ that's why it's crucial to minimize the amount of 3rd-party dependencies & nativ bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector. +As for key generation, we're deferring to built-in +[crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) +which is considered cryptographically secure (CSPRNG). + ## Speed Use [noble-curves](https://github.com/paulmillr/noble-curves) if you need even higher performance. From 18b09caa1f28c4ae0b8a716d4904c869673323fc Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 27 May 2023 14:11:19 +0000 Subject: [PATCH 104/145] pkg.json: Adjust funding field --- package-lock.json | 9 +++------ package.json | 7 +------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd76064..a501d6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,12 +7,6 @@ "": { "name": "@noble/secp256k1", "version": "2.0.0", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "license": "MIT", "devDependencies": { "@noble/hashes": "1.3.0", @@ -20,6 +14,9 @@ "micro-bmark": "0.3.0", "micro-should": "0.4.0", "typescript": "5.0.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/hashes": { diff --git a/package.json b/package.json index 548e07e..60be320 100644 --- a/package.json +++ b/package.json @@ -54,10 +54,5 @@ "default": "./index.js" } }, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "funding": "https://paulmillr.com/funding/" } From 34939587a87fe26cfce9d9a95ee399172f9dfd89 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 14 Jun 2023 21:28:23 +0000 Subject: [PATCH 105/145] readme --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9f579e9..56a60b6 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,7 @@ and blog post > npm install @noble/secp256k1 -We support all major platforms and runtimes. -For node.js <= 18, a polyfill for `globalThis.crypto` is needed, see below. -For React Native, which doesn't implement webcrypto, you may need a [polyfill for crypto.getRandomValues](https://github.com/LinusU/react-native-get-random-values) and either a polyfill for webcrypto, or simply enabling synchronous methods. +We support all major platforms and runtimes. For node.js <= 18 and React Native, additional polyfills are needed: see below. ```js import * as secp from '@noble/secp256k1'; @@ -58,25 +56,37 @@ import * as secp from '@noble/secp256k1'; })(); ``` -Advanced examples: +Additional steps needed for some environments: ```ts -// Enable synchronous methods. +// 1. Enable synchronous methods. // Only async methods are available by default, to keep the library dependency-free. import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) -// secp.sign(msgHash, privKey); // sync methods can be used now +// Sync methods can be used now: +// secp.sign(msgHash, privKey); -// node.js 18 and earlier requires globalThis.crypto polyfill. +// 2. node.js 18 and earlier, needs globalThis.crypto polyfill import { webcrypto } from 'node:crypto'; // @ts-ignore if (!globalThis.crypto) globalThis.crypto = webcrypto; +// 3. React Native needs crypto.getRandomValues polyfill and sha512 +import 'react-native-get-random-values'; +import { hmac } from '@noble/hashes/hmac'; +import { sha256 } from '@noble/hashes/sha256'; +secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)); +secp.etc.hmacSha256Async = (k, ...m) => Promise.resolve(secp.etc.hmacSha256Sync(k, ...m)); +``` + +Advanced examples: secure signatures with additional entropy and openssl-compatible signatures: + +```ts // Enable OpenSSL compatibility. // OpenSSL allows to create malleable signatures, which are not compatible with BTC/ETH. // By default, `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n). -const signatureMalleable = secp.sign(msgHash, privKey, { lowS: false }); +secp.sign(msgHash, privKey, { lowS: false }); // Signatures with improved security, containing additional entropy. // Adds entropy to deterministic signature, follows section 3.6 of RFC6979. @@ -89,9 +99,10 @@ const signatureMalleable = secp.sign(msgHash, privKey, { lowS: false }); // - Sigs with extra entropy would have different `r` / `s`, which means they // would still be valid, but may break some test vectors if you're // cross-testing against other libs -const signatureImproved = secp.sign(msgHash, privKey, { extraEntropy: true }); +secp.sign(msgHash, privKey, { extraEntropy: true }); ``` + ## API There are 3 main methods: `getPublicKey(privateKey)`, From 9ff94ca727021715bce73838e52117af7bf75d53 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 14 Jun 2023 21:32:07 +0000 Subject: [PATCH 106/145] Crypto updates --- index.js | 14 ++++++-------- index.ts | 12 +++++------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/index.js b/index.js index f7bdaa4..47480b2 100644 --- a/index.js +++ b/index.js @@ -430,20 +430,18 @@ const etc = { concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, hmacSha256Async: async (key, ...msgs) => { - const crypto = cr(); // HMAC-SHA256 async. No sync built-in! - if (!crypto) - return err('etc.hmacSha256Async not set'); // Uses webcrypto: native cryptography. - const s = crypto.subtle; + const c = cr(); // async HMAC-SHA256, no sync built-in! + const s = c && c.subtle; // For React Native support, see README. + if (!s) + return err('etc.hmacSha256Async not set'); // Uses webcrypto built-in cryptography. const k = await s.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); return u8n(await s.sign('HMAC', k, concatB(...msgs))); }, hmacSha256Sync: _hmacSync, hashToPrivateKey, randomBytes: (len) => { - const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: - // import { webcrypto } from 'node:crypto'; - // if (!globalThis.crypto) globalThis.crypto = webcrypto; - if (!crypto) + const crypto = cr(); // Must be shimmed in node.js <= 18 to prevent error. See README. + if (!crypto || !crypto.getRandomValues) err('crypto.getRandomValues must be defined'); return crypto.getRandomValues(u8n(len)); }, diff --git a/index.ts b/index.ts index 8ba2ef9..40467c3 100644 --- a/index.ts +++ b/index.ts @@ -367,19 +367,17 @@ const etc = { // Not placed in utils b concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, mod, invert: inv, // math utilities hmacSha256Async: async (key: Bytes, ...msgs: Bytes[]): Promise => { - const crypto = cr(); // HMAC-SHA256 async. No sync built-in! - if (!crypto) return err('etc.hmacSha256Async not set'); // Uses webcrypto: native cryptography. - const s = crypto.subtle; + const c = cr(); // async HMAC-SHA256, no sync built-in! + const s = c && c.subtle; // For React Native support, see README. + if (!s) return err('etc.hmacSha256Async not set'); // Uses webcrypto built-in cryptography. const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); return u8n(await s.sign('HMAC', k, concatB(...msgs))); }, hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below hashToPrivateKey, randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) - const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: - // import { webcrypto } from 'node:crypto'; - // if (!globalThis.crypto) globalThis.crypto = webcrypto; - if (!crypto) err('crypto.getRandomValues must be defined'); + const crypto = cr(); // Must be shimmed in node.js <= 18 to prevent error. See README. + if (!crypto || !crypto.getRandomValues) err('crypto.getRandomValues must be defined'); return crypto.getRandomValues(u8n(len)); }, } From f795a8dfb116d0a8261c84f350a6a4afccb83dae Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 14 Jun 2023 22:11:21 +0000 Subject: [PATCH 107/145] readme rework --- README.md | 98 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 56a60b6..e12e0ab 100644 --- a/README.md +++ b/README.md @@ -80,47 +80,32 @@ secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m secp.etc.hmacSha256Async = (k, ...m) => Promise.resolve(secp.etc.hmacSha256Sync(k, ...m)); ``` -Advanced examples: secure signatures with additional entropy and openssl-compatible signatures: - -```ts -// Enable OpenSSL compatibility. -// OpenSSL allows to create malleable signatures, which are not compatible with BTC/ETH. -// By default, `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n). -secp.sign(msgHash, privKey, { lowS: false }); - -// Signatures with improved security, containing additional entropy. -// Adds entropy to deterministic signature, follows section 3.6 of RFC6979. -// When `true`, it would be filled with 32b from CSPRNG. -// **Strongly recommended** to use, to improve security: -// - No disadvantage: if an entropy generator is broken, sigs would be the same -// as they are without the option -// - It would help a lot in case there is an error somewhere in `k` gen. -// Exposing `k` could leak private keys -// - Sigs with extra entropy would have different `r` / `s`, which means they -// would still be valid, but may break some test vectors if you're -// cross-testing against other libs -secp.sign(msgHash, privKey, { extraEntropy: true }); -``` - - ## API There are 3 main methods: `getPublicKey(privateKey)`, `sign(messageHash, privateKey)` and `verify(signature, messageHash, publicKey)`. +We accept Hex type everywhere: -```typescript -type Hex = Uint8Array | string; +```ts +type Hex = Uint8Array | string +``` -// Generates public key from 32-byte private key. -// isCompressed=true by default, meaning 33-byte output. Set to false for 65b. +### getPublicKey + +```ts function getPublicKey(privateKey: Hex, isCompressed?: boolean): Uint8Array; -// Use: -// - `ProjectivePoint.fromPrivateKey(privateKey)` for Point instance -// - `ProjectivePoint.fromHex(publicKey)` to convert hex / bytes into Point. +``` + +Generates 33-byte compressed public key from 32-byte private key. -// Generates low-s deterministic-k RFC6979 ECDSA signature. -// Use with `extraEntropy: true` to improve security. +- If you need uncompressed 65-byte public key, set second argument to `false`. +- Use `ProjectivePoint.fromPrivateKey(privateKey)` for Point instance. +- Use `ProjectivePoint.fromHex(publicKey)` to convert Hex / Uint8Array into Point. + +### sign + +```ts function sign( messageHash: Hex, // message hash (not message) which would be signed privateKey: Hex, // private key which will sign the hash @@ -131,33 +116,64 @@ function signAsync( privateKey: Hex, opts?: { lowS: boolean; extraEntropy: boolean | Hex } ): Promise; +secp.sign(msgHash, privKey, { lowS: false }); // Malleable signature +secp.sign(msgHash, privKey, { extraEntropy: true }); // Improved security +``` -// Verifies ECDSA signature. -// lowS option Ensures a signature.s is in the lower-half of CURVE.n. -// Used in BTC, ETH. -// `{ lowS: false }` should only be used if you need OpenSSL-compatible signatures +Generates low-s deterministic-k RFC6979 ECDSA signature. + +1. `lowS: false` allows to create malleable signatures, for compatibility with openssl. + Default `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) and is compatible with BTC/ETH. +2. `extraEntropy: true` improves security by adding entropy, follows section 3.6 of RFC6979: + - No disadvantage: if an entropy generator is broken, sigs would be the same + as they are without the option + - It would help a lot in case there is an error somewhere in `k` gen. + Exposing `k` could leak private keys + - Sigs with extra entropy would have different `r` / `s`, which means they + would still be valid, but may break some test vectors if you're + cross-testing against other libs + +### verify + +```ts function verify( signature: Hex | Signature, // returned by the `sign` function messageHash: Hex, // message hash (not message) that must be verified publicKey: Hex, // public (not private) key opts?: { lowS: boolean } // optional params; { lowS: true } by default ): boolean; +``` + +Verifies ECDSA signature and ensures it has lowS (compatible with BTC/ETH). +`lowS: false` turns off malleability check, but makes it OpenSSL-compatible. -// Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between -// key A and different key B. +### getSharedSecret + +```ts function getSharedSecret( privateKeyA: Uint8Array | string, // Alices's private key publicKeyB: Uint8Array | string, // Bob's public key isCompressed = true // optional arg. (default) true=33b key, false=65b. ): Uint8Array; -// Use `ProjectivePoint.fromHex(publicKeyB).multiply(privateKeyA)` for Point instance +``` + +Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between +key A and different key B. + +Use `ProjectivePoint.fromHex(publicKeyB).multiply(privateKeyA)` for Point instance + +### recoverPublicKey -// Recover public key from Signature instance with `recovery` bit set +```ts signature.recoverPublicKey( msgHash: Uint8Array | string ): Uint8Array | undefined; ``` +Recover public key from Signature instance with `recovery` bit set. + +### utils + A bunch of useful **utilities** are also exposed: ```typescript @@ -269,13 +285,11 @@ Compare to other libraries on M1 (`openssl` uses native bindings, not JS): sjcl#sign x 199 ops/sec openssl#sign x 4,243 ops/sec ecdsa#sign x 116 ops/sec - bip-schnorr#sign x 60 ops/sec elliptic#verify x 812 ops/sec sjcl#verify x 166 ops/sec openssl#verify x 4,452 ops/sec ecdsa#verify x 80 ops/sec - bip-schnorr#verify x 56 ops/sec elliptic#ecdh x 971 ops/sec From eeb3b069e50b53aee7042a8b83a99f56e213a2de Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 14 Jun 2023 22:12:54 +0000 Subject: [PATCH 108/145] readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e12e0ab..4a29d3a 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,8 @@ secp.sign(msgHash, privKey, { lowS: false }); // Malleable signature secp.sign(msgHash, privKey, { extraEntropy: true }); // Improved security ``` -Generates low-s deterministic-k RFC6979 ECDSA signature. +Generates low-s deterministic-k RFC6979 ECDSA signature. Assumes hash of message, +which means you'll need to do something like `sha256(message)` before signing. 1. `lowS: false` allows to create malleable signatures, for compatibility with openssl. Default `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) and is compatible with BTC/ETH. From 317457dbcba69129b1746fae3fd05c54cab2823c Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 14 Jun 2023 22:21:15 +0000 Subject: [PATCH 109/145] randomBytes default 32 --- index.d.ts | 2 +- index.js | 2 +- index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index f17f615..00a5f8c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -85,7 +85,7 @@ declare const etc: { hmacSha256Async: (key: Bytes, ...msgs: Bytes[]) => Promise; hmacSha256Sync: HmacFnSync; hashToPrivateKey: typeof hashToPrivateKey; - randomBytes: (len: number) => Bytes; + randomBytes: (len?: number) => Bytes; }; declare const utils: { normPrivateKeyToScalar: (p: PrivKey) => bigint; diff --git a/index.js b/index.js index 47480b2..4f056af 100644 --- a/index.js +++ b/index.js @@ -439,7 +439,7 @@ const etc = { }, hmacSha256Sync: _hmacSync, hashToPrivateKey, - randomBytes: (len) => { + randomBytes: (len = 32) => { const crypto = cr(); // Must be shimmed in node.js <= 18 to prevent error. See README. if (!crypto || !crypto.getRandomValues) err('crypto.getRandomValues must be defined'); diff --git a/index.ts b/index.ts index 40467c3..e0f782b 100644 --- a/index.ts +++ b/index.ts @@ -375,7 +375,7 @@ const etc = { // Not placed in utils b }, hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below hashToPrivateKey, - randomBytes: (len: number): Bytes => { // CSPRNG (random number generator) + randomBytes: (len = 32): Bytes => { // CSPRNG (random number generator) const crypto = cr(); // Must be shimmed in node.js <= 18 to prevent error. See README. if (!crypto || !crypto.getRandomValues) err('crypto.getRandomValues must be defined'); return crypto.getRandomValues(u8n(len)); From fda9aedf04ac5f4f2c08751c20aa7e9122527a43 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 28 Jun 2023 14:04:30 +0000 Subject: [PATCH 110/145] Add README link to new library noble-ciphers --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a29d3a..1fdbe3b 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,10 @@ and blog post - No dependencies, protection against supply chain attacks - Auditable TypeScript / JS code -- Supported in all major browsers and stable node.js versions -- All releases are signed with PGP keys +- Supported on all major platforms +- Releases are signed with PGP keys and built transparently with NPM provenance - Check out [homepage](https://paulmillr.com/noble/) & all libraries: + [ciphers](https://github.com/paulmillr/noble-ciphers), [curves](https://github.com/paulmillr/noble-curves) (4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519)), From 493e28cd18f0ad89a1e5e5b1480577d384f7610d Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 12 Jul 2023 18:29:48 +0000 Subject: [PATCH 111/145] package.json: declare side-effects free --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 60be320..035dfef 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "main": "index.js", "module": "index.js", "types": "index.d.ts", + "sideEffects": false, "scripts": { "build": "tsc", "build:release": "rollup -c rollup.config.js", From 86bd7a39e34de3499f6a448a793b51d9fea291e5 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 16 Jul 2023 06:32:15 +0200 Subject: [PATCH 112/145] readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1fdbe3b..f1668c6 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ and blog post - Releases are signed with PGP keys and built transparently with NPM provenance - Check out [homepage](https://paulmillr.com/noble/) & all libraries: [ciphers](https://github.com/paulmillr/noble-ciphers), - [curves](https://github.com/paulmillr/noble-curves) - (4kb versions [secp256k1](https://github.com/paulmillr/noble-secp256k1), - [ed25519](https://github.com/paulmillr/noble-ed25519)), - [hashes](https://github.com/paulmillr/noble-hashes) + [curves](https://github.com/paulmillr/noble-curves), + [hashes](https://github.com/paulmillr/noble-hashes), + 4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) / + [ed25519](https://github.com/paulmillr/noble-ed25519) ## Usage From 3cff88f26589df21f0dff152ce4599b7a038c2fa Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 26 Jul 2023 08:59:43 +0000 Subject: [PATCH 113/145] Improve tsconfig strictness --- tsconfig.json | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 4edd974..dc5185a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,23 @@ { "compilerOptions": { - "strict": true, - "declaration": true, - "declarationMap": false, "target": "es2020", "lib": ["es2020"], "module": "es6", - "moduleResolution": "node", + "moduleResolution": "bundler", "outDir": ".", - "noImplicitAny": true, - "preserveConstEnums": true, "baseUrl": ".", + "sourceMap": false, + "declaration": true, + "declarationMap": false, + "strict": true, + "allowSyntheticDefaultImports": false, + "allowUnreachableCode": false, + "esModuleInterop": false, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noUncheckedIndexedAccess": false, + "noUnusedLocals": true, + "noUnusedParameters": true, }, "include": ["index.ts"], "exclude": ["node_modules", "lib"] From 257ba6a9b00934a7344044c6c32011bbaaa72867 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 26 Jul 2023 08:59:54 +0000 Subject: [PATCH 114/145] Adjust some comments --- index.js | 2 +- index.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 4f056af..b634592 100644 --- a/index.js +++ b/index.js @@ -455,7 +455,7 @@ const utils = { return false; } }, randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 8)), - precompute(w = 8, p = G) { p.multiply(3n); return p; }, // no-op + precompute(w = 8, p = G) { p.multiply(3n); w; return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) diff --git a/index.ts b/index.ts index e0f782b..01428d7 100644 --- a/index.ts +++ b/index.ts @@ -137,7 +137,7 @@ const h2b = (hex: string): Bytes => { // hex to bytes }; const b2n = (b: Bytes): bigint => BigInt('0x' + (b2h(b) || '0')); // bytes to number const slcNum = (b: Bytes, from: number, to: number) => b2n(b.slice(from, to)); // slice bytes num -const n2b = (num: bigint): Bytes => { // number to 32bytes. mustbe 0 <= num < B256 +const n2b = (num: bigint): Bytes => { // number to 32b. Must be 0 <= num < B256 return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected'); }; const n2h = (num: bigint): string => b2h(n2b(num)); // number to 32b hex @@ -381,13 +381,13 @@ const etc = { // Not placed in utils b return crypto.getRandomValues(u8n(len)); }, } -const utils = { // utilities +const utils = { // utilities normPrivateKeyToScalar: toPriv, isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. - precompute(w=8, p: Point = G) { p.multiply(3n); return p; }, // no-op + precompute(w=8, p: Point = G) { p.multiply(3n); w; return p; }, // no-op }; -Object.defineProperties(etc, { hmacSha256Sync: { // Allow setting it once, ignore then +Object.defineProperties(etc, { hmacSha256Sync: { // Allow setting it once, ignore then configurable: false, get() { return _hmacSync; }, set(f) { if (!_hmacSync) _hmacSync = f; }, } }); const W = 8; // Precomputes-related code. W = window size From 5a6c97ecb30021400b7e9f46aa13f41692596727 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 26 Jul 2023 09:05:36 +0000 Subject: [PATCH 115/145] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f1668c6..7c6f42a 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ import * as secp from '@noble/secp256k1'; })(); ``` -Additional steps needed for some environments: +Additional polyfills for some environments: ```ts // 1. Enable synchronous methods. @@ -68,7 +68,7 @@ secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m // Sync methods can be used now: // secp.sign(msgHash, privKey); -// 2. node.js 18 and earlier, needs globalThis.crypto polyfill +// 2. node.js 18 and earlier, requires polyfilling globalThis.crypto import { webcrypto } from 'node:crypto'; // @ts-ignore if (!globalThis.crypto) globalThis.crypto = webcrypto; From d45df86c5d280dde13bd4c3f284a98913a81c051 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 4 Sep 2023 15:24:22 +0000 Subject: [PATCH 116/145] Update security file, bump devdep --- SECURITY.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index 09977f8..7b0e03c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,5 +1,7 @@ # Security Policy +See [README's Security section](./README.md#security) for detailed description of internal security practices. + ## Supported Versions | Version | Supported | diff --git a/package.json b/package.json index 035dfef..d33de6c 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "license": "MIT", "devDependencies": { - "@noble/hashes": "1.3.0", + "@noble/hashes": "1.3.2", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", From a5fa6eed61a2e093852eeb92255fff292c994699 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 6 Sep 2023 20:23:15 +0200 Subject: [PATCH 117/145] readme --- README.md | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 7c6f42a..44fdc23 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,25 @@ # noble-secp256k1 -[Fastest](#speed) 4KB JS implementation of -secp256k1 [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman) & -[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) -signatures compliant with [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). - -If you're looking for additional features, -check out [noble-curves](https://github.com/paulmillr/noble-curves): -a drop-in replacement with common.js, Schnorr signatures, DER encoding and -support for different hash functions. - -Check out [Upgrading](#upgrading) section for v1 to v2 transition instructions, -[the online demo](https://paulmillr.com/noble/), -[secp256k1-node compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts) -and blog post -[Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). +Fastest 4KB JS implementation of secp256k1 signatures & ECDH. + +- ✍️ Deterministic [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) + signatures compliant with [RFC6979](https://www.rfc-editor.org/rfc/rfc6979) +- 🤝 Elliptic Curve Diffie-Hellman [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman) +- 🪶 4KB gzipped, 450 lines of code + +To upgrade from v1 to v2, see [Upgrading](#upgrading). +If you're looking for additional features (cjs, Schnorr signatures, DER encoding, support for different hash functions), +check out a drop-in replacement [noble-curves](https://github.com/paulmillr/noble-curves). +[Online demo](https://paulmillr.com/noble/). ### This library belongs to _noble_ crypto > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools. -- No dependencies, protection against supply chain attacks -- Auditable TypeScript / JS code +- Zero or minimal dependencies - Supported on all major platforms -- Releases are signed with PGP keys and built transparently with NPM provenance +- Highly readable TypeScript / JS code +- PGP-signed releases & transparent NPM builds with provenance - Check out [homepage](https://paulmillr.com/noble/) & all libraries: [ciphers](https://github.com/paulmillr/noble-ciphers), [curves](https://github.com/paulmillr/noble-curves), From 097b60b10805058355f49924d6a5c5746ee116c9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 7 Sep 2023 15:32:40 +0200 Subject: [PATCH 118/145] readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 44fdc23..8669458 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,8 @@ check out a drop-in replacement [noble-curves](https://github.com/paulmillr/nobl > **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools. - Zero or minimal dependencies -- Supported on all major platforms - Highly readable TypeScript / JS code -- PGP-signed releases & transparent NPM builds with provenance +- PGP-signed releases and transparent NPM builds with provenance - Check out [homepage](https://paulmillr.com/noble/) & all libraries: [ciphers](https://github.com/paulmillr/noble-ciphers), [curves](https://github.com/paulmillr/noble-curves), From b032053763c0d4ba107c18fee28344f64242b075 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 20 Sep 2023 23:33:35 +0200 Subject: [PATCH 119/145] readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8669458..aff012c 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Fastest 4KB JS implementation of secp256k1 signatures & ECDH. - ✍️ Deterministic [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) signatures compliant with [RFC6979](https://www.rfc-editor.org/rfc/rfc6979) - 🤝 Elliptic Curve Diffie-Hellman [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman) +- 📦 Pure ESM, can be imported without transpilers - 🪶 4KB gzipped, 450 lines of code To upgrade from v1 to v2, see [Upgrading](#upgrading). From a87a536c3cdf2b4ffd12611d3258302f44484874 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 25 Dec 2023 16:32:33 +0100 Subject: [PATCH 120/145] readme --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index aff012c..92c447b 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,8 @@ Fastest 4KB JS implementation of secp256k1 signatures & ECDH. - 📦 Pure ESM, can be imported without transpilers - 🪶 4KB gzipped, 450 lines of code -To upgrade from v1 to v2, see [Upgrading](#upgrading). -If you're looking for additional features (cjs, Schnorr signatures, DER encoding, support for different hash functions), -check out a drop-in replacement [noble-curves](https://github.com/paulmillr/noble-curves). -[Online demo](https://paulmillr.com/noble/). +If you're looking for additional features (common.js, Schnorr signatures, DER encoding, support for different hash functions), +check out a drop-in replacement [noble-curves](https://github.com/paulmillr/noble-curves). To upgrade from v1 to v2, see [Upgrading](#upgrading). ### This library belongs to _noble_ crypto @@ -113,8 +111,9 @@ function signAsync( privateKey: Hex, opts?: { lowS: boolean; extraEntropy: boolean | Hex } ): Promise; -secp.sign(msgHash, privKey, { lowS: false }); // Malleable signature -secp.sign(msgHash, privKey, { extraEntropy: true }); // Improved security + +sign(msgHash, privKey, { lowS: false }); // Malleable signature +sign(msgHash, privKey, { extraEntropy: true }); // Improved security ``` Generates low-s deterministic-k RFC6979 ECDSA signature. Assumes hash of message, From 95febd9ccb136ee95d18b5cd947c791fd8371f3b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 25 Jan 2024 12:16:49 +0100 Subject: [PATCH 121/145] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92c447b..ed9bb01 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Fastest 4KB JS implementation of secp256k1 signatures & ECDH. - 📦 Pure ESM, can be imported without transpilers - 🪶 4KB gzipped, 450 lines of code -If you're looking for additional features (common.js, Schnorr signatures, DER encoding, support for different hash functions), -check out a drop-in replacement [noble-curves](https://github.com/paulmillr/noble-curves). To upgrade from v1 to v2, see [Upgrading](#upgrading). +Use [noble-curves](https://github.com/paulmillr/noble-curves) instead, if you need additional features such as +common.js, Schnorr signatures, DER encoding, support for different hash functions. To upgrade from v1 to v2, see [Upgrading](#upgrading). ### This library belongs to _noble_ crypto From 24f89fd364f3f8ecf38571306fccbb62df77ffa9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 8 Feb 2024 17:03:53 +0100 Subject: [PATCH 122/145] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed9bb01..aa3e423 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Fastest 4KB JS implementation of secp256k1 signatures & ECDH. Use [noble-curves](https://github.com/paulmillr/noble-curves) instead, if you need additional features such as common.js, Schnorr signatures, DER encoding, support for different hash functions. To upgrade from v1 to v2, see [Upgrading](#upgrading). -### This library belongs to _noble_ crypto +### This library belongs to _noble_ cryptography -> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools. +> **noble-cryptography** — high-security, easily auditable set of contained cryptographic libraries and tools. - Zero or minimal dependencies - Highly readable TypeScript / JS code From d9aabe978d741e5e0da601c51b155b5e23b825ef Mon Sep 17 00:00:00 2001 From: Nathan HERVIER <113121626+Elli610@users.noreply.github.com> Date: Mon, 19 Feb 2024 20:04:53 +0100 Subject: [PATCH 123/145] noble-secp256k1 is not handling properly the point at infinity (#121) * fix Point.fromAffine * new build * formatting * new build * formatting & new build * Fix formatting --------- Co-authored-by: Elli610 Co-authored-by: Paul Miller --- index.js | 7 ++++++- index.ts | 5 ++++- package-lock.json | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index b634592..5b46e3b 100644 --- a/index.js +++ b/index.js @@ -26,7 +26,12 @@ class Point { this.py = py; this.pz = pz; } //3d=less inversions - static fromAffine(p) { return new Point(p.x, p.y, 1n); } + static fromAffine(p) { + if ((p.x === 0n) && (p.y === 0n)) + return new Point(0n, 1n, 0n); + else + return new Point(p.x, p.y, 1n); + } static fromHex(hex) { hex = toU8(hex); // convert hex string to Uint8Array let p = undefined; diff --git a/index.ts b/index.ts index 01428d7..773c48b 100644 --- a/index.ts +++ b/index.ts @@ -26,7 +26,10 @@ class Point { // Point in 3d xyz proje constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} //3d=less inversions static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point static readonly ZERO = new Point(0n, 1n, 0n); // Identity / zero point - static fromAffine(p: AffinePoint) { return new Point(p.x, p.y, 1n); } + static fromAffine (p: AffinePoint) { + if ((p.x === 0n) && (p.y === 0n)) return Point.ZERO; + else return new Point(p.x, p.y, 1n) ; + } static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // convert hex string to Uint8Array let p: Point | undefined = undefined; diff --git a/package-lock.json b/package-lock.json index a501d6f..03f8143 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.0.0", "license": "MIT", "devDependencies": { - "@noble/hashes": "1.3.0", + "@noble/hashes": "1.3.2", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", @@ -20,16 +20,16 @@ } }, "node_modules/@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/fast-check": { "version": "3.0.0", From a4e165aab59c5761a96fe6184b6e3a0264379345 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 5 Mar 2024 04:34:01 +0100 Subject: [PATCH 124/145] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aa3e423..dff6c40 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Fastest 4KB JS implementation of secp256k1 signatures & ECDH. - 📦 Pure ESM, can be imported without transpilers - 🪶 4KB gzipped, 450 lines of code -Use [noble-curves](https://github.com/paulmillr/noble-curves) instead, if you need additional features such as -common.js, Schnorr signatures, DER encoding, support for different hash functions. To upgrade from v1 to v2, see [Upgrading](#upgrading). +Use larger drop-in replacement [noble-curves](https://github.com/paulmillr/noble-curves) instead, +if you need additional features such as common.js, Schnorr signatures, DER encoding or support for different hash functions. To upgrade from v1 to v2, see [Upgrading](#upgrading). ### This library belongs to _noble_ cryptography From 48b27e54f48524ecd5b9cde9e28483603bfc5cf7 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:26:29 +0000 Subject: [PATCH 125/145] Improve u8a check. Add Sig#normalizeS --- index.d.ts | 1 + index.js | 25 +++++++++++++++---------- index.ts | 25 ++++++++++++++++--------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/index.d.ts b/index.d.ts index 00a5f8c..bdf1be8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -52,6 +52,7 @@ declare class Signature { assertValidity(): this; addRecoveryBit(rec: number): SignatureWithRecovery; hasHighS(): boolean; + normalizeS(): Signature; recoverPublicKey(msgh: Hex): Point; toCompactRawBytes(): Uint8Array; toCompactHex(): string; diff --git a/index.js b/index.js index 5b46e3b..3b62d6c 100644 --- a/index.js +++ b/index.js @@ -7,19 +7,20 @@ const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy }; // exported variables incl. a, b const fLen = 32; // field / group byte length const crv = (x) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 -const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n) => typeof n === 'bigint'; // is big integer const str = (s) => typeof s === 'string'; // is string const fe = (n) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n) => big(n) && 0n < n && n < N; // is group element -const au8 = (a, l) => // is Uint8Array (of specific length) - !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? +const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace +const isu8 = (a) => (a instanceof Uint8Array || + (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')); +const au8 = (a, l) => // assert is Uint8Array (of specific length) + !isu8(a) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data) => new Uint8Array(data); // creates Uint8Array -const toU8 = (a, len) => au8(str(a) ? h2b(a) : u8n(a), len); // norm(hex/u8a) to u8a +const toU8 = (a, len) => au8(str(a) ? h2b(a) : u8n(au8(a)), len); // norm(hex/u8a) to u8a const mod = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const isPoint = (p) => (p instanceof Point ? p : err('Point expected')); // is 3d point -let Gpows = undefined; // precomputes for base point G class Point { constructor(px, py, pz) { this.px = px; @@ -28,7 +29,7 @@ class Point { } //3d=less inversions static fromAffine(p) { if ((p.x === 0n) && (p.y === 0n)) - return new Point(0n, 1n, 0n); + return Point.ZERO; else return new Point(p.x, p.y, 1n); } @@ -234,11 +235,14 @@ class Signature { return new Signature(this.r, this.s, rec); } hasHighS() { return moreThanHalfN(this.s); } + normalizeS() { + return this.hasHighS() ? new Signature(this.r, mod(this.s, N), this.recovery) : this; + } recoverPublicKey(msgh) { const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 if (![0, 1, 2, 3].includes(rec)) err('recovery id invalid'); // check recovery id - const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash + const h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element @@ -416,7 +420,7 @@ function verify(sig, msgh, pub, opts = optV) { } if (!R) return false; // stop if R is identity / zero point - const v = mod(R.x, N); // <== The weird ECDSA part. R.x must be in N's field, not P's + const v = mod(R.x, N); // R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r } function getSharedSecret(privA, pubB, isCompressed = true) { @@ -427,7 +431,7 @@ function hashToPrivateKey(hash) { const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); - const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes + const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+16 bytes return n2b(num); } const etc = { @@ -459,7 +463,7 @@ const utils = { catch (e) { return false; } }, - randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 8)), + randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 16)), precompute(w = 8, p = G) { p.multiply(3n); w; return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { @@ -482,6 +486,7 @@ const precompute = () => { } // which multiplies user point by scalar, return points; // when precomputes are using base point }; +let Gpows = undefined; // precomputes for base point G const wNAF = (n) => { // Compared to other point mult methods, const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction diff --git a/index.ts b/index.ts index 773c48b..dec7cfc 100644 --- a/index.ts +++ b/index.ts @@ -8,19 +8,22 @@ const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy}; // exported variables in const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 -const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: unknown): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: unknown): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const au8 = (a: unknown, l?: number): Bytes => // is Uint8Array (of specific length) - !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? +const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace +const isu8 = (a: unknown): a is Uint8Array => ( + a instanceof Uint8Array || + (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array') +); +const au8 = (a: unknown, l?: number): Bytes => // assert is Uint8Array (of specific length) + !isu8(a) || (typeof l === 'number' && l > 0 && a.length !== l) ? err('Uint8Array expected') : a; const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array -const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : u8n(a), len); // norm(hex/u8a) to u8a +const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : u8n(au8(a)), len); // norm(hex/u8a) to u8a const mod = (a: bigint, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division const isPoint = (p: unknown) => (p instanceof Point ? p : err('Point expected')); // is 3d point -let Gpows: Point[] | undefined = undefined; // precomputes for base point G interface AffinePoint { x: bigint, y: bigint } // Point in 2d xy affine coordinates class Point { // Point in 3d xyz projective coordinates constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} //3d=less inversions @@ -190,10 +193,13 @@ class Signature { // ECDSA Signature class return new Signature(this.r, this.s, rec) as SignatureWithRecovery; } hasHighS() { return moreThanHalfN(this.s); } + normalizeS() { + return this.hasHighS() ? new Signature(this.r, mod(this.s, N), this.recovery) : this + } recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 if (![0, 1, 2, 3].includes(rec!)) err('recovery id invalid'); // check recovery id - const h = bits2int_modN(toU8(msgh, 32)); // Truncate hash + const h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash const radj = rec === 2 || rec === 3 ? r + N : r; // If rec was 2 or 3, q.x is bigger than n if (radj >= P) err('q.x invalid'); // ensure q.x is still a field element const head = (rec! & 1) === 0 ? '02' : '03'; // head is 0x02 or 0x03 @@ -265,7 +271,7 @@ function hmacDrbg(asynchronous: false): (seed: Bytes, predicate: Pred) => function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async let v = u8n(fLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. let k = u8n(fLen); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same - let i = 0; // Iterations counter, will throw when over 1000 + let i = 0; // Iterations counter, will throw when over 1000 const reset = () => { v.fill(1); k.fill(0); i = 0; }; const _e = 'drbg: tried 1000 values'; if (asynchronous) { // asynchronous=true @@ -352,7 +358,7 @@ function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { R = G.mulAddQUns(P, u1, u2).aff(); // R = u1⋅G + u2⋅P } catch (error) { return false; } if (!R) return false; // stop if R is identity / zero point - const v = mod(R.x, N); // <== The weird ECDSA part. R.x must be in N's field, not P's + const v = mod(R.x, N); // R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r } function getSharedSecret(privA: Hex, pubB: Hex, isCompressed = true): Bytes { @@ -387,7 +393,7 @@ const etc = { // Not placed in utils b const utils = { // utilities normPrivateKeyToScalar: toPriv, isValidPrivateKey: (key: Hex) => { try { return !!toPriv(key); } catch (e) { return false; } }, - randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 8)), // FIPS 186 B.4.1. + randomPrivateKey: (): Bytes => hashToPrivateKey(etc.randomBytes(fLen + 16)), // FIPS 186 B.4.1. precompute(w=8, p: Point = G) { p.multiply(3n); w; return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { // Allow setting it once, ignore then @@ -406,6 +412,7 @@ const precompute = () => { // They give 12x faster } // which multiplies user point by scalar, return points; // when precomputes are using base point } +let Gpows: Point[] | undefined = undefined; // precomputes for base point G const wNAF = (n: bigint): { p: Point; f: Point } => { // w-ary non-adjacent form (wNAF) method. // Compared to other point mult methods, const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction From bc913473e6edf7759ac4d5da09da654aa3bf10aa Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:33:59 +0000 Subject: [PATCH 126/145] verify: remove length check in msg u8a to match noble-curves --- index.js | 4 ++-- index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 3b62d6c..d16e426 100644 --- a/index.js +++ b/index.js @@ -397,7 +397,7 @@ function verify(sig, msgh, pub, opts = optV) { err('signature must be 64 bytes'); try { sig_ = rs ? new Signature(sig.r, sig.s).assertValidity() : Signature.fromCompact(sig); - h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash + h = bits2int_modN(toU8(msgh)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { @@ -431,7 +431,7 @@ function hashToPrivateKey(hash) { const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); - const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+16 bytes + const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); } const etc = { diff --git a/index.ts b/index.ts index dec7cfc..6453fdf 100644 --- a/index.ts +++ b/index.ts @@ -344,7 +344,7 @@ function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { err('signature must be 64 bytes'); try { sig_ = rs ? new Signature(sig.r, sig.s).assertValidity() : Signature.fromCompact(sig); - h = bits2int_modN(toU8(msgh, fLen)); // Truncate hash + h = bits2int_modN(toU8(msgh)); // Truncate hash P = pub instanceof Point ? pub.ok() : Point.fromHex(pub); // Validate public key } catch (e) { return false; } // Check sig for validity in both cases if (!sig_) return false; From ebec017441702a8b8a964c0b51dfccefef907ecb Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:34:18 +0000 Subject: [PATCH 127/145] test: add basic.test.js from noble-curves that tests types --- package.json | 2 +- test/basic.test.js | 405 +++++++++++++++++++++++++++++++++++++++++++++ test/index.test.js | 5 + 3 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 test/basic.test.js create mode 100644 test/index.test.js diff --git a/package.json b/package.json index d33de6c..62f07f9 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "scripts": { "build": "tsc", "build:release": "rollup -c rollup.config.js", - "test": "node test/secp256k1.test.js", + "test": "node test/index.test.js", "test:webcrypto": "node test/secp256k1.webcrypto.test.js", "bench": "node test/benchmark.js", "min": "cd test/build; npm install; npm run terser", diff --git a/test/basic.test.js b/test/basic.test.js new file mode 100644 index 0000000..175be1d --- /dev/null +++ b/test/basic.test.js @@ -0,0 +1,405 @@ +import { deepStrictEqual, throws } from 'node:assert'; +import { should, describe } from 'micro-should'; +import * as fc from 'fast-check'; +import * as secp256k1 from '../index.js'; +import * as h from './secp256k1.helpers.js'; + +const CURVES = { secp256k1 } +const name = 'secp256k1'; +const C = CURVES[name]; +const CURVE_ORDER = C.CURVE.n; +const FC_BIGINT = fc.bigInt(1n + 1n, CURVE_ORDER - 1n); +const NUM_RUNS = 5; + +const getXY = (p) => ({ x: p.x, y: p.y }); +const toHex = secp256k1.etc.bytesToHex; + +function equal(a, b, comment) { + deepStrictEqual(a.equals(b), true, `eq(${comment})`); + if (a.toAffine && b.toAffine) { + deepStrictEqual(getXY(a.toAffine()), getXY(b.toAffine()), `eqToAffine(${comment})`); + } else if (!a.toAffine && !b.toAffine) { + // Already affine + deepStrictEqual(getXY(a), getXY(b), `eqAffine(${comment})`); + } else throw new Error('Different point types'); +} + +// Check that curve doesn't accept points from other curves +const POINTS = {}; + +for (const pointName in POINTS) { + const p = POINTS[pointName]; + if (!p) continue; + + const G = [p.ZERO, p.BASE]; + for (let i = 2n; i < 10n; i++) G.push(G[1].multiply(i)); + const title = `${name}/${pointName}`; + describe(title, () => { + describe('basic group laws', () => { + // Here we check basic group laws, to verify that points works as group + should('zero', () => { + equal(G[0].double(), G[0], '(0*G).double() = 0'); + equal(G[0].add(G[0]), G[0], '0*G + 0*G = 0'); + equal(G[0].subtract(G[0]), G[0], '0*G - 0*G = 0'); + equal(G[0].negate(), G[0], '-0 = 0'); + for (let i = 0; i < G.length; i++) { + const p = G[i]; + equal(p, p.add(G[0]), `${i}*G + 0 = ${i}*G`); + equal(G[0].multiply(BigInt(i + 1)), G[0], `${i + 1}*0 = 0`); + } + }); + should('one', () => { + equal(G[1].double(), G[2], '(1*G).double() = 2*G'); + equal(G[1].subtract(G[1]), G[0], '1*G - 1*G = 0'); + equal(G[1].add(G[1]), G[2], '1*G + 1*G = 2*G'); + }); + should('sanity tests', () => { + equal(G[2].double(), G[4], '(2*G).double() = 4*G'); + equal(G[2].add(G[2]), G[4], '2*G + 2*G = 4*G'); + equal(G[7].add(G[3].negate()), G[4], '7*G - 3*G = 4*G'); + }); + should('add commutativity', () => { + equal(G[4].add(G[3]), G[3].add(G[4]), '4*G + 3*G = 3*G + 4*G'); + equal(G[4].add(G[3]), G[3].add(G[2]).add(G[2]), '4*G + 3*G = 3*G + 2*G + 2*G'); + }); + should('double', () => { + equal(G[3].double(), G[6], '(3*G).double() = 6*G'); + }); + should('multiply', () => { + equal(G[2].multiply(3n), G[6], '(2*G).multiply(3) = 6*G'); + }); + should('add same-point', () => { + equal(G[3].add(G[3]), G[6], '3*G + 3*G = 6*G'); + }); + should('add same-point negative', () => { + equal(G[3].add(G[3].negate()), G[0], '3*G + (- 3*G) = 0*G'); + equal(G[3].subtract(G[3]), G[0], '3*G - 3*G = 0*G'); + }); + should('mul by curve order', () => { + equal(G[1].multiply(CURVE_ORDER - 1n).add(G[1]), G[0], '(N-1)*G + G = 0'); + equal(G[1].multiply(CURVE_ORDER - 1n).add(G[2]), G[1], '(N-1)*G + 2*G = 1*G'); + equal(G[1].multiply(CURVE_ORDER - 2n).add(G[2]), G[0], '(N-2)*G + 2*G = 0'); + const half = CURVE_ORDER / 2n; + const carry = CURVE_ORDER % 2n === 1n ? G[1] : G[0]; + equal(G[1].multiply(half).double().add(carry), G[0], '((N/2) * G).double() = 0'); + }); + should('inversion', () => { + const a = 1234n; + const b = 5678n; + const c = a * b; + equal(G[1].multiply(a).multiply(b), G[1].multiply(c), 'a*b*G = c*G'); + const inv = mod.invert(b, CURVE_ORDER); + equal(G[1].multiply(c).multiply(inv), G[1].multiply(a), 'c*G * (1/b)*G = a*G'); + }); + should('multiply, rand', () => + fc.assert( + fc.property(FC_BIGINT, FC_BIGINT, (a, b) => { + const c = mod.mod(a + b, CURVE_ORDER); + if (c === CURVE_ORDER || c < 1n) return; + const pA = G[1].multiply(a); + const pB = G[1].multiply(b); + const pC = G[1].multiply(c); + equal(pA.add(pB), pB.add(pA), 'pA + pB = pB + pA'); + equal(pA.add(pB), pC, 'pA + pB = pC'); + }), + { numRuns: NUM_RUNS } + ) + ); + should('multiply2, rand', () => + fc.assert( + fc.property(FC_BIGINT, FC_BIGINT, (a, b) => { + const c = mod.mod(a * b, CURVE_ORDER); + const pA = G[1].multiply(a); + const pB = G[1].multiply(b); + equal(pA.multiply(b), pB.multiply(a), 'b*pA = a*pB'); + equal(pA.multiply(b), G[1].multiply(c), 'b*pA = c*G'); + }), + { numRuns: NUM_RUNS } + ) + ); + }); + + for (const op of ['add', 'subtract']) { + describe(op, () => { + should('type check', () => { + throws(() => G[1][op](0), '0'); + throws(() => G[1][op](0n), '0n'); + G[1][op](G[2]); + throws(() => G[1][op](CURVE_ORDER), 'CURVE_ORDER'); + throws(() => G[1][op](-123n), '-123n'); + throws(() => G[1][op](123), '123'); + throws(() => G[1][op](123.456), '123.456'); + throws(() => G[1][op](true), 'true'); + throws(() => G[1][op](false), 'false'); + throws(() => G[1][op](null), 'null'); + throws(() => G[1][op](undefined), 'undefined'); + throws(() => G[1][op]('1'), "'1'"); + throws(() => G[1][op]({ x: 1n, y: 1n }), '{ x: 1n, y: 1n }'); + throws(() => G[1][op]({ x: 1n, y: 1n, z: 1n }), '{ x: 1n, y: 1n, z: 1n }'); + throws( + () => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }), + '{ x: 1n, y: 1n, z: 1n, t: 1n }' + ); + throws(() => G[1][op](new Uint8Array([])), 'ui8a([])'); + throws(() => G[1][op](new Uint8Array([0])), 'ui8a([0])'); + throws(() => G[1][op](new Uint8Array([1])), 'ui8a([1])'); + throws(() => G[1][op](new Uint8Array(4096).fill(1)), 'ui8a(4096*[1])'); + // if (G[1].toAffine) throws(() => G[1][op](C.Point.BASE), `Point ${op} ${pointName}`); + throws(() => G[1][op](o.BASE), `${op}/other curve point`); + }); + }); + } + + should('equals type check', () => { + throws(() => G[1].equals(0), '0'); + throws(() => G[1].equals(0n), '0n'); + deepStrictEqual(G[1].equals(G[2]), false, '1*G != 2*G'); + deepStrictEqual(G[1].equals(G[1]), true, '1*G == 1*G'); + deepStrictEqual(G[2].equals(G[2]), true, '2*G == 2*G'); + throws(() => G[1].equals(CURVE_ORDER), 'CURVE_ORDER'); + throws(() => G[1].equals(123.456), '123.456'); + throws(() => G[1].equals(true), 'true'); + throws(() => G[1].equals('1'), "'1'"); + throws(() => G[1].equals({ x: 1n, y: 1n, z: 1n, t: 1n }), '{ x: 1n, y: 1n, z: 1n, t: 1n }'); + throws(() => G[1].equals(new Uint8Array([])), 'ui8a([])'); + throws(() => G[1].equals(new Uint8Array([0])), 'ui8a([0])'); + throws(() => G[1].equals(new Uint8Array([1])), 'ui8a([1])'); + throws(() => G[1].equals(new Uint8Array(4096).fill(1)), 'ui8a(4096*[1])'); + // if (G[1].toAffine) throws(() => G[1].equals(C.Point.BASE), 'Point.equals(${pointName})'); + throws(() => G[1].equals(o.BASE), 'other curve point'); + }); + + for (const op of ['multiply', 'multiplyUnsafe']) { + if (!p.BASE[op]) continue; + describe(op, () => { + should('type check', () => { + if (op !== 'multiplyUnsafe') { + throws(() => G[1][op](0), '0'); + throws(() => G[1][op](0n), '0n'); + } + G[1][op](1n); + G[1][op](CURVE_ORDER - 1n); + throws(() => G[1][op](G[2]), 'G[2]'); + throws(() => G[1][op](CURVE_ORDER), 'CURVE_ORDER'); + throws(() => G[1][op](CURVE_ORDER + 1n), 'CURVE_ORDER+1'); + throws(() => G[1][op](123.456), '123.456'); + throws(() => G[1][op](true), 'true'); + throws(() => G[1][op]('1'), '1'); + throws(() => G[1][op](new Uint8Array([])), 'ui8a([])'); + throws(() => G[1][op](new Uint8Array([0])), 'ui8a([0])'); + throws(() => G[1][op](new Uint8Array([1])), 'ui8a([1])'); + throws(() => G[1][op](new Uint8Array(4096).fill(1)), 'ui8a(4096*[1])'); + throws(() => G[1][op](o.BASE), 'other curve point'); + }); + }); + } + // Complex point (Extended/Jacobian/Projective?) + // if (p.BASE.toAffine && C.Point) { + // should('toAffine()', () => { + // equal(p.ZERO.toAffine(), C.Point.ZERO, '0 = 0'); + // equal(p.BASE.toAffine(), C.Point.BASE, '1 = 1'); + // }); + // } + // if (p.fromAffine && C.Point) { + // should('fromAffine()', () => { + // equal(p.ZERO, p.fromAffine(C.Point.ZERO), '0 = 0'); + // equal(p.BASE, p.fromAffine(C.Point.BASE), '1 = 1'); + // }); + // } + // toHex/fromHex (if available) + if (p.fromHex && p.BASE.toHex) { + should('fromHex(toHex()) roundtrip', () => { + fc.assert( + fc.property(FC_BIGINT, (x) => { + const point = p.BASE.multiply(x); + const hex = point.toHex(); + const bytes = point.toRawBytes(); + deepStrictEqual(p.fromHex(hex).toHex(), hex); + deepStrictEqual(p.fromHex(bytes).toHex(), hex); + }) + ); + }); + should('fromHex(toHex(compressed=true)) roundtrip', () => { + fc.assert( + fc.property(FC_BIGINT, (x) => { + const point = p.BASE.multiply(x); + const hex = point.toHex(true); + const bytes = point.toRawBytes(true); + deepStrictEqual(p.fromHex(hex).toHex(true), hex); + deepStrictEqual(p.fromHex(bytes).toHex(true), hex); + }) + ); + }); + } + }); +} +describe(name, () => { + if (['bn254', 'pallas', 'vesta'].includes(name)) return; + // Generic complex things (getPublicKey/sign/verify/getSharedSecret) + should('.getPublicKey() type check', () => { + throws(() => C.getPublicKey(0), '0'); + throws(() => C.getPublicKey(0n), '0n'); + throws(() => C.getPublicKey(-123n), '-123n'); + throws(() => C.getPublicKey(123), '123'); + throws(() => C.getPublicKey(123.456), '123.456'); + throws(() => C.getPublicKey(true), 'true'); + throws(() => C.getPublicKey(false), 'false'); + throws(() => C.getPublicKey(null), 'null'); + throws(() => C.getPublicKey(undefined), 'undefined'); + throws(() => C.getPublicKey(''), "''"); + // NOTE: passes because of disabled hex padding checks for starknet, maybe enable? + // throws(() => C.getPublicKey('1'), "'1'"); + throws(() => C.getPublicKey('key'), "'key'"); + throws(() => C.getPublicKey({})); + throws(() => C.getPublicKey(new Uint8Array([]))); + throws(() => C.getPublicKey(new Uint8Array([0]))); + throws(() => C.getPublicKey(new Uint8Array([1]))); + throws(() => C.getPublicKey(new Uint8Array(4096).fill(1))); + throws(() => C.getPublicKey(Array(32).fill(1))); + }); + should('.verify() should verify random signatures', () => + fc.assert( + fc.property(fc.hexaString({ minLength: 64, maxLength: 64 }), (msg) => { + const priv = C.utils.randomPrivateKey(); + const pub = C.getPublicKey(priv); + const sig = C.sign(msg, priv); + const err = `priv=${toHex(priv)},pub=${toHex(pub)},msg=${msg}`; + deepStrictEqual( + C.verify(sig, msg, pub), + true, + err + ); + }), + { numRuns: NUM_RUNS } + ) + ); + should('.verify() should verify empty signatures', () => { + const msg = new Uint8Array([]); + const priv = C.utils.randomPrivateKey(); + const pub = C.getPublicKey(priv); + const sig = C.sign(msg, priv); + deepStrictEqual( + C.verify(sig, msg, pub), + true, + `priv=${toHex(priv)},pub=${toHex(pub)},msg=${msg}` + ); + }); + should('.sign() edge cases', () => { + throws(() => C.sign()); + throws(() => C.sign('')); + throws(() => C.sign('', '')); + throws(() => C.sign(new Uint8Array(), new Uint8Array())); + }); + + describe('verify()', () => { + const msg = '01'.repeat(32); + should('true for proper signatures', () => { + const priv = C.utils.randomPrivateKey(); + const sig = C.sign(msg, priv); + const pub = C.getPublicKey(priv); + deepStrictEqual(C.verify(sig, msg, pub), true); + }); + should('false for wrong messages', () => { + const priv = C.utils.randomPrivateKey(); + const sig = C.sign(msg, priv); + const pub = C.getPublicKey(priv); + deepStrictEqual(C.verify(sig, '11'.repeat(32), pub), false); + }); + should('false for wrong keys', () => { + const priv = C.utils.randomPrivateKey(); + const sig = C.sign(msg, priv); + deepStrictEqual(C.verify(sig, msg, C.getPublicKey(C.utils.randomPrivateKey())), false); + }); + }); + if (C.Signature) { + should('Signature serialization roundtrip', () => + fc.assert( + fc.property(fc.hexaString({ minLength: 64, maxLength: 64 }), (msg) => { + const priv = C.utils.randomPrivateKey(); + const sig = C.sign(msg, priv); + const sigRS = (sig) => ({ s: sig.s, r: sig.r }); + // Compact + deepStrictEqual(sigRS(C.Signature.fromCompact(sig.toCompactHex())), sigRS(sig)); + deepStrictEqual(sigRS(C.Signature.fromCompact(sig.toCompactRawBytes())), sigRS(sig)); + // DER + // deepStrictEqual(sigRS(C.Signature.fromDER(sig.toDERHex())), sigRS(sig)); + // deepStrictEqual(sigRS(C.Signature.fromDER(sig.toDERRawBytes())), sigRS(sig)); + }), + { numRuns: NUM_RUNS } + ) + ); + should('Signature.addRecoveryBit/Signature.recoveryPublicKey', () => + fc.assert( + fc.property(fc.hexaString({ minLength: 64, maxLength: 64 }), (msg) => { + const priv = C.utils.randomPrivateKey(); + const pub = C.getPublicKey(priv); + const sig = C.sign(msg, priv); + deepStrictEqual(sig.recoverPublicKey(msg).toRawBytes(), pub); + const sig2 = C.Signature.fromCompact(sig.toCompactHex()); + throws(() => sig2.recoverPublicKey(msg)); + const sig3 = sig2.addRecoveryBit(sig.recovery); + deepStrictEqual(sig3.recoverPublicKey(msg).toRawBytes(), pub); + }), + { numRuns: NUM_RUNS } + ) + ); + should('Signature.normalizeS', () => + fc.assert( + fc.property(fc.hexaString({ minLength: 64, maxLength: 64 }), (msg) => { + const priv = C.utils.randomPrivateKey(); + const pub = C.getPublicKey(priv); + const sig = C.sign(msg, priv); + const sig2 = sig.normalizeS(); + deepStrictEqual(sig2.hasHighS(), false); + }), + { numRuns: NUM_RUNS } + ) + ); + } + + // NOTE: fails for ed, because of empty message. Since we convert it to scalar, + // need to check what other implementations do. Empty message != new Uint8Array([0]), but what scalar should be in that case? + // should('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 })), + // (bytes, wrongBytes) => { + // const privKey = C.utils.randomPrivateKey(); + // const message = new Uint8Array(bytes); + // const wrongMessage = new Uint8Array(wrongBytes); + // const publicKey = C.getPublicKey(privKey); + // const signature = C.sign(message, privKey); + // deepStrictEqual( + // C.verify(signature, wrongMessage, publicKey), + // bytes.toString() === wrongBytes.toString() + // ); + // } + // ), + // { numRuns: NUM_RUNS } + // ); + // }); + + if (C.getSharedSecret) { + should('getSharedSecret() should be commutative', () => { + for (let i = 0; i < NUM_RUNS; i++) { + const asec = C.utils.randomPrivateKey(); + const apub = C.getPublicKey(asec); + const bsec = C.utils.randomPrivateKey(); + const bpub = C.getPublicKey(bsec); + try { + deepStrictEqual(C.getSharedSecret(asec, bpub), C.getSharedSecret(bsec, apub)); + } catch (error) { + console.error('not commutative', { asec, apub, bsec, bpub }); + throw error; + } + } + }); + } +}); + +// ESM is broken. +import url from 'url'; +if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { + should.run(); +} diff --git a/test/index.test.js b/test/index.test.js new file mode 100644 index 0000000..62b9695 --- /dev/null +++ b/test/index.test.js @@ -0,0 +1,5 @@ +import { should } from 'micro-should'; +import * as t1 from './basic.test.js'; +import * as t2 from './secp256k1.test.js'; + +should.run(); \ No newline at end of file From 85f220b2e2557d64db0aee721586673a31824de9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:45:27 +0000 Subject: [PATCH 128/145] Update build steps to use jsbt --- .github/workflows/nodejs-polyfill.yml | 23 +++++++++++++ .github/workflows/nodejs.yml | 47 ++++++++++----------------- .github/workflows/publish-npm.yml | 42 ++++++++++++------------ README.md | 4 ++- index.js | 8 ++--- package-lock.json | 28 +++++++++++----- package.json | 5 +-- tsconfig.json | 19 ++--------- 8 files changed, 92 insertions(+), 84 deletions(-) create mode 100644 .github/workflows/nodejs-polyfill.yml diff --git a/.github/workflows/nodejs-polyfill.yml b/.github/workflows/nodejs-polyfill.yml new file mode 100644 index 0000000..390443f --- /dev/null +++ b/.github/workflows/nodejs-polyfill.yml @@ -0,0 +1,23 @@ +name: Run node.js tests with polyfill +on: + - push + - pull_request +jobs: + test: + name: v${{ matrix.node }} @ ubuntu-latest + runs-on: ubuntu-latest + strategy: + matrix: + node: + - 18 + - 20 + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: ${{ matrix.node }} + - run: npm install + - run: npm run build --if-present + - run: npm test:webcrypto + - run: npm run lint --if-present diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 10806fa..81bf353 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,36 +1,23 @@ -name: Node CI - -on: [push, pull_request] +name: Run node.js tests +on: + - push + - pull_request jobs: test: - name: node @ ubuntu-latest + name: v${{ matrix.node }} @ ubuntu-latest runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x] + node: + - 18 + - 20 steps: - - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm run build --if-present - - run: npm test - - run: npm run lint --if-present - test-polyfill: - name: node+webcrypto @ ubuntu-latest - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [16.x, 18.x, 20.x] - steps: - - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm run build --if-present - - run: npm run test:webcrypto - - run: npm run lint --if-present + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: ${{ matrix.node }} + - run: npm install + - run: npm run build --if-present + - run: npm test + - run: npm run lint --if-present diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 3438a7f..cd57db8 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -1,23 +1,23 @@ -name: Publish Package to npm +name: Publish package to npm on: - release: - types: [created] + release: + types: [created] jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 - - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 - with: - node-version: 20 - registry-url: 'https://registry.npmjs.org' - cache: npm - - run: npm install -g npm - - run: npm ci - - run: npm run build - - run: npm publish --provenance --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + build: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install -g npm + - run: npm ci + - run: npm run build + - run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} diff --git a/README.md b/README.md index dff6c40..f4e0a5d 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ if you need additional features such as common.js, Schnorr signatures, DER encod [ciphers](https://github.com/paulmillr/noble-ciphers), [curves](https://github.com/paulmillr/noble-curves), [hashes](https://github.com/paulmillr/noble-hashes), + [post-quantum](https://github.com/paulmillr/noble-post-quantum), 4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) / [ed25519](https://github.com/paulmillr/noble-ed25519) @@ -62,7 +63,7 @@ secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m // Sync methods can be used now: // secp.sign(msgHash, privKey); -// 2. node.js 18 and earlier, requires polyfilling globalThis.crypto +// 2. node.js 18 and older, requires polyfilling globalThis.crypto import { webcrypto } from 'node:crypto'; // @ts-ignore if (!globalThis.crypto) globalThis.crypto = webcrypto; @@ -221,6 +222,7 @@ class Signature { readonly recovery?: number | undefined; ok(): Signature; hasHighS(): boolean; + normalizeS(): Signature; recoverPublicKey(msgh: Hex): Point; toCompactRawBytes(): Bytes; toCompactHex(): string; diff --git a/index.js b/index.js index d16e426..5fced2b 100644 --- a/index.js +++ b/index.js @@ -435,9 +435,9 @@ function hashToPrivateKey(hash) { return n2b(num); } const etc = { - hexToBytes: h2b, bytesToHex: b2h, + hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, - mod, invert: inv, + mod, invert: inv, // math utilities hmacSha256Async: async (key, ...msgs) => { const c = cr(); // async HMAC-SHA256, no sync built-in! const s = c && c.subtle; // For React Native support, see README. @@ -446,7 +446,7 @@ const etc = { const k = await s.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); return u8n(await s.sign('HMAC', k, concatB(...msgs))); }, - hmacSha256Sync: _hmacSync, + hmacSha256Sync: _hmacSync, // For TypeScript. Actual logic is below hashToPrivateKey, randomBytes: (len = 32) => { const crypto = cr(); // Must be shimmed in node.js <= 18 to prevent error. See README. @@ -463,7 +463,7 @@ const utils = { catch (e) { return false; } }, - randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 16)), + randomPrivateKey: () => hashToPrivateKey(etc.randomBytes(fLen + 16)), // FIPS 186 B.4.1. precompute(w = 8, p = G) { p.multiply(3n); w; return p; }, // no-op }; Object.defineProperties(etc, { hmacSha256Sync: { diff --git a/package-lock.json b/package-lock.json index 03f8143..08d348c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,20 +9,21 @@ "version": "2.0.0", "license": "MIT", "devDependencies": { - "@noble/hashes": "1.3.2", + "@noble/hashes": "1.4.0", + "@paulmillr/jsbt": "0.1.0", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", - "typescript": "5.0.2" + "typescript": "5.3.2" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, "engines": { "node": ">= 16" @@ -31,6 +32,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@paulmillr/jsbt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@paulmillr/jsbt/-/jsbt-0.1.0.tgz", + "integrity": "sha512-TdowoHD36hkZARv6LW4jenkVTdK2vP0sy4ZM8E9MxaqAAIRdwmn3RlB+zWkEHi4hKTgLqMGkURfNkFtt0STX2Q==", + "dev": true, + "bin": { + "jsbt": "jsbt.js" + } + }, "node_modules/fast-check": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.0.0.tgz", @@ -76,16 +86,16 @@ ] }, "node_modules/typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.20" + "node": ">=14.17" } } } diff --git a/package.json b/package.json index 62f07f9..3245b46 100644 --- a/package.json +++ b/package.json @@ -29,11 +29,12 @@ }, "license": "MIT", "devDependencies": { - "@noble/hashes": "1.3.2", + "@noble/hashes": "1.4.0", + "@paulmillr/jsbt": "0.1.0", "fast-check": "3.0.0", "micro-bmark": "0.3.0", "micro-should": "0.4.0", - "typescript": "5.0.2" + "typescript": "5.3.2" }, "keywords": [ "secp256k1", diff --git a/tsconfig.json b/tsconfig.json index dc5185a..ca1e717 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,23 +1,8 @@ { + "extends": "@paulmillr/jsbt/tsconfigs/esm.json", "compilerOptions": { - "target": "es2020", - "lib": ["es2020"], - "module": "es6", - "moduleResolution": "bundler", "outDir": ".", - "baseUrl": ".", - "sourceMap": false, - "declaration": true, - "declarationMap": false, - "strict": true, - "allowSyntheticDefaultImports": false, - "allowUnreachableCode": false, - "esModuleInterop": false, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "noUncheckedIndexedAccess": false, - "noUnusedLocals": true, - "noUnusedParameters": true, + "sourceMap": false }, "include": ["index.ts"], "exclude": ["node_modules", "lib"] From ee3e7439245bcaffed3eae57a4da502dba5378a9 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:47:55 +0000 Subject: [PATCH 129/145] build min: update terser --- test/build/package-lock.json | 60 ++++++++++++++++++------------------ test/build/package.json | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/test/build/package-lock.json b/test/build/package-lock.json index b3f326c..9b527de 100644 --- a/test/build/package-lock.json +++ b/test/build/package-lock.json @@ -9,65 +9,65 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "terser": "5.16.6" + "terser": "5.29.2" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/acorn": { @@ -114,13 +114,13 @@ } }, "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "version": "5.29.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", + "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, diff --git a/test/build/package.json b/test/build/package.json index 408095d..eef0f24 100644 --- a/test/build/package.json +++ b/test/build/package.json @@ -11,6 +11,6 @@ "author": "", "license": "MIT", "devDependencies": { - "terser": "5.16.6" + "terser": "5.29.2" } } From 3f9209d3876513de1d2efaea593f818c3303c13a Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:48:57 +0000 Subject: [PATCH 130/145] Remove node 18 from non-polyfilled test --- .github/workflows/nodejs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 81bf353..dae21a7 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -9,7 +9,6 @@ jobs: strategy: matrix: node: - - 18 - 20 steps: - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 From 7f49554bc804c0d2e74d765cdac437f25ad4f515 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:52:15 +0000 Subject: [PATCH 131/145] Comment clarifying fromAffine --- index.js | 5 +---- index.ts | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 5fced2b..452cd3a 100644 --- a/index.js +++ b/index.js @@ -28,10 +28,7 @@ class Point { this.pz = pz; } //3d=less inversions static fromAffine(p) { - if ((p.x === 0n) && (p.y === 0n)) - return Point.ZERO; - else - return new Point(p.x, p.y, 1n); + return ((p.x === 0n) && (p.y === 0n)) ? Point.ZERO : new Point(p.x, p.y, 1n); } static fromHex(hex) { hex = toU8(hex); // convert hex string to Uint8Array diff --git a/index.ts b/index.ts index 6453fdf..ca5e159 100644 --- a/index.ts +++ b/index.ts @@ -29,9 +29,8 @@ class Point { // Point in 3d xyz proje constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) {} //3d=less inversions static readonly BASE = new Point(Gx, Gy, 1n); // Generator / base point static readonly ZERO = new Point(0n, 1n, 0n); // Identity / zero point - static fromAffine (p: AffinePoint) { - if ((p.x === 0n) && (p.y === 0n)) return Point.ZERO; - else return new Point(p.x, p.y, 1n) ; + static fromAffine (p: AffinePoint) { // (0, 0) => (0, 1, 0), not (0, 0, 1) + return ((p.x === 0n) && (p.y === 0n)) ? Point.ZERO : new Point(p.x, p.y, 1n); } static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point hex = toU8(hex); // convert hex string to Uint8Array From de93875a4b60da0e672ad4c5c491bc64b47cc962 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 13:52:17 +0000 Subject: [PATCH 132/145] Fix ci --- .github/workflows/nodejs-polyfill.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nodejs-polyfill.yml b/.github/workflows/nodejs-polyfill.yml index 390443f..0af167d 100644 --- a/.github/workflows/nodejs-polyfill.yml +++ b/.github/workflows/nodejs-polyfill.yml @@ -4,7 +4,7 @@ on: - pull_request jobs: test: - name: v${{ matrix.node }} @ ubuntu-latest + name: v${{ matrix.node }} @ ubuntu-latest with polyfill runs-on: ubuntu-latest strategy: matrix: @@ -19,5 +19,5 @@ jobs: node-version: ${{ matrix.node }} - run: npm install - run: npm run build --if-present - - run: npm test:webcrypto + - run: npm run test:webcrypto - run: npm run lint --if-present From c473fee0af4698ff754cb8ff393bea7e26763a5c Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 23 Mar 2024 14:26:49 +0000 Subject: [PATCH 133/145] move err slightly --- index.js | 2 +- index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 452cd3a..45cad54 100644 --- a/index.js +++ b/index.js @@ -7,11 +7,11 @@ const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n; const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy }; // exported variables incl. a, b const fLen = 32; // field / group byte length const crv = (x) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 +const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n) => typeof n === 'bigint'; // is big integer const str = (s) => typeof s === 'string'; // is string const fe = (n) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n) => big(n) && 0n < n && n < N; // is group element -const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace const isu8 = (a) => (a instanceof Uint8Array || (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')); const au8 = (a, l) => // assert is Uint8Array (of specific length) diff --git a/index.ts b/index.ts index ca5e159..c9eae1a 100644 --- a/index.ts +++ b/index.ts @@ -8,11 +8,11 @@ const CURVE = {p: P, n: N, a: 0n, b: 7n, Gx, Gy}; // exported variables in const fLen = 32; // field / group byte length type Bytes = Uint8Array; type Hex = Bytes | string; type PrivKey = Hex | bigint; const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 +const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const big = (n: unknown): n is bigint => typeof n === 'bigint'; // is big integer const str = (s: unknown): s is string => typeof s === 'string'; // is string const fe = (n: bigint) => big(n) && 0n < n && n < P; // is field element (invertible) const ge = (n: bigint) => big(n) && 0n < n && n < N; // is group element -const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace const isu8 = (a: unknown): a is Uint8Array => ( a instanceof Uint8Array || (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array') From a88605e428b5e6970814cce754d3a095f56febbc Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 24 Mar 2024 10:47:51 +0000 Subject: [PATCH 134/145] Change function to const for better compression --- index.js | 28 ++++++++++++++-------------- index.ts | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/index.js b/index.js index 45cad54..f405b3b 100644 --- a/index.js +++ b/index.js @@ -213,9 +213,9 @@ const toPriv = (p) => { return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; const moreThanHalfN = (n) => n > (N >> 1n); // if a number is bigger than CURVE.n/2 -function getPublicKey(privKey, isCompressed = true) { +const getPublicKey = (privKey, isCompressed = true) => { return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output -} +}; class Signature { constructor(r, s, recovery) { this.r = r; @@ -267,7 +267,7 @@ const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs w let _hmacSync; // Can be redefined by use in utils; built-ins don't provide it const optS = { lowS: true }; // opts for sign() const optV = { lowS: true }; // standard opts for verify() -function prepSig(msgh, priv, opts = optS) { +const prepSig = (msgh, priv, opts = optS) => { if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); let { lowS } = opts; // generates low-s sigs by default @@ -308,7 +308,7 @@ function prepSig(msgh, priv, opts = optS) { return new Signature(r, normS, rec); // use normS, not s }; return { seed: concatB(...seed), k2sig }; -} +}; function hmacDrbg(asynchronous) { let v = u8n(fLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. let k = u8n(fLen); // Steps B, C of RFC6979 3.2: set hashLen, in our case always same @@ -374,15 +374,15 @@ function hmacDrbg(asynchronous) { } } // ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k -async function signAsync(msgh, priv, opts = optS) { +const signAsync = async (msgh, priv, opts = optS) => { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg return hmacDrbg(true)(seed, k2sig); // Re-run drbg until k2sig returns ok -} -function sign(msgh, priv, opts = optS) { +}; +const sign = (msgh, priv, opts = optS) => { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg return hmacDrbg(false)(seed, k2sig); // Re-run drbg until k2sig returns ok -} -function verify(sig, msgh, pub, opts = optV) { +}; +const verify = (sig, msgh, pub, opts = optV) => { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true @@ -419,18 +419,18 @@ function verify(sig, msgh, pub, opts = optV) { return false; // stop if R is identity / zero point const v = mod(R.x, N); // R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r -} -function getSharedSecret(privA, pubB, isCompressed = true) { +}; +const getSharedSecret = (privA, pubB, isCompressed = true) => { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH -} -function hashToPrivateKey(hash) { +}; +const hashToPrivateKey = (hash) => { hash = toU8(hash); // produces private keys with modulo bias const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); const num = mod(b2n(hash), N - 1n) + 1n; // takes at least n+8 bytes return n2b(num); -} +}; const etc = { hexToBytes: h2b, bytesToHex: b2h, // share API with noble-curves. concatBytes: concatB, bytesToNumberBE: b2n, numberToBytesBE: n2b, diff --git a/index.ts b/index.ts index c9eae1a..b2d6cd3 100644 --- a/index.ts +++ b/index.ts @@ -175,7 +175,7 @@ const toPriv = (p: PrivKey): bigint => { // normalize private key return ge(p) ? p : err('private key out of range'); // check if bigint is in range }; const moreThanHalfN = (n: bigint): boolean => n > (N >> 1n); // if a number is bigger than CURVE.n/2 -function getPublicKey(privKey: PrivKey, isCompressed = true) { // Make public key from priv +const getPublicKey = (privKey: PrivKey, isCompressed = true) => { // Make public key from priv return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); // 33b or 65b output } type SignatureWithRecovery = Signature & { recovery: number } @@ -228,7 +228,7 @@ let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don const optS: { lowS?: boolean; extraEntropy?: boolean | Hex; } = { lowS: true }; // opts for sign() const optV: { lowS?: boolean } = { lowS: true }; // standard opts for verify() type BC = { seed: Bytes, k2sig : (kb: Bytes) => SignatureWithRecovery | undefined }; // Bytes+predicate checker -function prepSig(msgh: Hex, priv: PrivKey, opts = optS): BC { // prepare for RFC6979 sig generation +const prepSig = (msgh: Hex, priv: PrivKey, opts=optS): BC => {// prepare for RFC6979 sig generation if (['der', 'recovered', 'canonical'].some(k => k in opts)) // Ban legacy options err('sign() legacy options not supported'); let { lowS } = opts; // generates low-s sigs by default @@ -324,16 +324,16 @@ function hmacDrbg(asynchronous: boolean) { // HMAC-DRBG async } } // ECDSA signature generation. via secg.org/sec1-v2.pdf 4.1.2 + RFC6979 deterministic k -async function signAsync(msgh: Hex, priv: PrivKey, opts = optS): Promise { +const signAsync = async (msgh: Hex, priv: PrivKey, opts = optS): Promise => { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg return hmacDrbg(true)(seed, k2sig); // Re-run drbg until k2sig returns ok } -function sign(msgh: Hex, priv: PrivKey, opts = optS): SignatureWithRecovery { +const sign = (msgh: Hex, priv: PrivKey, opts = optS): SignatureWithRecovery => { const { seed, k2sig } = prepSig(msgh, priv, opts); // Extract arguments for hmac-drbg return hmacDrbg(false)(seed, k2sig); // Re-run drbg until k2sig returns ok } type SigLike = { r: bigint, s: bigint }; -function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { +const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean => { let { lowS } = opts; // ECDSA signature verification if (lowS == null) lowS = true; // Default lowS=true if ('strict' in opts) err('verify() legacy options not supported'); // legacy param @@ -360,10 +360,10 @@ function verify(sig: Hex | SigLike, msgh: Hex, pub: Hex, opts = optV): boolean { const v = mod(R.x, N); // R.x must be in N's field, not P's return v === r; // mod(R.x, n) == r } -function getSharedSecret(privA: Hex, pubB: Hex, isCompressed = true): Bytes { +const getSharedSecret = (privA: Hex, pubB: Hex, isCompressed = true): Bytes => { return Point.fromHex(pubB).mul(toPriv(privA)).toRawBytes(isCompressed); // ECDH } -function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compliant key generation +const hashToPrivateKey = (hash: Hex): Bytes => { // FIPS 186 B.4.1 compliant key generation hash = toU8(hash); // produces private keys with modulo bias const minLen = fLen + 8; // being neglible. if (hash.length < minLen || hash.length > 1024) err('expected proper params'); From e355b8575d48609559aa559647b45fdb16c53008 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 24 Mar 2024 10:48:16 +0000 Subject: [PATCH 135/145] Update pkg.json scripts --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3245b46..ce0b1fa 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,12 @@ "sideEffects": false, "scripts": { "build": "tsc", - "build:release": "rollup -c rollup.config.js", + "build:min": "cd test/build; npm install; npm run terser", + "build:mingz": "npm run --silent build:min | gzip -c8", "test": "node test/index.test.js", "test:webcrypto": "node test/secp256k1.webcrypto.test.js", "bench": "node test/benchmark.js", - "min": "cd test/build; npm install; npm run terser", - "loc": "echo \"`npm run --silent min | wc -c` symbols `wc -l < index.ts` LOC, `npm run --silent min | gzip -c8 | wc -c`B gzipped\"" + "loc": "echo \"`npm run --silent build:min | wc -c` symbols `wc -l < index.ts` LOC, `npm run --silent build:mingz | wc -c`B gzipped\"" }, "author": "Paul Miller (https://paulmillr.com)", "homepage": "https://paulmillr.com/noble/", From bd1a2c7915d6b4d598e2f02ef351a1e5225624f2 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 24 Mar 2024 10:54:22 +0000 Subject: [PATCH 136/145] Add upload-release ci workflow --- .github/workflows/upload-release.yml | 24 ++++++++++++++++++++++++ package.json | 1 + 2 files changed, 25 insertions(+) create mode 100644 .github/workflows/upload-release.yml diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml new file mode 100644 index 0000000..b31635e --- /dev/null +++ b/.github/workflows/upload-release.yml @@ -0,0 +1,24 @@ +name: Upload standalone file to GitHub Releases +on: + release: + types: [created] +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install -g npm + - run: npm ci + - run: npm run build + - run: npm run build:release + - run: gh release upload ${{ github.event.release.tag_name }} test/build/noble-secp256k1.min.js test/build/noble-secp256k1.min.js.gz + env: + GH_TOKEN: ${{ github.token }} diff --git a/package.json b/package.json index ce0b1fa..fd7be35 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build": "tsc", "build:min": "cd test/build; npm install; npm run terser", "build:mingz": "npm run --silent build:min | gzip -c8", + "build:release": "npm run --silent build:min > test/build/noble-secp256k1.min.js; npm run --silent build:mingz > test/build/noble-secp256k1.min.js.gz", "test": "node test/index.test.js", "test:webcrypto": "node test/secp256k1.webcrypto.test.js", "bench": "node test/benchmark.js", From 29e0cf17385a6642b6b68c7095a643c86ee5243d Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sun, 24 Mar 2024 11:05:20 +0000 Subject: [PATCH 137/145] Release 2.1.0. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fd7be35..4da3209 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@noble/secp256k1", - "version": "2.0.0", + "version": "2.1.0", "description": "Fastest 4KB JS implementation of secp256k1 ECDH & ECDSA signatures compliant with RFC6979", "files": [ "index.js", @@ -26,7 +26,7 @@ "homepage": "https://paulmillr.com/noble/", "repository": { "type": "git", - "url": "https://github.com/paulmillr/noble-secp256k1.git" + "url": "git+https://github.com/paulmillr/noble-secp256k1.git" }, "license": "MIT", "devDependencies": { From 06e9a2a3bf490a696139b97c96bec940daa12c5e Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 24 Apr 2024 23:07:00 +0000 Subject: [PATCH 138/145] Publish 2.1.0 on jsr --- .github/workflows/publish-jsr.yml | 15 +++++++++++++++ jsr.json | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .github/workflows/publish-jsr.yml create mode 100644 jsr.json diff --git a/.github/workflows/publish-jsr.yml b/.github/workflows/publish-jsr.yml new file mode 100644 index 0000000..6d7bb0c --- /dev/null +++ b/.github/workflows/publish-jsr.yml @@ -0,0 +1,15 @@ +name: Publish packge to jsr +on: + push: + branches: + - main +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - run: npm install -g jsr + - run: jsr publish --allow-slow-types diff --git a/jsr.json b/jsr.json new file mode 100644 index 0000000..2be3232 --- /dev/null +++ b/jsr.json @@ -0,0 +1,13 @@ +{ + "name": "@noble/secp256k1", + "version": "2.1.0", + "exports": "./index.ts", + "publish": { + "include": [ + "LICENSE", + "README.md", + "index.ts", + "jsr.json" + ] + } +} \ No newline at end of file From 0c8366dafd4f720617799cbd9545a0885d7b1b5d Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 24 Apr 2024 23:13:32 +0000 Subject: [PATCH 139/145] CI: publish jsr only on release --- .github/workflows/publish-jsr.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-jsr.yml b/.github/workflows/publish-jsr.yml index 6d7bb0c..cb43651 100644 --- a/.github/workflows/publish-jsr.yml +++ b/.github/workflows/publish-jsr.yml @@ -1,8 +1,7 @@ name: Publish packge to jsr on: - push: - branches: - - main + release: + types: [created] jobs: publish: runs-on: ubuntu-latest From d0aa27d4a2ca5bbd31cae53d88392363902cc0d0 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 11 May 2024 23:44:49 +0000 Subject: [PATCH 140/145] README --- README.md | 58 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index f4e0a5d..34c3443 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ if you need additional features such as common.js, Schnorr signatures, DER encod ## Usage -> npm install @noble/secp256k1 +> `npm install @noble/secp256k1` > `deno add @noble/secp256k1` We support all major platforms and runtimes. For node.js <= 18 and React Native, additional polyfills are needed: see below. @@ -59,7 +59,7 @@ Additional polyfills for some environments: // Only async methods are available by default, to keep the library dependency-free. import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; -secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)) +secp.etc.hmacSha256Sync = (k, ...m) => hmac(sha256, k, secp.etc.concatBytes(...m)); // Sync methods can be used now: // secp.sign(msgHash, privKey); @@ -84,7 +84,7 @@ There are 3 main methods: `getPublicKey(privateKey)`, We accept Hex type everywhere: ```ts -type Hex = Uint8Array | string +type Hex = Uint8Array | string; ``` ### getPublicKey @@ -105,7 +105,7 @@ Generates 33-byte compressed public key from 32-byte private key. function sign( messageHash: Hex, // message hash (not message) which would be signed privateKey: Hex, // private key which will sign the hash - opts?: { lowS: boolean, extraEntropy: boolean | Hex } // optional params + opts?: { lowS: boolean; extraEntropy: boolean | Hex } // optional params ): Signature; function signAsync( messageHash: Hex, @@ -123,13 +123,13 @@ which means you'll need to do something like `sha256(message)` before signing. 1. `lowS: false` allows to create malleable signatures, for compatibility with openssl. Default `lowS: true` prohibits signatures which have (sig.s >= CURVE.n/2n) and is compatible with BTC/ETH. 2. `extraEntropy: true` improves security by adding entropy, follows section 3.6 of RFC6979: - - No disadvantage: if an entropy generator is broken, sigs would be the same - as they are without the option - - It would help a lot in case there is an error somewhere in `k` gen. - Exposing `k` could leak private keys - - Sigs with extra entropy would have different `r` / `s`, which means they - would still be valid, but may break some test vectors if you're - cross-testing against other libs + - No disadvantage: if an entropy generator is broken, sigs would be the same + as they are without the option + - It would help a lot in case there is an error somewhere in `k` gen. + Exposing `k` could leak private keys + - Sigs with extra entropy would have different `r` / `s`, which means they + would still be valid, but may break some test vectors if you're + cross-testing against other libs ### verify @@ -227,7 +227,7 @@ class Signature { toCompactRawBytes(): Bytes; toCompactHex(): string; } -CURVE // curve prime; order; equation params, generator coordinates +CURVE; // curve prime; order; equation params, generator coordinates ``` ## Security @@ -237,9 +237,9 @@ It is cross-tested against [noble-curves](https://github.com/paulmillr/noble-cur and has similar security. 1. The current version is rewrite of v1, which has been audited by cure53: -[PDF](https://cure53.de/pentest-report_noble-lib.pdf) (funded by [Umbra.cash](https://umbra.cash) & community). + [PDF](https://cure53.de/pentest-report_noble-lib.pdf) (funded by [Umbra.cash](https://umbra.cash) & community). 2. It's being fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz): -run the fuzzer by yourself to check. + run the fuzzer by yourself to check. Our EC multiplication is hardened to be algorithmically constant time. We're using built-in JS `BigInt`, which is potentially vulnerable to @@ -323,24 +323,24 @@ Switch to curves if you intend to keep using these features: Other changes for upgrading from @noble/secp256k1 1.7 to 2.0: - `getPublicKey` - - now produce 33-byte compressed signatures by default - - to use old behavior, which produced 65-byte uncompressed keys, set - argument `isCompressed` to `false`: `getPublicKey(priv, false)` + - now produce 33-byte compressed signatures by default + - to use old behavior, which produced 65-byte uncompressed keys, set + argument `isCompressed` to `false`: `getPublicKey(priv, false)` - `sign` - - is now sync; use `signAsync` for async version - - now returns `Signature` instance with `{ r, s, recovery }` properties - - `canonical` option was renamed to `lowS` - - `recovered` option has been removed because recovery bit is always returned now - - `der` option has been removed. There are 2 options: - 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`. - Compact encoding is simply a concatenation of 32-byte r and 32-byte s. - 2. If you must use DER encoding, switch to noble-curves (see above). + - is now sync; use `signAsync` for async version + - now returns `Signature` instance with `{ r, s, recovery }` properties + - `canonical` option was renamed to `lowS` + - `recovered` option has been removed because recovery bit is always returned now + - `der` option has been removed. There are 2 options: + 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`. + Compact encoding is simply a concatenation of 32-byte r and 32-byte s. + 2. If you must use DER encoding, switch to noble-curves (see above). - `verify` - - `strict` option was renamed to `lowS` + - `strict` option was renamed to `lowS` - `getSharedSecret` - - now produce 33-byte compressed signatures by default - - to use old behavior, which produced 65-byte uncompressed keys, set - argument `isCompressed` to `false`: `getSharedSecret(a, b, false)` + - now produce 33-byte compressed signatures by default + - to use old behavior, which produced 65-byte uncompressed keys, set + argument `isCompressed` to `false`: `getSharedSecret(a, b, false)` - `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)` - `number` type for private keys have been removed: use `bigint` instead - `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz) From 1177f212bbd534854983271bc66dc854b1a0f49e Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 11 May 2024 23:45:48 +0000 Subject: [PATCH 141/145] readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 34c3443..6e29e58 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ if you need additional features such as common.js, Schnorr signatures, DER encod ## Usage -> `npm install @noble/secp256k1` > `deno add @noble/secp256k1` +> `npm install @noble/secp256k1` + +> `deno add @noble/secp256k1` We support all major platforms and runtimes. For node.js <= 18 and React Native, additional polyfills are needed: see below. From 08030e6ca014743fa4f49eef3afa278cac94d98d Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 11 May 2024 23:52:42 +0000 Subject: [PATCH 142/145] readme --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6e29e58..f12d00b 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,10 @@ We support all major platforms and runtimes. For node.js <= 18 and React Native, ```js import * as secp from '@noble/secp256k1'; -// import * as secp from "https://deno.land/x/secp256k1/mod.ts"; // Deno // import * as secp from "https://unpkg.com/@noble/secp256k1"; // Unpkg (async () => { - // keys, messages & other inputs can be Uint8Arrays or hex strings - // Uint8Array.from([0xde, 0xad, 0xbe, 0xef]) === 'deadbeef' + // Uint8Arrays or hex strings are accepted: + // Uint8Array.from([0xde, 0xad, 0xbe, 0xef]) is equal to 'deadbeef' const privKey = secp.utils.randomPrivateKey(); // Secure random private key // sha256 of 'hello world' const msgHash = 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'; From 0f0d9b54460ad9eb5498650eea8342145ccc854f Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 18 May 2024 20:47:33 +0000 Subject: [PATCH 143/145] test: Change import assert to import with --- test/secp256k1.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/secp256k1.test.js b/test/secp256k1.test.js index 7ad7d68..7a51292 100644 --- a/test/secp256k1.test.js +++ b/test/secp256k1.test.js @@ -8,11 +8,11 @@ import { secp, sigFromDER, sigToDER, selectHash, normVerifySig, mod, bytesToNumberBE, numberToBytesBE } from './secp256k1.helpers.js'; -import { default as ecdsa } from './vectors/secp256k1/ecdsa.json' assert { type: 'json' }; -import { default as ecdh } from './wycheproof/ecdh_secp256k1_test.json' assert { type: 'json' }; -import { default as privates } from './vectors/secp256k1/privates.json' assert { type: 'json' }; -import { default as points } from './vectors/secp256k1/points.json' assert { type: 'json' }; -import { default as wp } from './wycheproof/ecdsa_secp256k1_sha256_test.json' assert { type: 'json' }; +import { default as ecdsa } from './vectors/secp256k1/ecdsa.json' with { type: 'json' }; +import { default as ecdh } from './wycheproof/ecdh_secp256k1_test.json' with { type: 'json' }; +import { default as privates } from './vectors/secp256k1/privates.json' with { type: 'json' }; +import { default as points } from './vectors/secp256k1/points.json' with { type: 'json' }; +import { default as wp } from './wycheproof/ecdsa_secp256k1_sha256_test.json' with { type: 'json' }; // Any changes to the file will need to be aware of the fact // the file is shared between noble-curves and noble-secp256k1. From 6db9d7cf20e99376ef237eba0f21926c412966ce Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 18 May 2024 20:48:04 +0000 Subject: [PATCH 144/145] ci: add node v22 --- .github/workflows/nodejs-polyfill.yml | 1 + .github/workflows/nodejs.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/nodejs-polyfill.yml b/.github/workflows/nodejs-polyfill.yml index 0af167d..dfe635e 100644 --- a/.github/workflows/nodejs-polyfill.yml +++ b/.github/workflows/nodejs-polyfill.yml @@ -11,6 +11,7 @@ jobs: node: - 18 - 20 + - 22 steps: - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - name: Use Node.js ${{ matrix.node }} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index dae21a7..e946b20 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -10,6 +10,7 @@ jobs: matrix: node: - 20 + - 22 steps: - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - name: Use Node.js ${{ matrix.node }} From 5249db1ef07ac97a8773f6e13ce578c7afc95c7b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 18 May 2024 23:04:29 +0200 Subject: [PATCH 145/145] test: prefix imports of built-in modules --- test/basic.test.js | 15 ++++----------- test/secp256k1.test.js | 6 +++--- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/test/basic.test.js b/test/basic.test.js index 175be1d..1c948a4 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -4,7 +4,7 @@ import * as fc from 'fast-check'; import * as secp256k1 from '../index.js'; import * as h from './secp256k1.helpers.js'; -const CURVES = { secp256k1 } +const CURVES = { secp256k1 }; const name = 'secp256k1'; const C = CURVES[name]; const CURVE_ORDER = C.CURVE.n; @@ -136,10 +136,7 @@ for (const pointName in POINTS) { throws(() => G[1][op]('1'), "'1'"); throws(() => G[1][op]({ x: 1n, y: 1n }), '{ x: 1n, y: 1n }'); throws(() => G[1][op]({ x: 1n, y: 1n, z: 1n }), '{ x: 1n, y: 1n, z: 1n }'); - throws( - () => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }), - '{ x: 1n, y: 1n, z: 1n, t: 1n }' - ); + throws(() => G[1][op]({ x: 1n, y: 1n, z: 1n, t: 1n }), '{ x: 1n, y: 1n, z: 1n, t: 1n }'); throws(() => G[1][op](new Uint8Array([])), 'ui8a([])'); throws(() => G[1][op](new Uint8Array([0])), 'ui8a([0])'); throws(() => G[1][op](new Uint8Array([1])), 'ui8a([1])'); @@ -264,11 +261,7 @@ describe(name, () => { const pub = C.getPublicKey(priv); const sig = C.sign(msg, priv); const err = `priv=${toHex(priv)},pub=${toHex(pub)},msg=${msg}`; - deepStrictEqual( - C.verify(sig, msg, pub), - true, - err - ); + deepStrictEqual(C.verify(sig, msg, pub), true, err); }), { numRuns: NUM_RUNS } ) @@ -399,7 +392,7 @@ describe(name, () => { }); // ESM is broken. -import url from 'url'; +import url from 'node:url'; if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { should.run(); } diff --git a/test/secp256k1.test.js b/test/secp256k1.test.js index 7a51292..e2a2df2 100644 --- a/test/secp256k1.test.js +++ b/test/secp256k1.test.js @@ -1,7 +1,7 @@ import { hexToBytes, bytesToHex as hex } from '@noble/hashes/utils'; -import { deepStrictEqual, throws } from 'assert'; +import { deepStrictEqual, throws } from 'node:assert'; import * as fc from 'fast-check'; -import { readFileSync } from 'fs'; +import { readFileSync } from 'node:fs'; import { should, describe } from 'micro-should'; // prettier-ignore import { @@ -543,7 +543,7 @@ describe('secp256k1', () => { }); // ESM is broken. -import url from 'url'; +import url from 'node:url'; if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { should.run(); }