* Functionality wrapped in a class for embedding into a Web Worker.
*/
+type Point = InstanceType<typeof Secp256k1.Point>
+type Signature = ReturnType<typeof Secp256k1.Signature>
+
/** Alias to Uint8Array. */
export type Bytes = Uint8Array
/** Signature instance, which allows recovering pubkey from it. */
type MaybePromise<T> = T | Promise<T>
-type Point = InstanceType<typeof Secp256k1.Point>
-type Signature = InstanceType<typeof Secp256k1.Signature>
-
export class Secp256k1 {
/**
* Curve params. secp256k1 is short weierstrass / koblitz curve. Equation is y² == x³ + ax + b.
/** Create 3d xyz point from 2d xy. (0, 0) => (0, 1, 0), not (0, 0, 1) */
static pointFromAffine (ap: AffinePoint): Point {
const { x, y } = ap
- return x === 0n && y === 0n ? Secp256k1.I : new this.Point(x, y, 1n)
+ return x === 0n && y === 0n ? this.I : new this.Point(x, y, 1n)
}
/** Convert Uint8Array or hex string to Point. */
static pointFromBytes (bytes: Bytes): Point {
return p ? p.assertValidity() : this.err('bad point: not on curve')
}
static pointFromHex (hex: string): Point {
- return this.pointFromBytes(Secp256k1.hexToBytes(hex))
+ return this.pointFromBytes(this.hexToBytes(hex))
}
/** Generator / base point */
static ALL_SIG = [this.SIG_COMPACT, this.SIG_RECOVERED, this.SIG_DER] as const
/** ECDSA Signature class. Supports only compact 64-byte representation, not DER. */
- static Signature = class {
- readonly r: bigint
- readonly s: bigint
- readonly recovery?: number
- constructor (r: bigint, s: bigint, recovery?: number) {
- this.r = Secp256k1.FnIsValidNot0(r) // 1 <= r < N
- this.s = Secp256k1.FnIsValidNot0(s) // 1 <= s < N
- if (recovery != null) this.recovery = recovery
- Object.freeze(this)
- }
- addRecoveryBit (bit: number): RecoveredSignature {
- return new Secp256k1.Signature(this.r, this.s, bit) as RecoveredSignature
- }
- hasHighS (): boolean {
- return Secp256k1.highS(this.s)
- }
- toBytes (format: ECDSASignatureFormat = Secp256k1.SIG_COMPACT): Bytes {
- const { r, s, recovery } = this
- const res = Secp256k1.concatBytes(Secp256k1.numTo32b(r), Secp256k1.numTo32b(s))
- if (format === Secp256k1.SIG_RECOVERED) {
- Secp256k1.assertRecoveryBit(recovery)
- return Secp256k1.concatBytes(Uint8Array.of(recovery!), res)
+ static Signature = (r: bigint, s: bigint, recovery?: number) => {
+ return Object.freeze({
+ r: this.FnIsValidNot0(r), // 1 <= r < N
+ s: this.FnIsValidNot0(s), // 1 <= s < N
+ recovery: recovery ?? undefined,
+ 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.numTo32b(r), this.numTo32b(s))
+ if (format === this.SIG_RECOVERED) {
+ this.assertRecoveryBit(recovery)
+ return this.concatBytes(Uint8Array.of(recovery!), res)
+ }
+ return res
}
- return res
- }
+ })
}
- static signatureFromBytes (b: Bytes, format: ECDSASignatureFormat = Secp256k1.SIG_COMPACT): Signature {
- Secp256k1.assertSigLength(b, format)
+ static signatureFromBytes (b: Bytes, format: ECDSASignatureFormat = this.SIG_COMPACT): Signature {
+ this.assertSigLength(b, format)
let rec: number | undefined
- if (format === Secp256k1.SIG_RECOVERED) {
+ if (format === this.SIG_RECOVERED) {
rec = b[0]
b = b.subarray(1)
}
- const r = Secp256k1.sliceBytesNumBE(b, 0, Secp256k1.L)
- const s = Secp256k1.sliceBytesNumBE(b, Secp256k1.L, Secp256k1.L2)
- return new this.Signature(r, s, rec)
+ const r = this.sliceBytesNumBE(b, 0, this.L)
+ const s = this.sliceBytesNumBE(b, this.L, this.L2)
+ return this.Signature(r, s, rec)
}
/**
normS = this.modN(-s) // in the bottom half of CURVE.n
recovery ^= 1
}
- const sig = new this.Signature(r, normS, recovery) as RecoveredSignature // use normS, not s
+ const sig = this.Signature(r, normS, recovery) as RecoveredSignature // use normS, not s
return sig.toBytes(opts.format)
}
return hmacDrbg(seed, k2sig)