]> git.codecow.com Git - libnemo.git/commitdiff
Remove redundant string type check. Remove redundant hex string padding. Remove check...
authorChris Duncan <chris@zoso.dev>
Mon, 1 Dec 2025 07:01:29 +0000 (23:01 -0800)
committerChris Duncan <chris@zoso.dev>
Mon, 1 Dec 2025 07:01:29 +0000 (23:01 -0800)
src/lib/crypto/secp256k1.ts

index a656a9b02903ff98f2a4fe55af5c9fe1caaf2974..791ce9dcd24ba9e44e8e7b39f01e1fd983cb7b13 100644 (file)
@@ -33,7 +33,7 @@ type Point = {
 type Signature = ReturnType<typeof Secp256k1.Signature>
 
 /** Alias to Uint8Array. */
-export type Bytes = Uint8Array
+export type Bytes = Uint8Array<ArrayBuffer>
 /** Signature instance, which allows recovering pubkey from it. */
 export type RecoveredSignature = Signature & { recovery: number }
 /** Weierstrass elliptic curve options. */
@@ -46,7 +46,6 @@ export type WeierstrassOpts<T> = Readonly<{
        Gx: T
        Gy: T
 }>
-declare const globalThis: Record<string, any> | undefined // Typescript symbol present in browsers
 /** Point in 2d xy affine coordinates. */
 export type AffinePoint = {
        x: bigint
@@ -155,7 +154,6 @@ export class Secp256k1 {
                this.captureTrace(e, this.err)
                throw e
        }
-       static isStr = (s: unknown): s is string => typeof s === 'string' // is string
        static isBytes = (a: unknown): a is Uint8Array =>
                a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array')
        /** Asserts something is Uint8Array. */
@@ -173,10 +171,9 @@ export class Secp256k1 {
        }
        /** create Uint8Array */
        static u8n = (len: number): Bytes => new Uint8Array(len)
-       static padh = (n: number | bigint, pad: number) => n.toString(16).padStart(pad, '0')
        static bytesToHex = (b: Bytes): string =>
                Array.from(this.abytes(b))
-                       .map((e) => this.padh(e, 2))
+                       .map((e) => e.toString(16).padStart(2, '0'))
                        .join('')
        static C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const // ASCII characters
        static _ch = (ch: number): number | undefined => {
@@ -187,7 +184,7 @@ export class Secp256k1 {
        }
        static hexToBytes = (hex: string): Bytes => {
                const e = 'hex invalid'
-               if (!this.isStr(hex)) return this.err(e)
+               if (hex !== 'string') return this.err(e)
                const hl = hex.length
                const al = hl / 2
                if (hl % 2) return this.err(e)
@@ -201,8 +198,6 @@ export class Secp256k1 {
                }
                return array
        }
-       static cr = () => globalThis?.crypto // WebCrypto is available in all modern environments
-       static subtle = () => this.cr()?.subtle ?? this.err('crypto.subtle must be defined, consider polyfill')
        // prettier-ignore
        static concatBytes = (...arrs: Bytes[]): Bytes => {
                const r = this.u8n(arrs.reduce((sum, a) => sum + this.abytes(a).length, 0)) // create u8a of summed length
@@ -212,8 +207,7 @@ export class Secp256k1 {
        }
        /** WebCrypto OS-level CSPRNG (random number generator). Will throw when not available. */
        static randomBytes = (len: number = this.L): Bytes => {
-               const c = this.cr()
-               return c.getRandomValues(this.u8n(len))
+               return crypto.getRandomValues(this.u8n(len))
        }
        static arange = (n: bigint, min: bigint, max: bigint, msg = 'bad number: out of range'): bigint =>
                typeof n === 'bigint' && min <= n && n < max ? n : this.err(msg)
@@ -446,7 +440,13 @@ export class Secp256k1 {
        static sliceBytesNumBE = (b: Bytes, from: number, to: number) => this.bytesToNumBE(b.subarray(from, to))
        static B256 = 2n ** 256n // secp256k1 is weierstrass curve. Equation is x³ + ax + b.
        /** Number to 32b. Must be 0 <= num < B256. validate, pad, to bytes. */
-       static numTo32b = (num: bigint): Bytes => this.hexToBytes(this.padh(this.arange(num, 0n, this.B256), this.L2))
+       static numTo32b = (num: bigint): Bytes => {
+               return this.hexToBytes(this
+                       .arange(num, 0n, this.B256)
+                       .toString(16)
+                       .padStart(this.L2, '0')
+               )
+       }
        /** Normalize private key to scalar (bigint). Verifies scalar is in range 1<s<N */
        static secretKeyToScalar = (secretKey: Bytes): bigint => {
                const num = this.bytesToNumBE(this.abytes(secretKey, this.L, 'secret key'))
@@ -577,13 +577,12 @@ export class Secp256k1 {
        static _sha = 'SHA-256'
        static hashes = {
                hmacSha256Async: async (key: Bytes, message: Bytes): Promise<Bytes> => {
-                       const s = this.subtle()
                        const name = 'HMAC'
-                       const k = await s.importKey('raw', key, { name, hash: { name: this._sha } }, false, ['sign'])
-                       return this.u8n(await s.sign(name, k, message))
+                       const k = await crypto.subtle.importKey('raw', key, { name, hash: { name: this._sha } }, false, ['sign'])
+                       return new Uint8Array(await crypto.subtle.sign(name, k, message))
                },
                hmacSha256: undefined as undefined | ((key: Bytes, message: Bytes) => Bytes),
-               sha256Async: async (msg: Bytes): Promise<Bytes> => this.u8n(await this.subtle().digest(this._sha, msg)),
+               sha256Async: async (msg: Bytes): Promise<Bytes> => new Uint8Array(await crypto.subtle.digest(this._sha, msg)),
                sha256: undefined as undefined | ((message: Bytes) => Bytes),
        }