Compare commits

...

25 Commits

Author SHA1 Message Date
a8ea9d757f Build noble-curves for ES2015 for Tornado purposes 2024-04-18 14:08:07 -07:00
Paul Miller
efeca9f478
Add hex tests 2024-03-27 12:12:01 +01:00
Paul Miller
8ad2f9a185
Merge pull request #133 from carleeto/main
Fix montgomery sample code in README.md
2024-03-25 08:28:17 +01:00
Carl Menezes
be576b4c17
Fix montgomery sample code in README.md
Resolves https://github.com/paulmillr/noble-curves/issues/132
2024-03-25 11:17:28 +13:00
Paul Miller
819514576c
Use jsbt for tsconfig and building 2024-03-17 14:19:18 +01:00
Paul Miller
a0e398489f
Release 1.4.0. 2024-03-14 07:29:55 +01:00
Paul Miller
85d194cb93
Bump hashes. Commit build lockfile 2024-03-14 07:27:17 +01:00
Paul Miller
1830124ca1
Merge pull request #129 from xrchz/patch-1
Update README.md with Ethereum example
2024-03-08 00:21:59 +01:00
Ramana Kumar
72cc640bb1
Update README.md with Ethereum example
Shows how to use the DST to sign/verify messages with the configuration suitable for Ethereum beacon chain.
2024-03-07 21:15:01 +00:00
Paul Miller
32bda7926d
Fix bls short sig verification on hex. Closes gh-124 2024-03-01 22:22:49 +01:00
Paul Miller
38a4ca1e6b
readme: new noble library 2024-02-28 05:07:38 +01:00
Paul Miller
07f7e53e31
Update build deps 2024-02-28 04:26:25 +01:00
Paul Miller
537db4a968
hash-to-curve: adjust dst logic a bit 2024-02-27 23:34:30 +01:00
Paul Miller
a70501cec4
ci: add upload-release action 2024-02-27 23:34:03 +01:00
Paul Miller
89aaf264c1
readme 2024-02-27 23:25:10 +01:00
Paul Miller
e93caf9567
weierstrass: improve Entropy type. Use new utility. 2024-02-27 23:25:10 +01:00
Paul Miller
0ce103bd6b
utils, hash-to-curve: reduce code duplication 2024-02-27 23:25:10 +01:00
Paul Miller
6a85252dc3
Merge pull request #117 from dhrubabasu/add-htfopts
bls: Add `htfOpts` parameter to `sign` functions
2024-02-17 17:50:59 +01:00
dhrubabasu
a8503d6819
bls: Add htfOpts parameter to sign functions 2024-02-16 18:03:27 -05:00
Paul Miller
8397b26b45
Update github workflows 2024-02-14 02:10:37 +01:00
Paul Miller
8c39a6ac5a
tsconfig: change module to Node16, copy noble-ciphers change 2024-02-14 02:10:32 +01:00
Paul Miller
a1a7dc9cbf
readme: Add link to gh discussions 2024-02-05 17:45:16 +01:00
Paul Miller
ba58a282bd
readme 2024-01-21 14:45:32 +04:00
Paul Miller
c4c479047e
Merge pull request #110 from ardislu/fix-broken-links
README: fix broken links
2024-01-20 13:47:48 +04:00
Ardis Lu
2bf2e312a0
README: fix broken links 2024-01-19 23:39:52 -08:00
21 changed files with 640 additions and 122 deletions

1
.github/funding.yml vendored

@ -1,2 +1 @@
github: paulmillr github: paulmillr
# custom: https://paulmillr.com/funding/

@ -1,17 +1,20 @@
name: Node CI name: Run node.js tests
on:
on: [push, pull_request] - push
- pull_request
jobs: jobs:
test: test:
name: v${{ matrix.node }} @ ubuntu-latest name: v${{ matrix.node }} @ ubuntu-latest
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node: [18, 20] node:
- 18
- 20
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@v3 uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
- run: npm install - run: npm install

@ -1,4 +1,4 @@
name: Publish Package to npm name: Publish package to npm
on: on:
release: release:
types: [created] types: [created]
@ -9,8 +9,8 @@ jobs:
contents: read contents: read
id-token: write id-token: write
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with: with:
node-version: 20 node-version: 20
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'

28
.github/workflows/upload-release.yml vendored Normal file

@ -0,0 +1,28 @@
name: Upload standalone file to GitHub Releases
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
cache: npm
- run: npm install -g npm
- run: npm ci
- run: npm run build
- run: |
cd build
npm ci
npm run build:release
cd ..
- run: gh release upload ${{ github.event.release.tag_name }} build/`npx jsbt outfile`
env:
GH_TOKEN: ${{ github.token }}

@ -7,14 +7,18 @@ Audited & minimal JS implementation of elliptic curve cryptography.
- 🏎 Ultra-fast, hand-optimized for caveats of JS engines - 🏎 Ultra-fast, hand-optimized for caveats of JS engines
- 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing - 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing
- ➰ Short Weierstrass, Edwards, Montgomery curves - ➰ Short Weierstrass, Edwards, Montgomery curves
- ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement - ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement, hashing to curves
- 🔖 SUF-CMA, SBS (non-repudiation), ZIP215 (consensus friendliness) features for ed25519 - 🔖 SUF-CMA, SBS (non-repudiation), ZIP215 (consensus friendliness) features for ed25519
- #⃣ hash-to-curve for encoding or hashing an arbitrary string to an elliptic curve point
- 🧜‍♂️ Poseidon ZK-friendly hash - 🧜‍♂️ Poseidon ZK-friendly hash
- 🪶 178KB for everything, 25KB for single-curve build
### This library belongs to _noble_ crypto For discussions, questions and support, visit
[GitHub Discussions](https://github.com/paulmillr/noble-curves/discussions)
section of the repository.
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools. ### This library belongs to _noble_ cryptography
> **noble cryptography** — high-security, easily auditable set of contained cryptographic libraries and tools.
- Zero or minimal dependencies - Zero or minimal dependencies
- Highly readable TypeScript / JS code - Highly readable TypeScript / JS code
@ -22,7 +26,10 @@ Audited & minimal JS implementation of elliptic curve cryptography.
- All libraries: - All libraries:
[ciphers](https://github.com/paulmillr/noble-ciphers), [ciphers](https://github.com/paulmillr/noble-ciphers),
[curves](https://github.com/paulmillr/noble-curves), [curves](https://github.com/paulmillr/noble-curves),
[hashes](https://github.com/paulmillr/noble-hashes) [hashes](https://github.com/paulmillr/noble-hashes),
[post-quantum](https://github.com/paulmillr/noble-post-quantum),
4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) /
[ed25519](https://github.com/paulmillr/noble-ed25519)
- [Check out homepage](https://paulmillr.com/noble/) - [Check out homepage](https://paulmillr.com/noble/)
for reading resources, documentation and apps built with noble for reading resources, documentation and apps built with noble
@ -38,7 +45,7 @@ A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/re
```js ```js
// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno // import { secp256k1 } from 'npm:@noble/curves@1.4.0/secp256k1'; // Deno
``` ```
- [Implementations](#implementations) - [Implementations](#implementations)
@ -239,7 +246,7 @@ Same RFC7748 / RFC8032 / IRTF draft are followed.
#### bls12-381 #### bls12-381
See [abstract/bls](#abstractbls-barreto-lynn-scott-curves). See [abstract/bls](#bls-barreto-lynn-scott-curves).
#### All available imports #### All available imports
@ -548,7 +555,7 @@ import { Field } from '@noble/curves/abstract/modular';
const x25519 = montgomery({ const x25519 = montgomery({
a: 486662n, a: 486662n,
Gu: 9n, Gu: 9n,
Fp: Field(2n ** 255n - 19n), P: 2n ** 255n - 19n,
montgomeryBits: 255, montgomeryBits: 255,
nByteLength: 32, nByteLength: 32,
// Optional param // Optional param
@ -606,6 +613,12 @@ const signature = bls.sign(message, privateKey);
const isValid = bls.verify(signature, message, publicKey); const isValid = bls.verify(signature, message, publicKey);
console.log({ publicKey, signature, isValid }); console.log({ publicKey, signature, isValid });
// Use custom DST, e.g. for Ethereum consensus layer
const htfEthereum = {DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'};
const signatureEth = bls.sign(message, privateKey, htfEthereum);
const isValidEth = bls.verify(signature, message, publicKey, htfEthereum);
console.log({ signatureEth, isValidEth });
// Sign 1 msg with 3 keys // Sign 1 msg with 3 keys
const privateKeys = [ const privateKeys = [
'18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4', '18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4',
@ -758,7 +771,7 @@ and [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).
This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level. This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level.
`hashToPrivateScalar()` that hashes to **private key** was created for this purpose. `hashToPrivateScalar()` that hashes to **private key** was created for this purpose.
Use [abstract/hash-to-curve](#abstracthash-to-curve-hashing-strings-to-curve-points) Use [abstract/hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points)
if you need to hash to **public key**. if you need to hash to **public key**.
```ts ```ts

@ -1,7 +1,7 @@
# build # build
The directory is used to build a single file `noble-curves.js` which contains everything. The directory is used to build a single file which contains everything.
The output file uses iife wrapper and can be used in browsers as-is. The single file uses iife wrapper and can be used in browsers as-is.
Don't use it unless you can't use NPM/ESM, which support tree shaking. Don't use it unless you can't use NPM/ESM, which support tree shaking.

@ -1,4 +1,4 @@
import { bytesToHex, concatBytes, hexToBytes } from '@noble/curves/abstract/utils'; import { bytesToHex, concatBytes, hexToBytes, utf8ToBytes } from '@noble/curves/abstract/utils';
export { secp256k1, schnorr as secp256k1_schnorr } from '@noble/curves/secp256k1'; export { secp256k1, schnorr as secp256k1_schnorr } from '@noble/curves/secp256k1';
export { export {
@ -17,4 +17,4 @@ export { p384 } from '@noble/curves/p384';
export { p521 } from '@noble/curves/p521'; export { p521 } from '@noble/curves/p521';
export { bls12_381 } from '@noble/curves/bls12-381'; export { bls12_381 } from '@noble/curves/bls12-381';
export const utils = { bytesToHex, concatBytes, hexToBytes }; export const utils = { bytesToHex, concatBytes, hexToBytes, utf8ToBytes };

445
build/package-lock.json generated Normal file

@ -0,0 +1,445 @@
{
"name": "build",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "build",
"version": "1.0.0",
"devDependencies": {
"@noble/curves": "file:..",
"esbuild": "0.20.1"
}
},
"..": {
"version": "1.4.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.4.0"
},
"devDependencies": {
"@paulmillr/jsbt": "0.1.0",
"fast-check": "3.0.0",
"micro-bmark": "0.3.1",
"micro-should": "0.4.0",
"prettier": "3.1.1",
"typescript": "5.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz",
"integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz",
"integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz",
"integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz",
"integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz",
"integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz",
"integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz",
"integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz",
"integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz",
"integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz",
"integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz",
"integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz",
"integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz",
"integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==",
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz",
"integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz",
"integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==",
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz",
"integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz",
"integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz",
"integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz",
"integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz",
"integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz",
"integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz",
"integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz",
"integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@noble/curves": {
"resolved": "..",
"link": true
},
"node_modules/esbuild": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
"integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.20.1",
"@esbuild/android-arm": "0.20.1",
"@esbuild/android-arm64": "0.20.1",
"@esbuild/android-x64": "0.20.1",
"@esbuild/darwin-arm64": "0.20.1",
"@esbuild/darwin-x64": "0.20.1",
"@esbuild/freebsd-arm64": "0.20.1",
"@esbuild/freebsd-x64": "0.20.1",
"@esbuild/linux-arm": "0.20.1",
"@esbuild/linux-arm64": "0.20.1",
"@esbuild/linux-ia32": "0.20.1",
"@esbuild/linux-loong64": "0.20.1",
"@esbuild/linux-mips64el": "0.20.1",
"@esbuild/linux-ppc64": "0.20.1",
"@esbuild/linux-riscv64": "0.20.1",
"@esbuild/linux-s390x": "0.20.1",
"@esbuild/linux-x64": "0.20.1",
"@esbuild/netbsd-x64": "0.20.1",
"@esbuild/openbsd-x64": "0.20.1",
"@esbuild/sunos-x64": "0.20.1",
"@esbuild/win32-arm64": "0.20.1",
"@esbuild/win32-ia32": "0.20.1",
"@esbuild/win32-x64": "0.20.1"
}
}
}
}

@ -2,17 +2,13 @@
"name": "build", "name": "build",
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"description": "Used to build a single file",
"main": "input.js", "main": "input.js",
"keywords": [],
"type": "module", "type": "module",
"author": "",
"license": "MIT",
"devDependencies": { "devDependencies": {
"@noble/curves": "..", "@noble/curves": "file:..",
"esbuild": "0.18.11" "esbuild": "0.20.1"
}, },
"scripts": { "scripts": {
"build": "npx esbuild --bundle input.js --outfile=noble-curves.js --global-name=nobleCurves" "build:release": "npx esbuild --bundle input.js --outfile=`npx jsbt outfile` --global-name=`npx jsbt global`"
} }
} }

26
package-lock.json generated

@ -1,17 +1,18 @@
{ {
"name": "@noble/curves", "name": "@tornado/noble-curves",
"version": "1.3.0", "version": "1.4.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@noble/curves", "name": "@tornado/noble-curves",
"version": "1.3.0", "version": "1.4.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@noble/hashes": "1.3.3" "@noble/hashes": "1.4.0"
}, },
"devDependencies": { "devDependencies": {
"@paulmillr/jsbt": "0.1.0",
"fast-check": "3.0.0", "fast-check": "3.0.0",
"micro-bmark": "0.3.1", "micro-bmark": "0.3.1",
"micro-should": "0.4.0", "micro-should": "0.4.0",
@ -23,9 +24,9 @@
} }
}, },
"node_modules/@noble/hashes": { "node_modules/@noble/hashes": {
"version": "1.3.3", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
"engines": { "engines": {
"node": ">= 16" "node": ">= 16"
}, },
@ -33,6 +34,15 @@
"url": "https://paulmillr.com/funding/" "url": "https://paulmillr.com/funding/"
} }
}, },
"node_modules/@paulmillr/jsbt": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@paulmillr/jsbt/-/jsbt-0.1.0.tgz",
"integrity": "sha512-TdowoHD36hkZARv6LW4jenkVTdK2vP0sy4ZM8E9MxaqAAIRdwmn3RlB+zWkEHi4hKTgLqMGkURfNkFtt0STX2Q==",
"dev": true,
"bin": {
"jsbt": "jsbt.js"
}
},
"node_modules/fast-check": { "node_modules/fast-check": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.0.0.tgz", "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.0.0.tgz",

@ -1,6 +1,6 @@
{ {
"name": "@noble/curves", "name": "@tornado/noble-curves",
"version": "1.3.0", "version": "1.4.0",
"description": "Audited & minimal JS implementation of elliptic curve cryptography", "description": "Audited & minimal JS implementation of elliptic curve cryptography",
"files": [ "files": [
"abstract", "abstract",
@ -14,7 +14,7 @@
"scripts": { "scripts": {
"bench": "cd benchmark; node secp256k1.js; node curves.js; node ecdh.js; node hash-to-curve.js; node modular.js; node bls.js; node ristretto255.js; node decaf448.js", "bench": "cd benchmark; node secp256k1.js; node curves.js; node ecdh.js; node hash-to-curve.js; node modular.js; node bls.js; node ristretto255.js; node decaf448.js",
"build": "tsc && tsc -p tsconfig.esm.json", "build": "tsc && tsc -p tsconfig.esm.json",
"build:release": "cd build; npm install && npm run build", "build:release": "cd build && npm i && npm run build",
"build:clean": "rm *.{js,d.ts,d.ts.map,js.map} esm/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null", "build:clean": "rm *.{js,d.ts,d.ts.map,js.map} esm/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null",
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'", "lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'",
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'", "format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'",
@ -24,13 +24,14 @@
"homepage": "https://paulmillr.com/noble/", "homepage": "https://paulmillr.com/noble/",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/paulmillr/noble-curves.git" "url": "https://git.tornado.ws/tornado-packages/noble-curvest"
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@noble/hashes": "1.3.3" "@noble/hashes": "1.4.0"
}, },
"devDependencies": { "devDependencies": {
"@paulmillr/jsbt": "0.1.0",
"fast-check": "3.0.0", "fast-check": "3.0.0",
"micro-bmark": "0.3.1", "micro-bmark": "0.3.1",
"micro-should": "0.4.0", "micro-should": "0.4.0",

@ -83,12 +83,12 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
getPublicKey: (privateKey: PrivKey) => Uint8Array; getPublicKey: (privateKey: PrivKey) => Uint8Array;
getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array; getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array;
sign: { sign: {
(message: Hex, privateKey: PrivKey): Uint8Array; (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
(message: ProjPointType<Fp2>, privateKey: PrivKey): ProjPointType<Fp2>; (message: ProjPointType<Fp2>, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType<Fp2>;
}; };
signShortSignature: { signShortSignature: {
(message: Hex, privateKey: PrivKey): Uint8Array; (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
(message: ProjPointType<Fp>, privateKey: PrivKey): ProjPointType<Fp>; (message: ProjPointType<Fp>, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType<Fp>;
}; };
verify: ( verify: (
signature: Hex | ProjPointType<Fp2>, signature: Hex | ProjPointType<Fp2>,

@ -2,7 +2,7 @@
import type { Group, GroupConstructor, AffinePoint } from './curve.js'; import type { Group, GroupConstructor, AffinePoint } from './curve.js';
import { mod, IField } from './modular.js'; import { mod, IField } from './modular.js';
import type { CHash } from './utils.js'; import type { CHash } from './utils.js';
import { bytesToNumberBE, isBytes, concatBytes, utf8ToBytes, validateObject } from './utils.js'; import { bytesToNumberBE, abytes, concatBytes, utf8ToBytes, validateObject } from './utils.js';
/** /**
* * `DST` is a domain separation tag, defined in section 2.2.5 * * `DST` is a domain separation tag, defined in section 2.2.5
@ -22,12 +22,6 @@ export type Opts = {
hash: CHash; hash: CHash;
}; };
function validateDST(dst: UnicodeOrBytes): Uint8Array {
if (isBytes(dst)) return dst;
if (typeof dst === 'string') return utf8ToBytes(dst);
throw new Error('DST must be Uint8Array or string');
}
// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. // Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
const os2ip = bytesToNumberBE; const os2ip = bytesToNumberBE;
@ -52,10 +46,7 @@ function strxor(a: Uint8Array, b: Uint8Array): Uint8Array {
return arr; return arr;
} }
function abytes(item: unknown): void { function anum(item: unknown): void {
if (!isBytes(item)) throw new Error('Uint8Array expected');
}
function isNum(item: unknown): void {
if (!Number.isSafeInteger(item)) throw new Error('number expected'); if (!Number.isSafeInteger(item)) throw new Error('number expected');
} }
@ -69,7 +60,7 @@ export function expand_message_xmd(
): Uint8Array { ): Uint8Array {
abytes(msg); abytes(msg);
abytes(DST); abytes(DST);
isNum(lenInBytes); anum(lenInBytes);
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)); if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H; const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
@ -103,7 +94,7 @@ export function expand_message_xof(
): Uint8Array { ): Uint8Array {
abytes(msg); abytes(msg);
abytes(DST); abytes(DST);
isNum(lenInBytes); anum(lenInBytes);
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
if (DST.length > 255) { if (DST.length > 255) {
@ -141,8 +132,8 @@ export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bi
}); });
const { p, k, m, hash, expand, DST: _DST } = options; const { p, k, m, hash, expand, DST: _DST } = options;
abytes(msg); abytes(msg);
isNum(count); anum(count);
const DST = validateDST(_DST); const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST;
const log2p = p.toString(2).length; const log2p = p.toString(2).length;
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
const len_in_bytes = count * m * L; const len_in_bytes = count * m * L;

@ -23,6 +23,10 @@ export function isBytes(a: unknown): a is Uint8Array {
); );
} }
export function abytes(item: unknown): void {
if (!isBytes(item)) throw new Error('Uint8Array expected');
}
// Array where index 0xf0 (240) is mapped to string 'f0' // Array where index 0xf0 (240) is mapped to string 'f0'
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>
i.toString(16).padStart(2, '0') i.toString(16).padStart(2, '0')
@ -31,7 +35,7 @@ const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/ */
export function bytesToHex(bytes: Uint8Array): string { export function bytesToHex(bytes: Uint8Array): string {
if (!isBytes(bytes)) throw new Error('Uint8Array expected'); abytes(bytes);
// pre-caching improves the speed 6x // pre-caching improves the speed 6x
let hex = ''; let hex = '';
for (let i = 0; i < bytes.length; i++) { for (let i = 0; i < bytes.length; i++) {
@ -86,7 +90,7 @@ export function bytesToNumberBE(bytes: Uint8Array): bigint {
return hexToNumber(bytesToHex(bytes)); return hexToNumber(bytesToHex(bytes));
} }
export function bytesToNumberLE(bytes: Uint8Array): bigint { export function bytesToNumberLE(bytes: Uint8Array): bigint {
if (!isBytes(bytes)) throw new Error('Uint8Array expected'); abytes(bytes);
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())); return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
} }
@ -138,7 +142,7 @@ export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
let sum = 0; let sum = 0;
for (let i = 0; i < arrays.length; i++) { for (let i = 0; i < arrays.length; i++) {
const a = arrays[i]; const a = arrays[i];
if (!isBytes(a)) throw new Error('Uint8Array expected'); abytes(a);
sum += a.length; sum += a.length;
} }
const res = new Uint8Array(sum); const res = new Uint8Array(sum);
@ -194,9 +198,9 @@ export function bitGet(n: bigint, pos: number) {
/** /**
* Sets single bit at position. * Sets single bit at position.
*/ */
export const bitSet = (n: bigint, pos: number, value: boolean) => { export function bitSet(n: bigint, pos: number, value: boolean) {
return n | ((value ? _1n : _0n) << BigInt(pos)); return n | ((value ? _1n : _0n) << BigInt(pos));
}; }
/** /**
* Calculate mask for N bits. Not using ** operator with bigints because of old engines. * Calculate mask for N bits. Not using ** operator with bigints because of old engines.

@ -27,7 +27,7 @@ export type BasicWCurve<T> = BasicCurve<T> & {
clearCofactor?: (c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>; clearCofactor?: (c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>;
}; };
type Entropy = Hex | true; type Entropy = Hex | boolean;
export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean }; export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean };
export type VerOpts = { lowS?: boolean; prehash?: boolean }; export type VerOpts = { lowS?: boolean; prehash?: boolean };
@ -158,7 +158,7 @@ export const DER = {
// parse DER signature // parse DER signature
const { Err: E } = DER; const { Err: E } = DER;
const data = typeof hex === 'string' ? h2b(hex) : hex; const data = typeof hex === 'string' ? h2b(hex) : hex;
if (!ut.isBytes(data)) throw new Error('ui8a expected'); ut.abytes(data);
let l = data.length; let l = data.length;
if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag');
if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length');
@ -977,7 +977,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
const seedArgs = [int2octets(d), int2octets(h1int)]; const seedArgs = [int2octets(d), int2octets(h1int)];
// extraEntropy. RFC6979 3.6: additional k' (optional). // extraEntropy. RFC6979 3.6: additional k' (optional).
if (ent != null) { if (ent != null && ent !== false) {
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes

@ -1364,7 +1364,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
fromHex(hex: Hex): ProjPointType<Fp2> { fromHex(hex: Hex): ProjPointType<Fp2> {
const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)); const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex));
const P = Fp.ORDER; const P = Fp.ORDER;
const half = hex.length / 2; const half = value.length / 2;
if (half !== 48 && half !== 96) if (half !== 48 && half !== 96)
throw new Error('Invalid compressed signature length, must be 96 or 192'); throw new Error('Invalid compressed signature length, must be 96 or 192');
const z1 = bytesToNumberBE(value.slice(0, half)); const z1 = bytesToNumberBE(value.slice(0, half));

3
src/package.json Normal file

@ -0,0 +1,3 @@
{
"type": "module"
}

@ -2,7 +2,7 @@ import { deepStrictEqual, throws } from 'assert';
import { should, describe } from 'micro-should'; import { should, describe } from 'micro-should';
import * as fc from 'fast-check'; import * as fc from 'fast-check';
import * as mod from '../esm/abstract/modular.js'; import * as mod from '../esm/abstract/modular.js';
import { bytesToHex as toHex } from '../esm/abstract/utils.js'; import { bytesToHex, isBytes, bytesToHex as toHex } from '../esm/abstract/utils.js';
// Generic tests for all curves in package // Generic tests for all curves in package
import { secp192r1, secp224r1 } from './_more-curves.helpers.js'; import { secp192r1, secp224r1 } from './_more-curves.helpers.js';
import { secp256r1 } from '../esm/p256.js'; import { secp256r1 } from '../esm/p256.js';
@ -595,6 +595,18 @@ for (const name in CURVES) {
{ numRuns: NUM_RUNS } { numRuns: NUM_RUNS }
) )
); );
should('.verify() should verify random signatures in hex', () =>
fc.assert(
fc.property(fc.hexaString({ minLength: 64, maxLength: 64 }), (msg) => {
const priv = toHex(C.utils.randomPrivateKey());
const pub = toHex(C.getPublicKey(priv));
const sig = C.sign(msg, priv);
let sighex = isBytes(sig) ? toHex(sig) : sig.toCompactHex();
deepStrictEqual(C.verify(sighex, msg, pub), true, `priv=${priv},pub=${pub},msg=${msg}`);
}),
{ numRuns: NUM_RUNS }
)
);
should('.verify() should verify empty signatures', () => { should('.verify() should verify empty signatures', () => {
const msg = new Uint8Array([]); const msg = new Uint8Array([]);
const priv = C.utils.randomPrivateKey(); const priv = C.utils.randomPrivateKey();

@ -1173,6 +1173,8 @@ describe('verify()', () => {
const pub = bls.getPublicKey(priv); const pub = bls.getPublicKey(priv);
const res = bls.verify(sig, msg, pub); const res = bls.verify(sig, msg, pub);
deepStrictEqual(res, true, `${priv}-${msg}`); deepStrictEqual(res, true, `${priv}-${msg}`);
const resHex = bls.verify(bytesToHex(sig), msg, pub);
deepStrictEqual(resHex, true, `${priv}-${msg}-hex`);
} }
}); });
should('not verify signature with wrong message', () => { should('not verify signature with wrong message', () => {
@ -1193,6 +1195,8 @@ describe('verify()', () => {
const invPub = bls.getPublicKey(invPriv); const invPub = bls.getPublicKey(invPriv);
const res = bls.verify(sig, msg, invPub); const res = bls.verify(sig, msg, invPub);
deepStrictEqual(res, false); deepStrictEqual(res, false);
const resHex = bls.verify(bytesToHex(sig), msg, invPub);
deepStrictEqual(resHex, false);
} }
}); });
should('verify signed message (short signatures)', () => { should('verify signed message (short signatures)', () => {
@ -1202,6 +1206,8 @@ describe('verify()', () => {
const pub = bls.getPublicKeyForShortSignatures(priv); const pub = bls.getPublicKeyForShortSignatures(priv);
const res = bls.verifyShortSignature(sig, msg, pub); const res = bls.verifyShortSignature(sig, msg, pub);
deepStrictEqual(res, true, `${priv}-${msg}`); deepStrictEqual(res, true, `${priv}-${msg}`);
const resHex = bls.verifyShortSignature(bytesToHex(sig), msg, pub);
deepStrictEqual(resHex, true, `${priv}-${msg}`);
} }
}); });
should('not verify signature with wrong message (short signatures)', () => { should('not verify signature with wrong message (short signatures)', () => {
@ -1212,6 +1218,8 @@ describe('verify()', () => {
const pub = bls.getPublicKeyForShortSignatures(priv); const pub = bls.getPublicKeyForShortSignatures(priv);
const res = bls.verifyShortSignature(sig, invMsg, pub); const res = bls.verifyShortSignature(sig, invMsg, pub);
deepStrictEqual(res, false); deepStrictEqual(res, false);
const resHex = bls.verifyShortSignature(bytesToHex(sig), invMsg, pub);
deepStrictEqual(resHex, false);
} }
}); });
should('not verify signature with wrong key', () => { should('not verify signature with wrong key', () => {
@ -1222,6 +1230,8 @@ describe('verify()', () => {
const invPub = bls.getPublicKeyForShortSignatures(invPriv); const invPub = bls.getPublicKeyForShortSignatures(invPriv);
const res = bls.verifyShortSignature(sig, msg, invPub); const res = bls.verifyShortSignature(sig, msg, invPub);
deepStrictEqual(res, false); deepStrictEqual(res, false);
const resHex = bls.verifyShortSignature(bytesToHex(sig), msg, invPub);
deepStrictEqual(resHex, false);
} }
}); });
describe('batch', () => { describe('batch', () => {
@ -1234,6 +1244,10 @@ describe('verify()', () => {
const signatures = messages.map((message, i) => bls.sign(message, privateKeys[i])); const signatures = messages.map((message, i) => bls.sign(message, privateKeys[i]));
const aggregatedSignature = bls.aggregateSignatures(signatures); const aggregatedSignature = bls.aggregateSignatures(signatures);
deepStrictEqual(bls.verifyBatch(aggregatedSignature, messages, publicKey), true); deepStrictEqual(bls.verifyBatch(aggregatedSignature, messages, publicKey), true);
deepStrictEqual(
bls.verifyBatch(bytesToHex(aggregatedSignature), messages, publicKey),
true
);
}) })
); );
}); });
@ -1252,6 +1266,10 @@ describe('verify()', () => {
bls.verifyBatch(aggregatedSignature, wrongMessages, publicKey), bls.verifyBatch(aggregatedSignature, wrongMessages, publicKey),
messages.every((m, i) => m === wrongMessages[i]) messages.every((m, i) => m === wrongMessages[i])
); );
deepStrictEqual(
bls.verifyBatch(bytesToHex(aggregatedSignature), wrongMessages, publicKey),
messages.every((m, i) => m === wrongMessages[i])
);
}) })
); );
}); });
@ -1274,6 +1292,10 @@ describe('verify()', () => {
bls.verifyBatch(aggregatedSignature, messages, wrongPublicKeys), bls.verifyBatch(aggregatedSignature, messages, wrongPublicKeys),
wrongPrivateKeys.every((p, i) => p === privateKeys[i]) wrongPrivateKeys.every((p, i) => p === privateKeys[i])
); );
deepStrictEqual(
bls.verifyBatch(bytesToHex(aggregatedSignature), messages, wrongPublicKeys),
wrongPrivateKeys.every((p, i) => p === privateKeys[i])
);
} }
) )
); );
@ -1287,6 +1309,10 @@ describe('verify()', () => {
const aggregatedSignature = bls.aggregateSignatures(signatures); const aggregatedSignature = bls.aggregateSignatures(signatures);
const aggregatedPublicKey = bls.aggregatePublicKeys(publicKey); const aggregatedPublicKey = bls.aggregatePublicKeys(publicKey);
deepStrictEqual(bls.verify(aggregatedSignature, message, aggregatedPublicKey), true); deepStrictEqual(bls.verify(aggregatedSignature, message, aggregatedPublicKey), true);
deepStrictEqual(
bls.verify(bytesToHex(aggregatedSignature), message, aggregatedPublicKey),
true
);
}) })
); );
}); });
@ -1302,6 +1328,10 @@ describe('verify()', () => {
bls.verify(aggregatedSignature, wrongMessage, aggregatedPublicKey), bls.verify(aggregatedSignature, wrongMessage, aggregatedPublicKey),
message === wrongMessage message === wrongMessage
); );
deepStrictEqual(
bls.verify(bytesToHex(aggregatedSignature), wrongMessage, aggregatedPublicKey),
message === wrongMessage
);
}) })
); );
}); });

@ -1,25 +1,9 @@
{ {
"extends": "@paulmillr/jsbt/tsconfigs/esm.json",
"compilerOptions": { "compilerOptions": {
"target": "es2020",
"lib": ["es2020"],
"strict": true,
"sourceMap": true,
"allowSyntheticDefaultImports": false,
"allowUnreachableCode": false,
"esModuleInterop": false,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"baseUrl": ".",
"paths": {
"@noble/hashes/crypto": ["src/crypto"]
},
"module": "es2020",
"outDir": "esm", "outDir": "esm",
"moduleResolution": "bundler" "target": "ES2015"
}, },
"include": ["src"], "include": ["index.ts", "src"],
"exclude": ["node_modules", "lib"] "exclude": ["node_modules", "lib"]
} }

@ -1,10 +1,9 @@
{ {
"extends": "./tsconfig.esm.json", "extends": "@paulmillr/jsbt/tsconfigs/cjs.json",
"compilerOptions": { "compilerOptions": {
"module": "commonjs",
"moduleResolution": "node10",
"outDir": ".", "outDir": ".",
"declaration": true, "target": "ES2015"
"declarationMap": true },
} "include": ["index.ts", "src"],
"exclude": ["node_modules", "lib"]
} }