UNPKG

@covenance/dlc

Version:

Crypto and Bitcoin functions for Covenance DLC implementation

338 lines (337 loc) 13 kB
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ declare const CURVE: Readonly<{ a: bigint; b: bigint; P: bigint; n: bigint; h: bigint; Gx: bigint; Gy: bigint; beta: bigint; }>; export { CURVE }; type Hex = Uint8Array | string; type PrivKey = Hex | bigint | number; type PubKey = Hex | Point; type Sig = Hex | Signature; /** * Jacobian Point works in 3d / jacobi coordinates: (x, y, z) ∋ (x=x/z², y=y/z³) * Default Point works in 2d / affine coordinates: (x, y) * We're doing calculations in jacobi, because its operations don't require costly inversion. */ declare class JacobianPoint { readonly x: bigint; readonly y: bigint; readonly z: bigint; constructor(x: bigint, y: bigint, z: bigint); static readonly BASE: JacobianPoint; static readonly ZERO: JacobianPoint; static fromAffine(p: Point): JacobianPoint; /** * Takes a bunch of Jacobian Points but executes only one * invert on all of them. invert is very slow operation, * so this improves performance massively. */ static toAffineBatch(points: JacobianPoint[]): Point[]; static normalizeZ(points: JacobianPoint[]): JacobianPoint[]; /** * Compare one point to another. */ equals(other: JacobianPoint): boolean; /** * Flips point to one corresponding to (x, -y) in Affine coordinates. */ negate(): JacobianPoint; double(): JacobianPoint; add(other: JacobianPoint): JacobianPoint; subtract(other: JacobianPoint): JacobianPoint; /** * Non-constant-time multiplication. Uses double-and-add algorithm. * It's faster, but should only be used when you don't care about * an exposed private key e.g. sig verification, which works over *public* keys. */ multiplyUnsafe(scalar: bigint): JacobianPoint; /** * Creates a wNAF precomputation window. Used for caching. * Default window size is set by `utils.precompute()` and is equal to 8. * Which means we are caching 65536 points: 256 points for every bit from 0 to 256. * @returns 65K precomputed points, depending on W */ private precomputeWindow; /** * Implements w-ary non-adjacent form for calculating ec multiplication. * @param n * @param affinePoint optional 2d point to save cached precompute windows on it. * @returns real and fake (for const-time) points */ private wNAF; /** * Constant time multiplication. * Uses wNAF method. Windowed method may be 10% faster, * but takes 2x longer to generate and consumes 2x memory. * @param scalar by which the point would be multiplied * @param affinePoint optional point ot save cached precompute windows on it * @returns New point */ multiply(scalar: number | bigint, affinePoint?: Point): JacobianPoint; toAffine(invZ?: bigint): Point; } /** * Default Point works in default aka affine coordinates: (x, y) */ export declare class Point { readonly x: bigint; readonly y: bigint; /** * Base point aka generator. public_key = Point.BASE * private_key */ static BASE: Point; /** * Identity point aka point at infinity. point = point + zero_point */ static ZERO: Point; _WINDOW_SIZE?: number; constructor(x: bigint, y: bigint); _setWindowSize(windowSize: number): void; hasEvenY(): boolean; /** * Supports compressed Schnorr and ECDSA points * @param bytes * @returns Point instance */ private static fromCompressedHex; private static fromUncompressedHex; /** * Converts hash string or Uint8Array to Point. * @param hex schnorr or ECDSA hex */ static fromHex(hex: Hex): Point; static fromPrivateKey(privateKey: PrivKey): Point; /** * Recovers public key from ECDSA signature. * https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Public_key_recovery * ``` * recover(r, s, h) where * u1 = hs^-1 mod n * u2 = sr^-1 mod n * Q = u1⋅G + u2⋅R * ``` */ static fromSignature(msgHash: Hex, signature: Sig, recovery: number): Point; toRawBytes(isCompressed?: boolean): Uint8Array; toHex(isCompressed?: boolean): string; toHexX(): string; toRawX(): Uint8Array<ArrayBuffer>; assertValidity(): void; equals(other: Point): boolean; negate(): Point; double(): Point; add(other: Point): Point; subtract(other: Point): Point; multiply(scalar: number | bigint): Point; /** * Efficiently calculate `aP + bQ`. * Unsafe, can expose private key, if used incorrectly. * TODO: Utilize Shamir's trick * @returns non-zero affine point */ multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined; } export declare class Signature { readonly r: bigint; readonly s: bigint; constructor(r: bigint, s: bigint); static fromCompact(hex: Hex): Signature; static fromDER(hex: Hex): Signature; static fromHex(hex: Hex): Signature; assertValidity(): void; hasHighS(): boolean; normalizeS(): Signature; toDERRawBytes(): Uint8Array<ArrayBufferLike>; toDERHex(): string; toRawBytes(): Uint8Array<ArrayBufferLike>; toHex(): string; toCompactRawBytes(): Uint8Array<ArrayBufferLike>; toCompactHex(): string; } declare function concatBytes(...arrays: Uint8Array[]): Uint8Array; /** * Convert byte array to hex string. Uses built-in function, when available. * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' */ export declare function bytesToHex(bytes: Uint8Array): string; /** * Convert hex string to byte array. Uses built-in function, when available. * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) */ export declare function hexToBytes(hex: string): Uint8Array; declare function numTo32b(num: bigint): Uint8Array; declare function mod(a: bigint, b?: bigint): bigint; declare function invert(number: bigint, modulo?: bigint): bigint; type U8A = Uint8Array; type Sha256FnSync = undefined | ((...messages: Uint8Array[]) => Uint8Array); type HmacFnSync = undefined | ((key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array); declare function normalizePrivateKey(key: PrivKey): bigint; /** * Computes public key for secp256k1 private key. * @param privateKey 32-byte private key * @param isCompressed whether to return compact, or full key * @returns Public key, full by default; short when isCompressed=true */ export declare function getPublicKey(privateKey: PrivKey, isCompressed?: boolean): Uint8Array; /** * Recovers public key from signature and recovery bit. Throws on invalid sig/hash. * @param msgHash message hash * @param signature DER or compact sig * @param recovery 0 or 1 * @param isCompressed whether to return compact, or full key * @returns Public key, full by default; short when isCompressed=true */ export declare function recoverPublicKey(msgHash: Hex, signature: Sig, recovery: number, isCompressed?: boolean): Uint8Array; /** * ECDH (Elliptic Curve Diffie Hellman) implementation. * 1. Checks for validity of private key * 2. Checks for the public key of being on-curve * @param privateA private key * @param publicB different public key * @param isCompressed whether to return compact, or full key * @returns shared public key */ export declare function getSharedSecret(privateA: PrivKey, publicB: PubKey, isCompressed?: boolean): Uint8Array; type Entropy = Hex | true; type OptsOther = { canonical?: boolean; der?: boolean; extraEntropy?: Entropy; }; type OptsRecov = { recovered: true; } & OptsOther; type OptsNoRecov = { recovered?: false; } & OptsOther; /** * Signs message hash (not message: you need to hash it by yourself). * We don't auto-hash because some users would want non-SHA256 hash. * We are always using deterministic signatures (RFC6979 3.1) instead of * letting user specify random k. * HMAC-DRBG generates k, then calculates sig point Q & signature r, s based on it. * Could receive extra entropy k' as per RFC6979 3.6 Additional data. * k' is not generated by default, because of backwards-compatibility concerns. * We strongly recommend to pass {extraEntropy: true}. * * low-s signatures are generated by default. If you don't want it, use canonical: false. * * ``` * sign(m, d, k) where * (x, y) = G × k * r = x mod n * s = (m + dr)/k mod n * ``` * @param opts `recovered, canonical, der, extraEntropy` */ declare function sign(msgHash: Hex, privKey: PrivKey, opts: OptsRecov): Promise<[U8A, number]>; declare function sign(msgHash: Hex, privKey: PrivKey, opts?: OptsNoRecov): Promise<U8A>; /** * Signs message hash (not message: you need to hash it by yourself). * Synchronous version of `sign()`: see its documentation. * @param opts `recovered, canonical, der, extraEntropy` */ declare function signSync(msgHash: Hex, privKey: PrivKey, opts: OptsRecov): [U8A, number]; declare function signSync(msgHash: Hex, privKey: PrivKey, opts?: OptsNoRecov): U8A; export { sign, signSync }; type VOpts = { strict?: boolean; }; /** * Verifies a signature against message hash and public key. * Rejects non-canonical / high-s signatures by default: to override, * specify option `{strict: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: * * ``` * verify(r, s, h, P) where * U1 = hs^-1 mod n * U2 = rs^-1 mod n * R = U1⋅G - U2⋅P * mod(R.x, n) == r * ``` */ export declare function verify(signature: Sig, msgHash: Hex, publicKey: PubKey, opts?: VOpts): boolean; declare class SchnorrSignature { readonly r: bigint; readonly s: bigint; constructor(r: bigint, s: bigint); static fromHex(hex: Hex): SchnorrSignature; assertValidity(): void; toHex(): string; toRawBytes(): Uint8Array; } declare function schnorrGetPublicKey(privateKey: PrivKey): Uint8Array; /** * Creates Schnorr signature. Improved security: verifies itself before producing an output. * @param msg message (not message hash) * @param privateKey private key * @param auxRand random bytes that would be added to k. Bad RNG won't break it. */ declare function schnorrSign(msg: Hex, privKey: PrivKey, auxRand?: Hex): Promise<Uint8Array>; /** * Synchronously creates Schnorr signature. Improved security: verifies itself before * producing an output. * @param msg message (not message hash) * @param privateKey private key * @param auxRand random bytes that would be added to k. Bad RNG won't break it. */ declare function schnorrSignSync(msg: Hex, privKey: PrivKey, auxRand?: Hex): Uint8Array; /** * Verifies Schnorr signature. */ declare function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): Promise<boolean>; /** * Verifies Schnorr signature synchronously. */ declare function schnorrVerifySync(signature: Hex, message: Hex, publicKey: Hex): boolean; export declare const schnorr: { Signature: typeof SchnorrSignature; getPublicKey: typeof schnorrGetPublicKey; sign: typeof schnorrSign; verify: typeof schnorrVerify; signSync: typeof schnorrSignSync; verifySync: typeof schnorrVerifySync; }; export declare const utils: { bytesToHex: typeof bytesToHex; hexToBytes: typeof hexToBytes; concatBytes: typeof concatBytes; mod: typeof mod; invert: typeof invert; isValidPrivateKey(privateKey: PrivKey): boolean; _bigintTo32Bytes: typeof numTo32b; _normalizePrivateKey: typeof normalizePrivateKey; /** * Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF * and convert them into private key, with the modulo bias being neglible. * As per FIPS 186 B.4.1. * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ * @param hash hash output from sha512, or a similar function * @returns valid private key */ hashToPrivateKey: (hash: Hex) => Uint8Array; randomBytes: (bytesLength?: number) => Uint8Array; randomPrivateKey: () => Uint8Array; /** * 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it. * 2. Precomputes point multiplication table. Is done by default on first `getPublicKey()` call. * If you want your first getPublicKey to take 0.16ms instead of 20ms, make sure to call * utils.precompute() somewhere without arguments first. * @param windowSize 2, 4, 8, 16 * @returns cached point */ precompute(windowSize?: number, point?: Point): Point; sha256: (...messages: Uint8Array[]) => Promise<Uint8Array>; hmacSha256: (key: Uint8Array, ...messages: Uint8Array[]) => Promise<Uint8Array>; sha256Sync: Sha256FnSync; hmacSha256Sync: HmacFnSync; taggedHash: (tag: string, ...messages: Uint8Array[]) => Promise<Uint8Array>; taggedHashSync: (tag: string, ...messages: Uint8Array[]) => Uint8Array; _JacobianPoint: typeof JacobianPoint; };