@noble/secp256k1
Advanced tools
Comparing version 2.2.2 to 2.2.3
@@ -13,11 +13,23 @@ /** | ||
}; | ||
/** Alias to Uint8Array. */ | ||
export type Bytes = Uint8Array; | ||
/** Hex-encoded string or Uint8Array. */ | ||
export type Hex = Bytes | string; | ||
/** Hex-encoded string, Uint8Array or bigint. */ | ||
export type PrivKey = Hex | bigint; | ||
/** Signature instance. Has properties r and s. */ | ||
export type SigLike = { | ||
r: bigint; | ||
s: bigint; | ||
}; | ||
/** Signature instance, which allows recovering pubkey from it. */ | ||
export type SignatureWithRecovery = Signature & { | ||
recovery: number; | ||
}; | ||
/** Point in 2d xy affine coordinates. */ | ||
interface AffinePoint { | ||
export interface AffinePoint { | ||
x: bigint; | ||
y: bigint; | ||
} | ||
/** Point in 3d xyz projective coordinates. */ | ||
/** Point in 3d xyz projective coordinates. 3d takes less inversions than 2d. */ | ||
declare class Point { | ||
@@ -28,16 +40,31 @@ readonly px: bigint; | ||
constructor(px: bigint, py: bigint, pz: bigint); | ||
/** Generator / base point */ | ||
static readonly BASE: Point; | ||
/** Identity / zero point */ | ||
static readonly ZERO: Point; | ||
/** Create 3d xyz point from 2d xy. (0, 0) => (0, 1, 0), not (0, 0, 1) */ | ||
static fromAffine(p: AffinePoint): Point; | ||
/** Convert Uint8Array or hex string to Point. */ | ||
static fromHex(hex: Hex): Point; | ||
/** Create point from a private key. */ | ||
static fromPrivateKey(k: PrivKey): Point; | ||
get x(): bigint; | ||
get y(): bigint; | ||
/** Equality check: compare points P&Q. */ | ||
equals(other: Point): boolean; | ||
/** Flip point over y coordinate. */ | ||
negate(): Point; | ||
/** Point doubling: P+P, complete formula. */ | ||
double(): Point; | ||
/** | ||
* Point addition: P+Q, complete, exception-free formula | ||
* (Renes-Costello-Batina, algo 1 of [2015/1060](https://eprint.iacr.org/2015/1060)). | ||
* Cost: 12M + 0S + 3*a + 3*b3 + 23add. | ||
*/ | ||
add(other: Point): Point; | ||
mul(n: bigint, safe?: boolean): Point; | ||
mulAddQUns(R: Point, u1: bigint, u2: bigint): Point; | ||
/** Convert point to 2d xy affine point. (x, y, z) ∋ (x=x/z, y=y/z) */ | ||
toAffine(): AffinePoint; | ||
/** Checks if the point is valid and on-curve. */ | ||
assertValidity(): Point; | ||
@@ -50,8 +77,4 @@ multiply(n: bigint): Point; | ||
} | ||
/** Create public key from private. Output is compressed 33b or uncompressed 65b. */ | ||
/** Creates 33/65-byte public key from 32-byte private key. */ | ||
declare const getPublicKey: (privKey: PrivKey, isCompressed?: boolean) => Bytes; | ||
/** Signature which allows recovering pubkey from it. */ | ||
export type SignatureWithRecovery = Signature & { | ||
recovery: number; | ||
}; | ||
/** ECDSA Signature class. Supports only compact 64-byte representation, not DER. */ | ||
@@ -63,9 +86,14 @@ declare class Signature { | ||
constructor(r: bigint, s: bigint, recovery?: number | undefined); | ||
/** Create signature from 64b compact (r || s) representation. */ | ||
static fromCompact(hex: Hex): Signature; | ||
assertValidity(): Signature; | ||
/** Create new signature, with added recovery bit. */ | ||
addRecoveryBit(rec: number): SignatureWithRecovery; | ||
hasHighS(): boolean; | ||
normalizeS(): Signature; | ||
/** ECDSA public key recovery. Requires msg hash and recovery id. */ | ||
recoverPublicKey(msgh: Hex): Point; | ||
/** Uint8Array 64b compact (r || s) representation. */ | ||
toCompactRawBytes(): Bytes; | ||
/** Hex string 64b compact (r || s) representation. */ | ||
toCompactHex(): string; | ||
@@ -84,4 +112,8 @@ } | ||
* Sign a msg hash using secp256k1. Async. | ||
* It is advised to use `extraEntropy: true` (from RFC6979 3.6) to prevent fault attacks. | ||
* Worst case: if randomness source for extraEntropy is bad, it would be as secure as if | ||
* the option has not been used. | ||
* @param msgh - message HASH, not message itself e.g. sha256(message) | ||
* @param priv - private key | ||
* @param opts - `lowS: true` to prevent malleability (s >= CURVE.n/2), `extraEntropy: boolean | Hex` to improve sig security. | ||
*/ | ||
@@ -91,10 +123,12 @@ declare const signAsync: (msgh: Hex, priv: PrivKey, opts?: OptS) => Promise<SignatureWithRecovery>; | ||
* Sign a msg hash using secp256k1. | ||
* It is advised to use `extraEntropy: true` (from RFC6979 3.6) to prevent fault attacks. | ||
* Worst case: if randomness source for extraEntropy is bad, it would be as secure as if | ||
* the option has not been used. | ||
* @param msgh - message HASH, not message itself e.g. sha256(message) | ||
* @param priv - private key | ||
* @param opts - `lowS: true` to prevent malleability (s >= CURVE.n/2), `extraEntropy: boolean | Hex` to improve sig security. | ||
* @example | ||
* const sig = sign(sha256('hello'), privKey, { extraEntropy: true }).toCompactRawBytes(); | ||
*/ | ||
declare const sign: (msgh: Hex, priv: PrivKey, opts?: OptS) => SignatureWithRecovery; | ||
type SigLike = { | ||
r: bigint; | ||
s: bigint; | ||
}; | ||
/** | ||
@@ -105,2 +139,3 @@ * Verify a signature using secp256k1. | ||
* @param pub - public key | ||
* @param opts - { lowS: true } is default, prohibits s >= CURVE.n/2 to prevent malleability | ||
*/ | ||
@@ -107,0 +142,0 @@ declare const verify: (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts?: OptV) => boolean; |
63
index.js
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ | ||
/** | ||
* ECDSA & ECDH over secp256k1 short weierstrass curve. | ||
* 4KB JS implementation of secp256k1 signatures & ECDH. Compliant with RFC6979. | ||
* @module | ||
@@ -36,3 +36,3 @@ */ | ||
const aPoint = (p) => (p instanceof Point ? p : err('Point expected')); // is 3d point | ||
/** Point in 3d xyz projective coordinates. */ | ||
/** Point in 3d xyz projective coordinates. 3d takes less inversions than 2d. */ | ||
class Point { | ||
@@ -45,5 +45,7 @@ constructor(px, py, pz) { | ||
} | ||
/** Create 3d xyz point from 2d xy. (0, 0) => (0, 1, 0), not (0, 0, 1) */ | ||
static fromAffine(p) { | ||
return ((p.x === 0n) && (p.y === 0n)) ? I : new Point(p.x, p.y, 1n); | ||
} | ||
/** Convert Uint8Array or hex string to Point. */ | ||
static fromHex(hex) { | ||
@@ -68,5 +70,7 @@ hex = toU8(hex); // convert hex string to Uint8Array | ||
} | ||
static fromPrivateKey(k) { return G.mul(toPriv(k)); } // Create point from a private key. | ||
/** Create point from a private key. */ | ||
static fromPrivateKey(k) { return G.mul(toPriv(k)); } | ||
get x() { return this.aff().x; } // .x, .y will call expensive toAffine: | ||
get y() { return this.aff().y; } // should be used with care. | ||
/** Equality check: compare points P&Q. */ | ||
equals(other) { | ||
@@ -79,8 +83,15 @@ const { px: X1, py: Y1, pz: Z1 } = this; | ||
} | ||
negate() { return new Point(this.px, M(-this.py), this.pz); } // Flip point over y coord | ||
double() { return this.add(this); } // Point doubling: P+P, complete formula. | ||
/** Flip point over y coordinate. */ | ||
negate() { return new Point(this.px, M(-this.py), this.pz); } | ||
/** Point doubling: P+P, complete formula. */ | ||
double() { return this.add(this); } | ||
/** | ||
* Point addition: P+Q, complete, exception-free formula | ||
* (Renes-Costello-Batina, algo 1 of [2015/1060](https://eprint.iacr.org/2015/1060)). | ||
* Cost: 12M + 0S + 3*a + 3*b3 + 23add. | ||
*/ | ||
add(other) { | ||
const { px: X1, py: Y1, pz: Z1 } = this; // free formula from Renes-Costello-Batina | ||
const { px: X2, py: Y2, pz: Z2 } = aPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 | ||
const { a, b } = CURVE; // Cost: 12M + 0S + 3*a + 3*b3 + 23add | ||
const { px: X1, py: Y1, pz: Z1 } = this; | ||
const { px: X2, py: Y2, pz: Z2 } = aPoint(other); | ||
const { a, b } = CURVE; | ||
let X3 = 0n, Y3 = 0n, Z3 = 0n; | ||
@@ -146,4 +157,5 @@ const b3 = M(b * 3n); | ||
} // to private keys. Doesn't use Shamir trick | ||
/** Convert point to 2d xy affine point. (x, y, z) ∋ (x=x/z, y=y/z) */ | ||
toAffine() { | ||
const { px: x, py: y, pz: z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) | ||
const { px: x, py: y, pz: z } = this; | ||
if (this.equals(I)) | ||
@@ -158,2 +170,3 @@ return { x: 0n, y: 0n }; // fast-path for zero point | ||
} | ||
/** Checks if the point is valid and on-curve. */ | ||
assertValidity() { | ||
@@ -178,4 +191,6 @@ const { x, y } = this.aff(); // convert to 2d xy affine point. | ||
} | ||
Point.BASE = new Point(Gx, Gy, 1n); // Generator / base point | ||
Point.ZERO = new Point(0n, 1n, 0n); // Identity / zero point | ||
/** Generator / base point */ | ||
Point.BASE = new Point(Gx, Gy, 1n); | ||
/** Identity / zero point */ | ||
Point.ZERO = new Point(0n, 1n, 0n); | ||
const { BASE: G, ZERO: I } = Point; // Generator, identity points | ||
@@ -249,3 +264,3 @@ const padh = (n, pad) => n.toString(16).padStart(pad, '0'); | ||
const high = (n) => n > (N >> 1n); // if a number is bigger than CURVE.n/2 | ||
/** Create public key from private. Output is compressed 33b or uncompressed 65b. */ | ||
/** Creates 33/65-byte public key from 32-byte private key. */ | ||
const getPublicKey = (privKey, isCompressed = true) => { | ||
@@ -262,2 +277,3 @@ return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); | ||
} // constructed outside. | ||
/** Create signature from 64b compact (r || s) representation. */ | ||
static fromCompact(hex) { | ||
@@ -268,2 +284,3 @@ hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) | ||
assertValidity() { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n | ||
/** Create new signature, with added recovery bit. */ | ||
addRecoveryBit(rec) { | ||
@@ -276,2 +293,3 @@ return new Signature(this.r, this.s, rec); | ||
} | ||
/** ECDSA public key recovery. Requires msg hash and recovery id. */ | ||
recoverPublicKey(msgh) { | ||
@@ -292,4 +310,6 @@ const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 | ||
} | ||
toCompactRawBytes() { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr | ||
toCompactHex() { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr | ||
/** Uint8Array 64b compact (r || s) representation. */ | ||
toCompactRawBytes() { return h2b(this.toCompactHex()); } | ||
/** Hex string 64b compact (r || s) representation. */ | ||
toCompactHex() { return n2h(this.r) + n2h(this.s); } | ||
} | ||
@@ -308,3 +328,3 @@ const bits2int = (bytes) => { | ||
const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with crypto | ||
typeof globalThis === 'object' && 'crypto' in globalThis && 'subtle' in globalThis.crypto ? globalThis.crypto : undefined; | ||
typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; | ||
let _hmacSync; // Can be redefined by use in utils; built-ins don't provide it | ||
@@ -417,4 +437,8 @@ const optS = { lowS: true }; // opts for sign() | ||
* Sign a msg hash using secp256k1. Async. | ||
* It is advised to use `extraEntropy: true` (from RFC6979 3.6) to prevent fault attacks. | ||
* Worst case: if randomness source for extraEntropy is bad, it would be as secure as if | ||
* the option has not been used. | ||
* @param msgh - message HASH, not message itself e.g. sha256(message) | ||
* @param priv - private key | ||
* @param opts - `lowS: true` to prevent malleability (s >= CURVE.n/2), `extraEntropy: boolean | Hex` to improve sig security. | ||
*/ | ||
@@ -427,4 +451,10 @@ const signAsync = async (msgh, priv, opts = optS) => { | ||
* Sign a msg hash using secp256k1. | ||
* It is advised to use `extraEntropy: true` (from RFC6979 3.6) to prevent fault attacks. | ||
* Worst case: if randomness source for extraEntropy is bad, it would be as secure as if | ||
* the option has not been used. | ||
* @param msgh - message HASH, not message itself e.g. sha256(message) | ||
* @param priv - private key | ||
* @param opts - `lowS: true` to prevent malleability (s >= CURVE.n/2), `extraEntropy: boolean | Hex` to improve sig security. | ||
* @example | ||
* const sig = sign(sha256('hello'), privKey, { extraEntropy: true }).toCompactRawBytes(); | ||
*/ | ||
@@ -440,2 +470,3 @@ const sign = (msgh, priv, opts = optS) => { | ||
* @param pub - public key | ||
* @param opts - { lowS: true } is default, prohibits s >= CURVE.n/2 to prevent malleability | ||
*/ | ||
@@ -511,3 +542,3 @@ const verify = (sig, msgh, pub, opts = optV) => { | ||
if (!s) | ||
return err('etc.hmacSha256Async not set'); // Uses webcrypto built-in cryptography. | ||
return err('etc.hmacSha256Async or crypto.subtle must be defined'); // Uses webcrypto built-in cryptography. | ||
const k = await s.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); | ||
@@ -514,0 +545,0 @@ return u8n(await s.sign('HMAC', k, concatB(...msgs))); |
95
index.ts
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ | ||
/** | ||
* ECDSA & ECDH over secp256k1 short weierstrass curve. | ||
* 4KB JS implementation of secp256k1 signatures & ECDH. Compliant with RFC6979. | ||
* @module | ||
@@ -18,5 +18,12 @@ */ | ||
const fLen = 32; // field / group byte length | ||
/** Alias to Uint8Array. */ | ||
export type Bytes = Uint8Array; | ||
/** Hex-encoded string or Uint8Array. */ | ||
export type Hex = Bytes | string; | ||
/** Hex-encoded string, Uint8Array or bigint. */ | ||
export type PrivKey = Hex | bigint; | ||
/** Signature instance. Has properties r and s. */ | ||
export type SigLike = { r: bigint, s: bigint }; | ||
/** Signature instance, which allows recovering pubkey from it. */ | ||
export type SignatureWithRecovery = Signature & { recovery: number } | ||
const curve = (x: bigint) => M(M(x * x) * x + CURVE.b); // x³ + ax + b weierstrass formula; a=0 | ||
@@ -41,14 +48,18 @@ const err = (m = ''): never => { throw new Error(m); }; // error helper, messes-up stack trace | ||
/** Point in 2d xy affine coordinates. */ | ||
interface AffinePoint { x: bigint, y: bigint } | ||
/** Point in 3d xyz projective coordinates. */ | ||
export interface AffinePoint { x: bigint, y: bigint } | ||
/** Point in 3d xyz projective coordinates. 3d takes less inversions than 2d. */ | ||
class Point { | ||
constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) { //3d=less inversions | ||
constructor(readonly px: bigint, readonly py: bigint, readonly pz: bigint) { | ||
Object.freeze(this); | ||
} | ||
static readonly BASE: Point = new Point(Gx, Gy, 1n); // Generator / base point | ||
static readonly ZERO: Point = new Point(0n, 1n, 0n); // Identity / zero point | ||
static fromAffine(p: AffinePoint): Point { // (0, 0) => (0, 1, 0), not (0, 0, 1) | ||
/** Generator / base point */ | ||
static readonly BASE: Point = new Point(Gx, Gy, 1n); | ||
/** Identity / zero point */ | ||
static readonly ZERO: Point = new Point(0n, 1n, 0n); | ||
/** Create 3d xyz point from 2d xy. (0, 0) => (0, 1, 0), not (0, 0, 1) */ | ||
static fromAffine(p: AffinePoint): Point { | ||
return ((p.x === 0n) && (p.y === 0n)) ? I : new Point(p.x, p.y, 1n); | ||
} | ||
static fromHex(hex: Hex): Point { // Convert Uint8Array or hex string to Point | ||
/** Convert Uint8Array or hex string to Point. */ | ||
static fromHex(hex: Hex): Point { | ||
hex = toU8(hex); // convert hex string to Uint8Array | ||
@@ -69,6 +80,8 @@ let p: Point | undefined = undefined; | ||
} | ||
static fromPrivateKey(k: PrivKey): Point { return G.mul(toPriv(k)); } // Create point from a private key. | ||
/** Create point from a private key. */ | ||
static fromPrivateKey(k: PrivKey): Point { return G.mul(toPriv(k)); } | ||
get x(): bigint { return this.aff().x; } // .x, .y will call expensive toAffine: | ||
get y(): bigint { return this.aff().y; } // should be used with care. | ||
equals(other: Point): boolean { // Equality check: compare points | ||
/** Equality check: compare points P&Q. */ | ||
equals(other: Point): boolean { | ||
const { px: X1, py: Y1, pz: Z1 } = this; | ||
@@ -80,8 +93,15 @@ const { px: X2, py: Y2, pz: Z2 } = aPoint(other); // isPoint() checks class equality | ||
} | ||
negate(): Point { return new Point(this.px, M(-this.py), this.pz); } // Flip point over y coord | ||
double(): Point { return this.add(this); } // Point doubling: P+P, complete formula. | ||
add(other: Point): Point { // Point addition: P+Q, complete, exception | ||
const { px: X1, py: Y1, pz: Z1 } = this; // free formula from Renes-Costello-Batina | ||
const { px: X2, py: Y2, pz: Z2 } = aPoint(other); // https://eprint.iacr.org/2015/1060, algo 1 | ||
const { a, b } = CURVE; // Cost: 12M + 0S + 3*a + 3*b3 + 23add | ||
/** Flip point over y coordinate. */ | ||
negate(): Point { return new Point(this.px, M(-this.py), this.pz); } | ||
/** Point doubling: P+P, complete formula. */ | ||
double(): Point { return this.add(this); } | ||
/** | ||
* Point addition: P+Q, complete, exception-free formula | ||
* (Renes-Costello-Batina, algo 1 of [2015/1060](https://eprint.iacr.org/2015/1060)). | ||
* Cost: 12M + 0S + 3*a + 3*b3 + 23add. | ||
*/ | ||
add(other: Point): Point { | ||
const { px: X1, py: Y1, pz: Z1 } = this; | ||
const { px: X2, py: Y2, pz: Z2 } = aPoint(other); | ||
const { a, b } = CURVE; | ||
let X3 = 0n, Y3 = 0n, Z3 = 0n; | ||
@@ -107,3 +127,3 @@ const b3 = M(b * 3n); | ||
} | ||
mul(n: bigint, safe = true): Point { // Point scalar multiplication. | ||
mul(n: bigint, safe = true): Point { // Point-by-scalar multiplication. | ||
if (!safe && n === 0n) return I; // in unsafe mode, allow zero | ||
@@ -122,4 +142,5 @@ if (!ge(n)) err('scalar invalid'); // must be 0 < n < CURVE.n | ||
} // to private keys. Doesn't use Shamir trick | ||
toAffine(): AffinePoint { // Convert point to 2d xy affine point. | ||
const { px: x, py: y, pz: z } = this; // (x, y, z) ∋ (x=x/z, y=y/z) | ||
/** Convert point to 2d xy affine point. (x, y, z) ∋ (x=x/z, y=y/z) */ | ||
toAffine(): AffinePoint { | ||
const { px: x, py: y, pz: z } = this; | ||
if (this.equals(I)) return { x: 0n, y: 0n }; // fast-path for zero point | ||
@@ -131,3 +152,4 @@ if (z === 1n) return { x, y }; // if z is 1, pass affine coordinates as-is | ||
} | ||
assertValidity(): Point { // Checks if the point is valid and on-curve | ||
/** Checks if the point is valid and on-curve. */ | ||
assertValidity(): Point { | ||
const { x, y } = this.aff(); // convert to 2d xy affine point. | ||
@@ -209,8 +231,6 @@ if (!fe(x) || !fe(y)) err('Point invalid: x or y'); // x and y must be in range 0 < n < P | ||
const high = (n: bigint): boolean => n > (N >> 1n); // if a number is bigger than CURVE.n/2 | ||
/** Create public key from private. Output is compressed 33b or uncompressed 65b. */ | ||
/** Creates 33/65-byte public key from 32-byte private key. */ | ||
const getPublicKey = (privKey: PrivKey, isCompressed = true): Bytes => { | ||
return Point.fromPrivateKey(privKey).toRawBytes(isCompressed); | ||
} | ||
/** Signature which allows recovering pubkey from it. */ | ||
export type SignatureWithRecovery = Signature & { recovery: number } | ||
/** ECDSA Signature class. Supports only compact 64-byte representation, not DER. */ | ||
@@ -221,3 +241,4 @@ class Signature { | ||
} // constructed outside. | ||
static fromCompact(hex: Hex): Signature { // create signature from 64b compact repr | ||
/** Create signature from 64b compact (r || s) representation. */ | ||
static fromCompact(hex: Hex): Signature { | ||
hex = toU8(hex, 64); // compact repr is (32b r)||(32b s) | ||
@@ -227,2 +248,3 @@ return new Signature(slc(hex, 0, fLen), slc(hex, fLen, 2 * fLen)); | ||
assertValidity(): Signature { return ge(this.r) && ge(this.s) ? this : err(); } // 0 < r or s < CURVE.n | ||
/** Create new signature, with added recovery bit. */ | ||
addRecoveryBit(rec: number): SignatureWithRecovery { | ||
@@ -235,3 +257,4 @@ return new Signature(this.r, this.s, rec) as SignatureWithRecovery; | ||
} | ||
recoverPublicKey(msgh: Hex): Point { // ECDSA public key recovery | ||
/** ECDSA public key recovery. Requires msg hash and recovery id. */ | ||
recoverPublicKey(msgh: Hex): Point { | ||
const { r, s, recovery: rec } = this; // secg.org/sec1-v2.pdf 4.1.6 | ||
@@ -249,4 +272,6 @@ if (![0, 1, 2, 3].includes(rec!)) err('recovery id invalid'); // check recovery id | ||
} | ||
toCompactRawBytes(): Bytes { return h2b(this.toCompactHex()); } // Uint8Array 64b compact repr | ||
toCompactHex(): string { return n2h(this.r) + n2h(this.s); } // hex 64b compact repr | ||
/** Uint8Array 64b compact (r || s) representation. */ | ||
toCompactRawBytes(): Bytes { return h2b(this.toCompactHex()); } | ||
/** Hex string 64b compact (r || s) representation. */ | ||
toCompactHex(): string { return n2h(this.r) + n2h(this.s); } | ||
} | ||
@@ -265,3 +290,3 @@ const bits2int = (bytes: Bytes): bigint => { // RFC6979: ensure ECDSA msg is X bytes. | ||
const cr = () => // We support: 1) browsers 2) node.js 19+ 3) deno, other envs with crypto | ||
typeof globalThis === 'object' && 'crypto' in globalThis && 'subtle' in globalThis.crypto ? globalThis.crypto : undefined; | ||
typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; | ||
type HmacFnSync = undefined | ((key: Bytes, ...msgs: Bytes[]) => Bytes); | ||
@@ -367,4 +392,8 @@ let _hmacSync: HmacFnSync; // Can be redefined by use in utils; built-ins don't provide it | ||
* Sign a msg hash using secp256k1. Async. | ||
* It is advised to use `extraEntropy: true` (from RFC6979 3.6) to prevent fault attacks. | ||
* Worst case: if randomness source for extraEntropy is bad, it would be as secure as if | ||
* the option has not been used. | ||
* @param msgh - message HASH, not message itself e.g. sha256(message) | ||
* @param priv - private key | ||
* @param opts - `lowS: true` to prevent malleability (s >= CURVE.n/2), `extraEntropy: boolean | Hex` to improve sig security. | ||
*/ | ||
@@ -377,4 +406,10 @@ const signAsync = async (msgh: Hex, priv: PrivKey, opts: OptS = optS): Promise<SignatureWithRecovery> => { | ||
* Sign a msg hash using secp256k1. | ||
* It is advised to use `extraEntropy: true` (from RFC6979 3.6) to prevent fault attacks. | ||
* Worst case: if randomness source for extraEntropy is bad, it would be as secure as if | ||
* the option has not been used. | ||
* @param msgh - message HASH, not message itself e.g. sha256(message) | ||
* @param priv - private key | ||
* @param opts - `lowS: true` to prevent malleability (s >= CURVE.n/2), `extraEntropy: boolean | Hex` to improve sig security. | ||
* @example | ||
* const sig = sign(sha256('hello'), privKey, { extraEntropy: true }).toCompactRawBytes(); | ||
*/ | ||
@@ -385,3 +420,2 @@ const sign = (msgh: Hex, priv: PrivKey, opts: OptS = optS): SignatureWithRecovery => { | ||
}; | ||
type SigLike = { r: bigint, s: bigint }; | ||
/** | ||
@@ -392,2 +426,3 @@ * Verify a signature using secp256k1. | ||
* @param pub - public key | ||
* @param opts - { lowS: true } is default, prohibits s >= CURVE.n/2 to prevent malleability | ||
*/ | ||
@@ -450,3 +485,3 @@ const verify = (sig: Hex | SigLike, msgh: Hex, pub: Hex, opts: OptV = optV): boolean => { | ||
const s = c && c.subtle; // For React Native support, see README. | ||
if (!s) return err('etc.hmacSha256Async not set'); // Uses webcrypto built-in cryptography. | ||
if (!s) return err('etc.hmacSha256Async or crypto.subtle must be defined'); // Uses webcrypto built-in cryptography. | ||
const k = await s.importKey('raw', key, {name:'HMAC',hash:{name:'SHA-256'}}, false, ['sign']); | ||
@@ -453,0 +488,0 @@ return u8n(await s.sign('HMAC', k, concatB(...msgs))); |
{ | ||
"name": "@noble/secp256k1", | ||
"version": "2.2.2", | ||
"version": "2.2.3", | ||
"description": "Fastest 4KB JS implementation of secp256k1 ECDH & ECDSA signatures compliant with RFC6979", | ||
@@ -33,3 +33,3 @@ "files": [ | ||
"devDependencies": { | ||
"@noble/hashes": "1.6.1", | ||
"@noble/hashes": "1.7.0", | ||
"@paulmillr/jsbt": "0.2.1", | ||
@@ -36,0 +36,0 @@ "fast-check": "3.0.0", |
85614
1299