noble-secp256k1
Advanced tools
Comparing version 1.1.3 to 1.2.0
@@ -51,3 +51,3 @@ /*! noble-secp256k1 - MIT License (c) Paul Miller (paulmillr.com) */ | ||
export declare const SignResult: typeof Signature; | ||
export declare function getPublicKey(privateKey: Uint8Array | bigint | number, isCompressed?: boolean): Uint8Array; | ||
export declare function getPublicKey(privateKey: Uint8Array | number | bigint, isCompressed?: boolean): Uint8Array; | ||
export declare function getPublicKey(privateKey: string, isCompressed?: boolean): string; | ||
@@ -54,0 +54,0 @@ export declare function recoverPublicKey(msgHash: string, signature: string, recovery: number): string | undefined; |
89
index.js
@@ -16,3 +16,2 @@ 'use strict'; | ||
const PRIME_SIZE = 256; | ||
const P_DIV4_1 = (CURVE.P + 1n) / 4n; | ||
function weistrass(x) { | ||
@@ -150,3 +149,3 @@ const { a, b } = CURVE; | ||
precomputeWindow(W) { | ||
const windows = USE_ENDOMORPHISM ? 128 / W + 2 : 256 / W + 1; | ||
const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1; | ||
let points = []; | ||
@@ -183,3 +182,3 @@ let p = this; | ||
let f = JacobianPoint.ZERO; | ||
const windows = USE_ENDOMORPHISM ? 128 / W + 2 : 256 / W + 1; | ||
const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1; | ||
const windowSize = 2 ** (W - 1); | ||
@@ -257,3 +256,3 @@ const mask = BigInt(2 ** W - 1); | ||
const sqrY = weistrass(x); | ||
let y = powMod(sqrY, P_DIV4_1, CURVE.P); | ||
let y = sqrtMod(sqrY); | ||
if (isShort) { | ||
@@ -452,6 +451,7 @@ const isYOdd = (y & 1n) === 1n; | ||
function hexToBytes(hex) { | ||
hex = hex.length & 1 ? `0${hex}` : hex; | ||
if (hex.length & 1) | ||
throw new Error('Expected valid hex'); | ||
const array = new Uint8Array(hex.length / 2); | ||
for (let i = 0; i < array.length; i++) { | ||
let j = i * 2; | ||
const j = i * 2; | ||
array[i] = Number.parseInt(hex.slice(j, j + 2), 16); | ||
@@ -471,13 +471,28 @@ } | ||
} | ||
function powMod(x, power, order) { | ||
let res = 1n; | ||
while (power > 0) { | ||
if (power & 1n) { | ||
res = mod(res * x, order); | ||
} | ||
power >>= 1n; | ||
x = mod(x * x, order); | ||
function powMod2(t, power) { | ||
const { P } = CURVE; | ||
let res = t; | ||
while (power-- > 0n) { | ||
res *= res; | ||
res %= P; | ||
} | ||
return res; | ||
} | ||
function sqrtMod(a) { | ||
const { P } = CURVE; | ||
const x2 = (a * a * a) % P; | ||
const x3 = (x2 * x2 * a) % P; | ||
const x6 = (powMod2(x3, 3n) * x3) % P; | ||
const x9 = (powMod2(x6, 3n) * x3) % P; | ||
const x11 = (powMod2(x9, 2n) * x2) % P; | ||
const x22 = (powMod2(x11, 11n) * x11) % P; | ||
const x44 = (powMod2(x22, 22n) * x22) % P; | ||
const x88 = (powMod2(x44, 44n) * x44) % P; | ||
const x176 = (powMod2(x88, 88n) * x88) % P; | ||
const x220 = (powMod2(x176, 44n) * x44) % P; | ||
const x223 = (powMod2(x220, 3n) * x3) % P; | ||
const t1 = (powMod2(x223, 23n) * x22) % P; | ||
const t2 = (powMod2(t1, 6n) * x2) % P; | ||
return powMod2(t2, 2n); | ||
} | ||
function egcd(a, b) { | ||
@@ -526,2 +541,4 @@ let [x, y, u, v] = [0n, 1n, 1n, 0n]; | ||
} | ||
const divNearest = (a, b) => (a + b / 2n) / b; | ||
const POW_2_128 = 2n ** 128n; | ||
function splitScalarEndo(k) { | ||
@@ -533,9 +550,15 @@ const { n } = CURVE; | ||
const b2 = a1; | ||
const c1 = (b2 * k) / n; | ||
const c2 = (-b1 * k) / n; | ||
const k1 = k - c1 * a1 - c2 * a2; | ||
const k2 = -c1 * b1 - c2 * b2; | ||
const k1neg = k1 < 0; | ||
const k2neg = k2 < 0; | ||
return [k1neg, k1neg ? -k1 : k1, k2neg, k2neg ? -k2 : k2]; | ||
const c1 = divNearest(b2 * k, n); | ||
const c2 = divNearest(-b1 * k, n); | ||
let k1 = mod(k - c1 * a1 - c2 * a2, n); | ||
let k2 = mod(-c1 * b1 - c2 * b2, n); | ||
const k1neg = k1 > POW_2_128; | ||
const k2neg = k2 > POW_2_128; | ||
if (k1neg) | ||
k1 = n - k1; | ||
if (k2neg) | ||
k2 = n - k2; | ||
if (k1 > POW_2_128 || k2 > POW_2_128) | ||
throw new Error('Endomorphism failed'); | ||
return [k1neg, k1, k2neg, k2]; | ||
} | ||
@@ -592,14 +615,22 @@ function truncateHash(hash) { | ||
function normalizePrivateKey(privateKey) { | ||
if (!privateKey) | ||
throw new Error(`Expected receive valid private key, not "${privateKey}"`); | ||
let key; | ||
if (privateKey instanceof Uint8Array) { | ||
if (privateKey.length !== 32) | ||
throw new Error('Expected 32 bytes of private key'); | ||
key = bytesToNumber(privateKey); | ||
} | ||
else if (typeof privateKey === 'string') { | ||
if (privateKey.length !== 64) | ||
throw new Error('Expected 32 bytes of private key'); | ||
key = hexToNumber(privateKey); | ||
} | ||
else { | ||
else if (Number.isSafeInteger(privateKey) && privateKey > 0) { | ||
key = BigInt(privateKey); | ||
} | ||
else if (typeof privateKey === 'bigint' && privateKey > 0n && privateKey < CURVE.P) { | ||
key = privateKey; | ||
} | ||
else { | ||
throw new TypeError('Expected valid private key'); | ||
} | ||
return key; | ||
@@ -639,8 +670,6 @@ } | ||
function getSharedSecret(privateA, publicB, isCompressed = false) { | ||
if (isPub(privateA) && !isPub(publicB)) { | ||
[privateA, publicB] = [publicB, privateA]; | ||
} | ||
else if (!isPub(publicB)) { | ||
throw new Error('Received invalid keys'); | ||
} | ||
if (isPub(privateA)) | ||
throw new TypeError('getSharedSecret: first arg must be private key'); | ||
if (!isPub(publicB)) | ||
throw new TypeError('getSharedSecret: second arg must be public key'); | ||
const b = publicB instanceof Point ? publicB : Point.fromHex(publicB); | ||
@@ -647,0 +676,0 @@ b.assertValidity(); |
{ | ||
"name": "noble-secp256k1", | ||
"version": "1.1.3", | ||
"description": "Fastest JS implementation of secp256k1. Zero-dependency, high-security, auditable ECDSA & Schnorr", | ||
"version": "1.2.0", | ||
"description": "Fastest JS implementation of secp256k1. Zero-dependency, high-security, audited ECDSA & Schnorr", | ||
"main": "index.js", | ||
@@ -6,0 +6,0 @@ "files": [ |
@@ -5,10 +5,6 @@ # 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) | ||
an elliptic curve that could be used for asymmetric encryption, | ||
ECDH key agreement protocol and signature schemes. | ||
ECDH key agreement protocol and signature schemes. Supports deterministic **ECDSA** from RFC6979 and **Schnorr** signatures from BIP0340. | ||
Supports deterministic **ECDSA** from RFC6979 and **Schnorr** signatures from BIP0340. | ||
[**Audited**](#security) by an independent security firm. Tested against thousands of test vectors from a different library. Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/) | ||
Algorithmically resistant to timing attacks. Tested against thousands of vectors from tiny-secp256k1. | ||
Check out [the online demo](https://paulmillr.com/ecc) and blog post: [Learning fast elliptic-curve cryptography in JS](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/) | ||
### This library belongs to *noble* crypto | ||
@@ -229,3 +225,3 @@ | ||
Noble is production-ready. Our goal is to have it audited by a good security expert. | ||
Noble is production-ready. The library has been audited by an independent security firm cure53: [PDF](https://cure53.de/pentest-report_noble-lib.pdf). | ||
@@ -244,9 +240,10 @@ We're using built-in JS `BigInt`, which is "unsuitable for use in cryptography" as [per official spec](https://github.com/tc39/proposal-bigint#cryptography). This means that the lib is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack). But: | ||
getPublicKey(utils.randomPrivateKey()) x 5,596 ops/sec @ 178μs/op | ||
sign x 3,873 ops/sec @ 258μs/op | ||
verify x 832 ops/sec @ 1ms/op | ||
getPublicKey(utils.randomPrivateKey()) x 5,764 ops/sec @ 173μs/op | ||
sign x 3,952 ops/sec @ 253μs/op | ||
verify x 851 ops/sec @ 1ms/op | ||
recoverPublicKey x 438 ops/sec @ 2ms/op | ||
getSharedSecret aka ecdh x 488 ops/sec @ 2ms/op | ||
getSharedSecret (precomputed) x 6,204 ops/sec @ 161μs/op | ||
schnorr.sign x 359 ops/sec @ 2ms/op | ||
getSharedSecret (precomputed) x 6,243 ops/sec @ 160μs/op | ||
Point.fromHex (decompression) x 11,201 ops/sec @ 89μs/op | ||
schnorr.sign x 372 ops/sec @ 2ms/op | ||
schnorr.verify x 471 ops/sec @ 2ms/op | ||
@@ -253,0 +250,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
49910
942
282