}
/** 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
// -----------------
/** 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) */
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. */
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 {
*/
// 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
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 {
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 {
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
// 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()