return int
}
- /** Number to 32b. Must be 0 <= num < 2²⁵⁶. validate, pad, to bytes. */
- static bigintTo32Bytes (num: bigint): Bytes {
- this.bigintInRange(num, 0n, 2n ** 256n) // secp256k1 is weierstrass curve. Equation is x³ + ax + b.
- let len = this.L, bytes = new Uint8Array(len)
- for (let i = len - 1; i >= 0; i--) {
- bytes[i] = Number(num & 0xffn)
- num >>= 8n
- }
- return bytes
- }
-
/** Checks if the point is valid and on-curve. */
- static isValidPoint (p?: Point): Point {
- if (p) {
- const { x, y } = this.Affine(p) // convert to 2d xy affine point.
- this.bigintInRange(x, 1n, this.P) // must be in range 1 <= x,y < P
- this.bigintInRange(y, 1n, this.P)
- // y² == x³ + ax + b, equation sides must be equal
- return this.M(y * y) === this.koblitz(x) ? p : this.err('bad point: not on curve')
- }
- this.err('bad point: undefined')
+ static isValidPoint (p: Point): Point {
+ const { x, y } = this.Affine(p) // convert to 2d xy affine point.
+ this.bigintInRange(x, 1n, this.P) // must be in range 1 <= x,y < P
+ this.bigintInRange(y, 1n, this.P)
+ // y² == x³ + ax + b, equation sides must be equal
+ return this.M(y * y) === this.koblitz(x) ? p : this.err('bad point: not on curve')
}
/** Normalize private key to scalar (bigint). Verifies scalar is in range 1<s<N */
/** Converts point to 33-byte Uint8Array and checks validity. */
static isValidPublicKey (pk: Bytes): boolean {
if (pk.length !== this.C) return false
+ const prefix = pk[0]
+ if (prefix !== 0x02 && prefix !== 0x03) return false
+ const evenH = prefix === 0x02
try {
this.abytes(pk)
- let p: Point | undefined = undefined
- const length = pk.length
- const head = pk[0]
- const tail = pk.subarray(1)
- const x = this.bytesToBigint(tail.subarray(0, this.L))
- // No actual validation is done here until calling isValidPoint()
- if (length === this.C && (head === 0x02 || head === 0x03)) {
- // Equation is y² == x³ + ax + b. We calculate y from x.
- // y = √y²; there are two solutions: y, -y. Determine proper solution based on prefix
- let y = this.lift_x(x)
- const evenY = this.isEven(y)
- const evenH = this.isEven(BigInt(head))
- if (evenH !== evenY) y = this.M(-y)
- p = this.Point(x, y, 1n)
- }
+ const x = this.bytesToBigint(pk.subarray(1))
+ // Equation is y² == x³ + ax + b. We calculate y from x.
+ // y = √y²; there are two solutions: y, -y. Determine proper solution based on SEC1 prefix
+ let y = this.lift_x(x)
+ const evenY = this.isEven(y)
+ if (evenH !== evenY) y = this.M(-y)
+ const p = this.Point(x, y, 1n)
// Validate point
return !!this.isValidPoint(p)
} catch (error) {