diff --git a/README.md b/README.md index 706e5d1..9b7fa14 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ const secq256k1 = weierstrass({ randomBytes, }); -// weierstrassPoints can also be used if you don't need ECDSA, hash, hmac, randomBytes +// Replace weierstrass with weierstrassPoints if you don't need ECDSA, hash, hmac, randomBytes ``` Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass` diff --git a/benchmark/curves.js b/benchmark/curves.js index 9916a67..4d7b254 100644 --- a/benchmark/curves.js +++ b/benchmark/curves.js @@ -1,14 +1,14 @@ import { run, mark, utils } from 'micro-bmark'; import { generateData } from './_shared.js'; -import { P256 } from '../p256.js'; -import { P384 } from '../p384.js'; -import { P521 } from '../p521.js'; +import { p256 } from '../p256.js'; +import { p384 } from '../p384.js'; +import { p521 } from '../p521.js'; import { ed25519 } from '../ed25519.js'; import { ed448 } from '../ed448.js'; run(async () => { const RAM = false - for (let kv of Object.entries({ P256, P384, P521, ed25519, ed448 })) { + for (let kv of Object.entries({ p256, p384, p521, ed25519, ed448 })) { const [name, curve] = kv; console.log(); console.log(`\x1b[36m${name}\x1b[0m`); diff --git a/benchmark/ecdh.js b/benchmark/ecdh.js index c238826..538a269 100644 --- a/benchmark/ecdh.js +++ b/benchmark/ecdh.js @@ -1,14 +1,13 @@ -import { run, mark, compare, utils } from 'micro-bmark'; -import { generateData } from './_shared.js'; +import { run, compare } from 'micro-bmark'; import { secp256k1 } from '../secp256k1.js'; -import { P256 } from '../p256.js'; -import { P384 } from '../p384.js'; -import { P521 } from '../p521.js'; +import { p256 } from '../p256.js'; +import { p384 } from '../p384.js'; +import { p521 } from '../p521.js'; import { x25519 } from '../ed25519.js'; import { x448 } from '../ed448.js'; run(async () => { - const curves = { x25519, secp256k1, P256, P384, P521, x448 }; + const curves = { x25519, secp256k1, p256, p384, p521, x448 }; const fns = {}; for (let [k, c] of Object.entries(curves)) { const pubB = c.getPublicKey(c.utils.randomPrivateKey()); diff --git a/benchmark/hash-to-curve.js b/benchmark/hash-to-curve.js index 267e5d6..f622b9a 100644 --- a/benchmark/hash-to-curve.js +++ b/benchmark/hash-to-curve.js @@ -5,9 +5,9 @@ import { randomBytes } from '@noble/hashes/utils'; import { sha256 } from '@noble/hashes/sha256'; // import { generateData } from './_shared.js'; import { hashToCurve as secp256k1 } from '../secp256k1.js'; -import { hashToCurve as P256 } from '../p256.js'; -import { hashToCurve as P384 } from '../p384.js'; -import { hashToCurve as P521 } from '../p521.js'; +import { hashToCurve as p256 } from '../p256.js'; +import { hashToCurve as p384 } from '../p384.js'; +import { hashToCurve as p521 } from '../p521.js'; import { hashToCurve as ed25519 } from '../ed25519.js'; import { hashToCurve as ed448 } from '../ed448.js'; import { utf8ToBytes } from '../abstract/utils.js'; @@ -23,7 +23,7 @@ run(async () => { hash_to_field(rand, 1, { DST: 'secp256k1', hash: sha256, expand: 'xmd', p: N, m: 1, k: 128 }) ); const msg = utf8ToBytes('message'); - for (let [title, fn] of Object.entries({ secp256k1, P256, P384, P521, ed25519, ed448 })) { + for (let [title, fn] of Object.entries({ secp256k1, p256, p384, p521, ed25519, ed448 })) { await mark(`hashToCurve ${title}`, 1000, () => fn(msg)); } }); diff --git a/src/p256.ts b/src/p256.ts index bb30d93..b124420 100644 --- a/src/p256.ts +++ b/src/p256.ts @@ -5,10 +5,9 @@ import { Field } from './abstract/modular.js'; import { mapToCurveSimpleSWU } from './abstract/weierstrass.js'; import * as htf from './abstract/hash-to-curve.js'; -// NIST secp256r1 aka P256 +// NIST secp256r1 aka p256 // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 -// Field over which we'll do calculations; 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n const Fp = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')); const CURVE_A = Fp.create(BigInt('-3')); const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'); @@ -19,23 +18,20 @@ const mapSWU = mapToCurveSimpleSWU(Fp, { Z: Fp.create(BigInt('-10')), }); -export const P256 = createCurve( - { - // Params: a, b - a: CURVE_A, - b: CURVE_B, - Fp, - // Curve order, total count of valid points in the field - n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), - // Base point (x, y) aka generator point - Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), - Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), - h: BigInt(1), - lowS: false, - } as const, - sha256 -); -export const secp256r1 = P256; +// prettier-ignore +export const p256 = createCurve({ + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n + // Curve order, total count of valid points in the field + n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), + // Base (generator) point (x, y) + Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), + Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), + h: BigInt(1), + lowS: false, +} as const, sha256); +export const secp256r1 = p256; const { hashToCurve, encodeToCurve } = htf.createHasher( secp256r1.ProjectivePoint, diff --git a/src/p384.ts b/src/p384.ts index 3f8db49..c70184f 100644 --- a/src/p384.ts +++ b/src/p384.ts @@ -5,10 +5,10 @@ import { Field } from './abstract/modular.js'; import { mapToCurveSimpleSWU } from './abstract/weierstrass.js'; import * as htf from './abstract/hash-to-curve.js'; -// NIST secp384r1 aka P384 +// NIST secp384r1 aka p384 // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 -// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n +// Field over which we'll do calculations. // prettier-ignore const P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'); const Fp = Field(P); @@ -16,31 +16,27 @@ const CURVE_A = Fp.create(BigInt('-3')); // prettier-ignore const CURVE_B = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef'); +// prettier-ignore +export const p384 = createCurve({ + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n + // Curve order, total count of valid points in the field. + n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'), + // Base (generator) point (x, y) + Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'), + Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'), + h: BigInt(1), + lowS: false, +} as const, sha384); +export const secp384r1 = p384; + const mapSWU = mapToCurveSimpleSWU(Fp, { A: CURVE_A, B: CURVE_B, Z: Fp.create(BigInt('-12')), }); -// prettier-ignore -export const P384 = createCurve({ - // Params: a, b - a: CURVE_A, - b: CURVE_B, - // Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n - Fp, - // Curve order, total count of valid points in the field. - n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'), - // Base point (x, y) aka generator point - Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'), - Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'), - h: BigInt(1), - lowS: false, - } as const, - sha384 -); -export const secp384r1 = P384; - const { hashToCurve, encodeToCurve } = htf.createHasher( secp384r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), diff --git a/src/p521.ts b/src/p521.ts index 999895c..0bed62b 100644 --- a/src/p521.ts +++ b/src/p521.ts @@ -5,41 +5,53 @@ import { Field } from './abstract/modular.js'; import { mapToCurveSimpleSWU } from './abstract/weierstrass.js'; import * as htf from './abstract/hash-to-curve.js'; -// NIST secp521r1 aka P521 +// NIST secp521r1 aka p521 // Note that it's 521, which differs from 512 of its hash function. // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 -// Field over which we'll do calculations; 2n**521n - 1n +// Field over which we'll do calculations. // prettier-ignore const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); const Fp = Field(P); -const CURVE_A = Fp.create(BigInt('-3')); -// prettier-ignore -const CURVE_B = BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'); - -const mapSWU = mapToCurveSimpleSWU(Fp, { - A: CURVE_A, - B: CURVE_B, - Z: Fp.create(BigInt('-4')), -}); - -// prettier-ignore -export const P521 = createCurve({ - // Params: a, b - a: CURVE_A, - b: CURVE_B, +const CURVE = { + a: Fp.create(BigInt('-3')), + b: BigInt( + '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00' + ), Fp, - // Curve order, total count of valid points in the field - n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'), - // Base point (x, y) aka generator point - Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'), - Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'), + n: BigInt( + '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409' + ), + Gx: BigInt( + '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66' + ), + Gy: BigInt( + '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650' + ), h: BigInt(1), +}; + +// prettier-ignore +export const p521 = createCurve({ + a: CURVE.a, // Equation params: a, b + b: CURVE.b, + Fp, // Field: 2n**521n - 1n + // Curve order, total count of valid points in the field + n: CURVE.n, + Gx: CURVE.Gx, // Base point (x, y) aka generator point + Gy: CURVE.Gy, + h: CURVE.h, lowS: false, allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b } as const, sha512); -export const secp521r1 = P521; +export const secp521r1 = p521; + +const mapSWU = mapToCurveSimpleSWU(Fp, { + A: CURVE.a, + B: CURVE.b, + Z: Fp.create(BigInt('-4')), +}); const { hashToCurve, encodeToCurve } = htf.createHasher( secp521r1.ProjectivePoint, diff --git a/test/_more-curves.helpers.js b/test/_more-curves.helpers.js index 634686d..07b2005 100644 --- a/test/_more-curves.helpers.js +++ b/test/_more-curves.helpers.js @@ -3,9 +3,9 @@ import { createCurve } from '../esm/_shortw_utils.js'; import { sha224, sha256 } from '@noble/hashes/sha256'; import { Field as Fp } from '../esm/abstract/modular.js'; -// NIST secp192r1 aka P192 +// NIST secp192r1 aka p192 // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1 -export const P192 = createCurve( +export const p192 = createCurve( { // Params: a, b a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'), @@ -22,9 +22,9 @@ export const P192 = createCurve( }, sha256 ); -export const secp192r1 = P192; +export const secp192r1 = p192; -export const P224 = createCurve( +export const p224 = createCurve( { // Params: a, b a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'), @@ -41,4 +41,4 @@ export const P224 = createCurve( }, sha224 ); -export const secp224r1 = P224; +export const secp224r1 = p224; diff --git a/test/nist.test.js b/test/nist.test.js index 27939ae..aff3e27 100644 --- a/test/nist.test.js +++ b/test/nist.test.js @@ -1,10 +1,10 @@ import { deepStrictEqual, throws } from 'assert'; import { describe, should } from 'micro-should'; -import { secp192r1, secp224r1, P192, P224 } from './_more-curves.helpers.js'; +import { secp192r1, secp224r1, p192, p224 } from './_more-curves.helpers.js'; import { DER } from '../esm/abstract/weierstrass.js'; -import { secp256r1, P256 } from '../esm/p256.js'; -import { secp384r1, P384 } from '../esm/p384.js'; -import { secp521r1, P521 } from '../esm/p521.js'; +import { secp256r1, p256 } from '../esm/p256.js'; +import { secp384r1, p384 } from '../esm/p384.js'; +import { secp521r1, p521 } from '../esm/p521.js'; import { secp256k1 } from '../esm/secp256k1.js'; import { hexToBytes, bytesToHex } from '../esm/abstract/utils.js'; import { default as ecdsa } from './wycheproof/ecdsa_test.json' assert { type: 'json' }; @@ -71,11 +71,11 @@ const hex = bytesToHex; // prettier-ignore const NIST = { - secp192r1, P192, - secp224r1, P224, - secp256r1, P256, - secp384r1, P384, - secp521r1, P521, + secp192r1, P192: p192, + secp224r1, P224: p224, + secp256r1, P256: p256, + secp384r1, P384: p384, + secp521r1, P521: p521, secp256k1, }; @@ -125,24 +125,24 @@ describe('wycheproof ECDH', () => { // More per curve tests const WYCHEPROOF_ECDH = { - P224: { - curve: P224, + p224: { + curve: p224, tests: [ecdh_secp224r1_test], }, - P256: { - curve: P256, + p256: { + curve: p256, tests: [ecdh_secp256r1_test], }, secp256k1: { curve: secp256k1, tests: [ecdh_secp256k1_test], }, - P384: { - curve: P384, + p384: { + curve: p384, tests: [ecdh_secp384r1_test], }, - P521: { - curve: P521, + p521: { + curve: p521, tests: [ecdh_secp521r1_test], }, }; @@ -182,8 +182,8 @@ describe('wycheproof ECDH', () => { }); const WYCHEPROOF_ECDSA = { - P224: { - curve: P224, + p224: { + curve: p224, hashes: { sha224: { hash: sha224, @@ -244,8 +244,8 @@ const WYCHEPROOF_ECDSA = { }, }, }, - P256: { - curve: P256, + p256: { + curve: p256, hashes: { sha256: { hash: sha256, @@ -269,8 +269,8 @@ const WYCHEPROOF_ECDSA = { }, }, }, - P384: { - curve: P384, + p384: { + curve: p384, hashes: { sha384: { hash: sha384, @@ -294,8 +294,8 @@ const WYCHEPROOF_ECDSA = { }, }, }, - P521: { - curve: P521, + p521: { + curve: p521, hashes: { sha3_512: { hash: sha3_512,