]> git.codecow.com Git - libnemo.git/commitdiff
Add modular division helper to be explicit about the arguments.
authorChris Duncan <chris@zoso.dev>
Wed, 3 Dec 2025 22:45:02 +0000 (14:45 -0800)
committerChris Duncan <chris@zoso.dev>
Wed, 3 Dec 2025 22:45:02 +0000 (14:45 -0800)
src/lib/crypto/secp256k1.ts

index c5c0560bb1f2616d9b6ea5f5114c9f362188bc2f..e1e2bda76ad041a3783c01c16d2e3976cfa1526d 100644 (file)
@@ -226,12 +226,12 @@ export class Secp256k1 {
        }
 
        /** modular division */
-       static M (a: bigint, b: bigint = this.P): bigint {
+       static M (a: bigint, b: bigint): bigint {
                const r = a % b
                return r >= 0n ? r : b + r
        }
-
        static modN = (a: bigint) => this.M(a, this.N)
+       static modP = (a: bigint) => this.M(a, this.P)
 
        /** Modular inversion using eucledian GCD (non-CT). No negative exponent for now. */
        // prettier-ignore
@@ -256,7 +256,7 @@ export class Secp256k1 {
        // -----------------
 
        /** secp256k1 formula. Koblitz curves are subclass of weierstrass curves with a=0, making it x³+b */
-       static koblitz = (x: bigint) => this.M(this.M(x * x) * x + this._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) */
@@ -281,7 +281,7 @@ export class Secp256k1 {
                        if (e & 1n) r = (r * num) % this.P // Uses exponentiation by squaring.
                        num = (num * num) % this.P // Not constant-time.
                }
-               return this.M(r * r) === c ? r : this.err('sqrt invalid') // check if result is valid
+               return this.modP(r * r) === c ? r : this.err('sqrt invalid') // check if result is valid
        }
 
        /** Point in 3d xyz projective coordinates. 3d takes less inversions than 2d. */
@@ -295,15 +295,15 @@ export class Secp256k1 {
                        equals (other: Point): boolean {
                                const { X: X1, Y: Y1, Z: Z1 } = this
                                const { X: X2, Y: Y2, Z: Z2 } = other
-                               const X1Z2 = secp256k1.M(X1 * Z2)
-                               const X2Z1 = secp256k1.M(X2 * Z1)
-                               const Y1Z2 = secp256k1.M(Y1 * Z2)
-                               const Y2Z1 = secp256k1.M(Y2 * Z1)
+                               const X1Z2 = secp256k1.modP(X1 * Z2)
+                               const X2Z1 = secp256k1.modP(X2 * Z1)
+                               const Y1Z2 = secp256k1.modP(Y1 * Z2)
+                               const Y2Z1 = secp256k1.modP(Y2 * Z1)
                                return X1Z2 === X2Z1 && Y1Z2 === Y2Z1
                        },
                        /** Flip point over y coordinate. */
                        negate (): Point {
-                               return secp256k1.Point(X, secp256k1.M(-Y), Z)
+                               return secp256k1.Point(X, secp256k1.modP(-Y), Z)
                        },
                        /** Point doubling: P+P, complete formula. */
                        double (): Point {
@@ -316,7 +316,7 @@ export class Secp256k1 {
                         */
                        // prettier-ignore
                        add (other: Point): Point {
-                               const M = (v: bigint): bigint => secp256k1.M(v)
+                               const M = (v: bigint): bigint => secp256k1.modP(v)
                                const { X: X1, Y: Y1, Z: Z1 } = { X, Y, Z }
                                const { X: X2, Y: Y2, Z: Z2 } = other
                                const a = 0n
@@ -378,9 +378,9 @@ export class Secp256k1 {
                                if (z === 1n) return { x, y }
                                const iz = secp256k1.invert(z, secp256k1.P)
                                // (Z * Z^-1) must be 1, otherwise bad math
-                               if (secp256k1.M(z * iz) !== 1n) secp256k1.err('inverse invalid')
+                               if (secp256k1.modP(z * iz) !== 1n) secp256k1.err('inverse invalid')
                                // x = X*Z^-1; y = Y*Z^-1
-                               return { x: secp256k1.M(x * iz), y: secp256k1.M(y * iz) }
+                               return { x: secp256k1.modP(x * iz), y: secp256k1.modP(y * iz) }
                        },
                        /** Checks if the point is valid and on-curve. */
                        assertValidity (): Point {
@@ -388,7 +388,7 @@ export class Secp256k1 {
                                secp256k1.FpIsValidNot0(x) // must be in range 1 <= x,y < P
                                secp256k1.FpIsValidNot0(y)
                                // y² == x³ + ax + b, equation sides must be equal
-                               return secp256k1.M(y * y) === secp256k1.koblitz(x) ? this : secp256k1.err('bad point: not on curve')
+                               return secp256k1.modP(y * y) === secp256k1.koblitz(x) ? this : secp256k1.err('bad point: not on curve')
                        },
                        /** Converts point to 33/65-byte Uint8Array. */
                        toBytes (isCompressed = true): Bytes {
@@ -425,7 +425,7 @@ export class Secp256k1 {
                        let y = this.lift_x(x)
                        const evenY = this.isEven(y)
                        const evenH = this.isEven(BigInt(head))
-                       if (evenH !== evenY) y = this.M(-y)
+                       if (evenH !== evenY) y = this.modP(-y)
                        p = this.Point(x, y, 1n)
                }
                // Uncompressed 65-byte point, 0x04 prefix
@@ -1029,7 +1029,7 @@ export class Secp256k1 {
                        // Fail if x ≥ p. Let c = x³ + 7 mod p.
                        const x = this.bytesToBigint(pub)
                        const y = this.lift_x(x) // Let y = c^(p+1)/4 mod p.
-                       const y_ = this.isEven(y) ? y : this.M(-y)
+                       const y_ = this.isEven(y) ? y : this.modP(-y)
                        // Return the unique point P such that x(P) = x and
                        // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
                        const P_ = this.Point(x, y_, 1n).assertValidity()