Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

noble-secp256k1

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

noble-secp256k1 - npm Package Compare versions

Comparing version 1.0.6 to 1.1.0

13

index.d.ts

@@ -66,7 +66,20 @@ declare const CURVE: {

export declare function verify(signature: Signature, msgHash: Hex, publicKey: PubKey): boolean;
declare class SchnorrSignResult {
readonly r: bigint;
readonly s: bigint;
constructor(r: bigint, s: bigint);
toHex(): string;
toRawBytes(): Uint8Array;
}
export declare const schnorr: {
SignResult: typeof SchnorrSignResult;
sign(message: Hex, privateKey: PrivKey, auxRand?: Hex): Promise<SchnorrSignResult>;
verify(signature: SchnorrSignResult, message: Hex, publicKey: PubKey): Promise<boolean>;
};
export declare const utils: {
isValidPrivateKey(privateKey: PrivKey): boolean;
randomPrivateKey: (bytesLength?: number) => Uint8Array;
sha256: (message: Uint8Array) => Promise<Uint8Array>;
hmacSha256: (key: Uint8Array, ...messages: Uint8Array[]) => Promise<Uint8Array>;
precompute(windowSize?: number, point?: Point): Point;
};

97

index.js

@@ -273,3 +273,3 @@ 'use strict';

static fromHex(hex) {
const bytes = hex instanceof Uint8Array ? hex : hexToArray(hex);
const bytes = hex instanceof Uint8Array ? hex : hexToBytes(hex);
const header = bytes[0];

@@ -301,3 +301,3 @@ if (header === 0x02 || header === 0x03)

toRawBytes(isCompressed = false) {
return hexToArray(this.toHex(isCompressed));
return hexToBytes(this.toHex(isCompressed));
}

@@ -377,3 +377,3 @@ toHex(isCompressed = false) {

toRawBytes(isCompressed = false) {
return hexToArray(this.toHex(isCompressed));
return hexToBytes(this.toHex(isCompressed));
}

@@ -414,2 +414,5 @@ toHex(isCompressed = false) {

}
function pad32b(num) {
return hexToBytes(pad64(num));
}
function numberToHex(num) {

@@ -425,3 +428,3 @@ const hex = num.toString(16);

}
function hexToArray(hex) {
function hexToBytes(hex) {
hex = hex.length & 1 ? `0${hex}` : hex;

@@ -528,4 +531,4 @@ const array = new Uint8Array(hex.length / 2);

const num = typeof msgHash === 'string' ? hexToNumber(msgHash) : bytesToNumber(msgHash);
const h1 = hexToArray(pad64(num));
const x = hexToArray(pad64(privateKey));
const h1 = pad32b(num);
const x = pad32b(privateKey);
const h1n = bytesToNumber(h1);

@@ -655,2 +658,69 @@ let v = new Uint8Array(32).fill(1);

exports.verify = verify;
function rawX(point) {
return point.toRawBytes(true).slice(1);
}
async function taggedHash(tag, ...messages) {
const tagB = new Uint8Array(tag.split('').map((c) => c.charCodeAt(0)));
const tagH = await exports.utils.sha256(tagB);
const h = await exports.utils.sha256(concatBytes(tagH, tagH, ...messages));
return bytesToNumber(h);
}
async function createChallenge(x, p, message) {
const rx = pad32b(x);
const t = await taggedHash('BIP0340/challenge', rx, rawX(p), message);
return mod(t, CURVE.n);
}
function hasEvenY(point) {
return mod(point.y, 2n) === 0n;
}
class SchnorrSignResult {
constructor(r, s) {
this.r = r;
this.s = s;
}
toHex() {
return pad64(this.r) + pad64(this.s);
}
toRawBytes() {
return hexToBytes(this.toHex());
}
}
exports.schnorr = {
SignResult: SchnorrSignResult,
async sign(message, privateKey, auxRand = exports.utils.randomPrivateKey()) {
if (message == null)
throw new TypeError(`Expected valid message, not "${message}"`);
if (privateKey == null)
throw new TypeError('Expected valid private key');
const msg = typeof message === 'string' ? hexToBytes(message) : message;
const rand = typeof auxRand === 'string' ? hexToBytes(auxRand) : auxRand;
const order = CURVE.n;
const d0 = normalizePrivateKey(privateKey);
const p = Point.fromPrivateKey(d0);
const d = hasEvenY(p) ? d0 : order - d0;
const t0h = await taggedHash('BIP0340/aux', rand);
const t = d ^ t0h;
const k0h = await taggedHash('BIP0340/nonce', pad32b(t), rawX(p), msg);
const k0 = mod(k0h, order);
if (k0 === 0n)
throw new Error('Creation of signature failed. k is zero');
const r = Point.fromPrivateKey(k0);
const k = hasEvenY(r) ? k0 : order - k0;
const e = await createChallenge(r.x, p, msg);
const sig = new SchnorrSignResult(r.x, mod(k + e * d, order));
return sig;
},
async verify(signature, message, publicKey) {
const { r, s } = signature;
const msg = typeof message === 'string' ? hexToBytes(message) : message;
const pub = normalizePublicKey(publicKey);
if (r === 0n || s === 0n || r >= CURVE.P || s >= CURVE.n)
return false;
const e = await createChallenge(r, pub, msg);
const vr = Point.fromPrivateKey(s).add(pub.multiply(CURVE.n - e));
if (vr.equals(Point.BASE) || !hasEvenY(vr) || vr.x !== r)
return false;
return true;
},
};
Point.BASE._setWindowSize(8);

@@ -673,5 +743,18 @@ exports.utils = {

},
sha256: async (message) => {
if (typeof window == 'object' && 'crypto' in window) {
const buffer = await window.crypto.subtle.digest('SHA-256', message.buffer);
return new Uint8Array(buffer);
}
else if (typeof process === 'object' && 'node' in process.versions) {
const { createHash } = require('crypto');
return Uint8Array.from(createHash('sha256').update(message).digest());
}
else {
throw new Error("The environment doesn't have sha256 function");
}
},
hmacSha256: async (key, ...messages) => {
if (typeof window == 'object' && 'crypto' in window) {
const ckey = await window.crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign', 'verify']);
const ckey = await window.crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);
const message = concatBytes(...messages);

@@ -678,0 +761,0 @@ const buffer = await window.crypto.subtle.sign('HMAC', ckey, message);

7

package.json
{
"name": "noble-secp256k1",
"version": "1.0.6",
"description": "Noble secp256k1. Very fast, high-security, auditable, 0-dep, 1-file pubkey & ECDSA.",
"version": "1.1.0",
"description": "Noble secp256k1. Very fast, high-security, auditable, 0-dep, 1-file ECDSA & Schnorr.",
"main": "index.js",

@@ -50,2 +50,5 @@ "files": [

"rfc6979",
"schnorr",
"bip0340",
"bip340",
"ecdsa",

@@ -52,0 +55,0 @@ "endomorphism",

# noble-secp256k1 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
[secp256k1](https://www.secg.org/sec2-v2.pdf), an elliptic curve that could be used for asymmetric encryption, ECDH key agreement protocol and deterministic ECDSA signature scheme from RFC6979.
[Very fast](#speed) JS implementattion of [secp256k1](https://www.secg.org/sec2-v2.pdf),
an elliptic curve that could be used for asymmetric encryption,
ECDH key agreement protocol and deterministic ECDSA signature scheme from RFC6979. Supports **Schnorr** signatures as per BIP0340.
Algorithmically resistant to timing attacks. [Faster](#speed) than indutny/elliptic, ecdsa.js and sjcl. Tested against thousands of vectors from tiny-secp256k1.
Algorithmically resistant to timing attacks. Tested against thousands of vectors from tiny-secp256k1.

@@ -37,2 +39,6 @@ Check out a blog post about this library: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).

const isSigned = secp.verify(signature, messageHash, publicKey);
// Supports Schnorr signatures.
const signature2 = await secp.schnorr.sign(messageHash, privateKey);
const isSigned2 = await secp.schnorr.verify(signature2, messageHash, privateKey);
})();

@@ -55,2 +61,4 @@ ```

- [`recoverPublicKey(hash, signature, recovery)`](#recoverpublickeyhash-signature-recovery)
- [`schnorr.sign(hash, privateKey)`](#schnorrsignhash-privatekey)
- [`schnorr.verify(signature, hash, publicKey)`](#schnorrverifysignature-hash-publickey)
- [Helpers](#helpers)

@@ -126,2 +134,23 @@

##### `schnorr.sign(hash, privateKey)`
```typescript
function schnorrSign(msgHash: Uint8Array, privateKey: Uint8Array, auxilaryRandom?: Uint8Array): Promise<schnorr.SignResult>;
```
Generates Schnorr signature as per BIP0340. Asynchronous, so use `await`.
- `msgHash: Uint8Array | string` - message hash which would be signed
- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash
- `auxilaryRandom?: Uint8Array` — optional 32 random bytes. By default, the method gathers cryptogarphically secure random.
- Returns Schnorr signature.
##### `schnorr.verify(signature, hash, publicKey)`
```typescript
function schnorrVerify(signature: Uint8Array, msgHash: Uint8Array, publicKey: Uint8Array): boolean
```
- `signature: Uint8Array | string | { r: bigint, s: bigint }` - object returned by the `sign` function
- `msgHash: Uint8Array | string` - message hash that needs to be verified
- `publicKey: Uint8Array | string | Point` - e.g. that was generated from `privateKey` by `getPublicKey`
- Returns `boolean`: `true` if `signature == hash`; otherwise `false`
#### Point methods

@@ -199,10 +228,12 @@

Benchmarks measured with 2.9Ghz Coffee Lake.
Benchmarks measured with 2.9Ghz i9-8950HK.
getPublicKey(utils.randomPrivateKey()) x 4017 ops/sec @ 248μs/op
sign x 2620 ops/sec @ 381μs/op
getPublicKey(utils.randomPrivateKey()) x 4,017 ops/sec @ 248μs/op
sign x 2,620 ops/sec @ 381μs/op
verify x 558 ops/sec @ 1ms/op
recoverPublicKey x 301 ops/sec @ 3ms/op
getSharedSecret aka ecdh x 435 ops/sec @ 2ms/op
getSharedSecret (precomputed) x 4079 ops/sec @ 245μs/op
getSharedSecret (precomputed) x 4,079 ops/sec @ 245μs/op
schnorr.sign x 1,643 ops/sec @ 608μs/op
schnorr.verify x 316 ops/sec @ 3ms/op

@@ -209,0 +240,0 @@ Compare to other libraries:

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc