From 688d8239b84704ae4044218bd7767ec284ec1830 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Wed, 3 Dec 2025 15:46:18 -0800 Subject: [PATCH] Remove string handling from byte casting to bigint. Remove some redundant or unused functions. --- src/lib/crypto/secp256k1.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/lib/crypto/secp256k1.ts b/src/lib/crypto/secp256k1.ts index 683b37a..7e66c80 100644 --- a/src/lib/crypto/secp256k1.ts +++ b/src/lib/crypto/secp256k1.ts @@ -385,7 +385,7 @@ export class Secp256k1 { const length = bytes.length const head = bytes[0] const tail = bytes.subarray(1) - const x = this.sliceBytesNumBE(tail, 0, this.L) + const x = this.bytesToBigint(tail.subarray(0, this.L)) // No actual validation is done here: use .assertValidity() if (length === comp && (head === 0x02 || head === 0x03)) { // Equation is y² == x³ + ax + b. We calculate y from x. @@ -397,7 +397,7 @@ export class Secp256k1 { p = this.Point(x, y, 1n) } // Uncompressed 65-byte point, 0x04 prefix - if (length === uncomp && head === 0x04) p = this.Point(x, this.sliceBytesNumBE(tail, this.L, this.L2), 1n) + if (length === uncomp && head === 0x04) p = this.Point(x, this.bytesToBigint(tail.subarray(this.L, this.L2)), 1n) // Validate point return p ? p.assertValidity() : this.err('bad point: not on curve') } @@ -415,8 +415,14 @@ export class Secp256k1 { return this.G.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2)).assertValidity() } - static bytesToBigint = (b: Bytes): bigint => BigInt('0x' + (this.bytesToHex(b) || '0')) - static sliceBytesNumBE = (b: Bytes, from: number, to: number) => this.bytesToBigint(b.subarray(from, to)) + static bytesToBigint (b: Bytes): bigint { + let int = BigInt(b[0]), len = b.length + for (let i = 1; i < len; i++) { + int <<= 8n + int |= BigInt(b[i]) + } + return int + } /** Number to 32b. Must be 0 <= num < 2²⁵⁶. validate, pad, to bytes. */ static bigintTo32Bytes (num: bigint): Bytes { @@ -426,13 +432,13 @@ export class Secp256k1 { .padStart(this.L2, '0') ) } + /** Normalize private key to scalar (bigint). Verifies scalar is in range 1 n > this.N >> 1n + /** Creates 33/65-byte public key from 32-byte private key. */ static getPublicKey (privKey: Bytes, isCompressed = true): Bytes { return this.G.multiply(this.secretKeyToScalar(privKey)).toBytes(isCompressed) @@ -505,9 +511,6 @@ export class Secp256k1 { addRecoveryBit: (bit: number): RecoveredSignature => { return this.Signature(r, s, bit) as RecoveredSignature }, - hasHighS: (): boolean => { - return this.highS(s) - }, toBytes: (format: ECDSASignatureFormat = this.SIG_COMPACT): Bytes => { const res = this.concatBytes(this.bigintTo32Bytes(r), this.bigintTo32Bytes(s)) if (format === this.SIG_RECOVERED) { @@ -526,8 +529,8 @@ export class Secp256k1 { recoveryBit = b[0] b = b.subarray(1) } - const r = this.sliceBytesNumBE(b, 0, this.L) - const s = this.sliceBytesNumBE(b, this.L, this.L2) + const r = this.bytesToBigint(b.subarray(0, this.L)) + const s = this.bytesToBigint(b.subarray(this.L, this.L2)) return this.Signature(r, s, recoveryBit) } -- 2.47.3