From 9f6ba3df9e4ec739b0b16d8f9066adce5b57e165 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Thu, 4 Dec 2025 10:45:25 -0800 Subject: [PATCH] Deprecate range helpers and use underlying function directly. --- src/lib/crypto/secp256k1.ts | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/lib/crypto/secp256k1.ts b/src/lib/crypto/secp256k1.ts index 278278b..ae978b5 100644 --- a/src/lib/crypto/secp256k1.ts +++ b/src/lib/crypto/secp256k1.ts @@ -140,19 +140,13 @@ export class Secp256k1 { // ----------------- /** secp256k1 formula. Koblitz curves are subclass of weierstrass curves with a=0, making it x³+b */ - static koblitz = (x: bigint) => this.modP(this.modP(x * x) * x + this.b) - /** assert is element of field mod P (incl. 0) */ - static FpIsValid = (n: bigint) => this.bigintInRange(n, 0n, this.P) - /** assert is element of field mod P (excl. 0) */ - static FpIsValidNot0 = (n: bigint) => this.bigintInRange(n, 1n, this.P) - /** assert is element of field mod N (excl. 0) */ - static FnIsValidNot0 = (n: bigint) => this.bigintInRange(n, 1n, this.N) - static isEven = (y: bigint) => (y & 1n) === 0n + static koblitz = (x: bigint): bigint => this.modP(this.modP(x * x) * x + this.b) + static isEven = (y: bigint): boolean => (y & 1n) === 0n static getPrefix = (y: bigint) => Uint8Array.of(this.isEven(y) ? 0x02 : 0x03) /** lift_x from BIP340 calculates square root. Validates x, then validates root*root. */ - static lift_x (x: bigint) { + static lift_x (x: bigint): bigint { // Let c = x³ + 7 mod p. Fail if x ≥ p. (also fail if x < 1) - const c = this.koblitz(this.FpIsValidNot0(x)) + const c = this.koblitz(this.bigintInRange(x, 1n, this.P)) // c = √y // y = c^((p+1)/4) mod p // This formula works for fields p = 3 mod 4 -- a special, fast case. @@ -170,9 +164,9 @@ export class Secp256k1 { static Point (X: bigint, Y: bigint, Z: bigint): Point { const secp256k1 = this return Object.freeze({ - X: this.FpIsValid(X), - Y: this.FpIsValidNot0(Y), // Y can't be 0 in Projective - Z: this.FpIsValid(Z), + X: this.bigintInRange(X, 0n, this.P), + Y: this.bigintInRange(Y, 1n, this.P), // Y can't be 0 in Projective + Z: this.bigintInRange(Z, 0n, this.P), /** Equality check: compare points P&Q. */ equals (other: Point): boolean { const { X: X1, Y: Y1, Z: Z1 } = this @@ -232,7 +226,7 @@ export class Secp256k1 { */ multiply (n: bigint, safe = true): Point { if (!safe && n === 0n) return secp256k1.I - secp256k1.FnIsValidNot0(n) + secp256k1.bigintInRange(n, 1n, secp256k1.N) if (n === 1n) return this if (this.equals(secp256k1.G)) return secp256k1.wNAF(n).p // init result point & fake point @@ -261,8 +255,8 @@ export class Secp256k1 { /** Checks if the point is valid and on-curve. */ assertValidity (): Point { const { x, y } = this.toAffine() // convert to 2d xy affine point. - secp256k1.FpIsValidNot0(x) // must be in range 1 <= x,y < P - secp256k1.FpIsValidNot0(y) + secp256k1.bigintInRange(x, 1n, secp256k1.P) // must be in range 1 <= x,y < P + secp256k1.bigintInRange(y, 1n, secp256k1.P) // y² == x³ + ax + b, equation sides must be equal return secp256k1.modP(y * y) === secp256k1.koblitz(x) ? this : secp256k1.err('bad point: not on curve') }, -- 2.47.3