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. */
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
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. */
}
/** 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 => {
}
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)
}
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
}
/** 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)
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'))
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),
}