170 Commits
0.6.3 ... 1.1.0

Author SHA1 Message Date
Paul Miller
62e806cfaf Release 1.1.0. 2023-06-03 14:31:43 +02:00
Paul Miller
6a72821185 readme 2023-06-03 14:27:05 +02:00
Paul Miller
8cee1f559f Bump noble-hashes to 1.3.1 2023-06-03 14:23:18 +02:00
Paul Miller
6f10632ac0 Add build directory that allows to test tree-shaking 2023-06-02 17:16:56 +02:00
Paul Miller
b281167e8d Fix utf8ToBytes in firefox extension context 2023-06-02 15:57:46 +02:00
Paul Miller
c6b4aadafb utils: harmonize with noble-hashes 2023-06-02 15:35:37 +02:00
Paul Miller
aade023e48 pkg.json: Adjust funding field 2023-05-27 16:10:58 +02:00
Paul Miller
2e04d96ce9 readme 2023-05-26 13:27:41 +02:00
Paul Miller
79dd7d3426 readme 2023-05-20 12:34:51 +02:00
Paul Miller
ff5b231e31 secp256k1 & other implementations: reduce bundle size by 20% by using PURE.
PURE annotation helps bundlers during tree-shaking and eliminates dead code.

* secp256k1: 75.4kb => 62.3kb

* ed25519: 67.5kb => 51.1kb

* ed448: 55.1kb => 44.0kb

* p256: 67.8kb => 59.8kb

* p384: 75.4kb => 67.4kb

* p521: 75.8kb => 67.8kb
2023-05-20 10:49:50 +02:00
Paul Miller
648fd2cc07 benchmark: curves should bench ed25519 first 2023-05-19 09:58:30 +02:00
Paul Miller
f67134ca86 benchmark: add msm to bls 2023-05-19 09:58:13 +02:00
Paul Miller
6d0678b076 readme 2023-05-14 06:54:17 +02:00
Paul Miller
53ebde19ea readme 2023-05-14 06:48:22 +02:00
Paul Miller
a7755332c8 readme 2023-05-14 06:40:09 +02:00
Paul Miller
5f0007ab24 readme 2023-05-13 01:31:55 +02:00
Paul Miller
1ee5a5c07f CI: auto-publish to NPM on GH release 2023-05-12 20:53:24 +02:00
Paul Miller
708c0e14d5 readme 2023-05-12 19:03:17 +02:00
Paul Miller
624d7c9910 Merge pull request #46 from sublimator/nd-sort-few-typos-things-editor-nagging-about-2023-05-09
docs(modular): sort few typos/things editor nagging about
2023-05-09 18:01:35 +02:00
Nicholas Dudfield
665ef2dd93 docs(modular): sort few typos/things editor nagging about 2023-05-09 07:35:33 +07:00
Paul Miller
acc1f26acf readme 2023-05-07 23:32:41 +02:00
Paul Miller
3c4a25263e readme 2023-05-06 22:05:33 +02:00
Paul Miller
e887d516ab readme 2023-05-06 21:20:38 +02:00
Paul Miller
90e87f7ab1 weierstrass: adjust SWUFpSqrtRatio to not use exp operator 2023-05-06 14:38:53 +02:00
Paul Miller
5edafbac97 Merge pull request #42 from sublimator/patch-1
ed25519: fix ristrettoHash size typo in hashToCurve
2023-05-05 17:48:08 +02:00
Nicholas Dudfield
554c94509e ed25519: fix ristrettoHash size typo in hashToCurve 2023-05-05 18:17:40 +07:00
Paul Miller
7c11a021c0 Drop v16 from ci, it will be out in 4 months 2023-05-05 03:54:16 +02:00
Paul Miller
531b6a3a48 Adjust CI 2023-05-05 03:53:35 +02:00
Paul Miller
fb5cd9df39 README 2023-05-05 03:52:49 +02:00
Paul Miller
53a6d636d4 Merge pull request #38 from legobeat/ci-node-version-matrix
ci: test nodejs v16/v18/v20
2023-05-05 03:50:00 +02:00
Paul Miller
42de620010 edwards: make zip215 false Strongly Binding Signature (SBS) secure. gh-40 2023-05-05 03:37:13 +02:00
Paul Miller
6621053c7d edwards: ensure Point.fromHex fails when x=0 and first x bit is 1. gh-40 2023-05-05 01:39:53 +02:00
Paul Miller
9bee88888f weierstrass: improve return type of sign(). Clarify comments. 2023-05-03 18:28:35 +02:00
legobt
103ba5f0a7 ci: test nodejs v16/v18/v20 2023-05-02 11:59:54 +09:00
Paul Miller
d5de5d2659 README: add more projects using curves 2023-04-28 02:46:07 +02:00
Paul Miller
217cf8c654 readme: more resources 2023-04-27 01:58:29 +02:00
Paul Miller
8e307d8f89 readme 2023-04-27 01:01:42 +02:00
Paul Miller
8c0018d57f readme 2023-04-27 00:54:41 +02:00
Paul Miller
ca7f202839 Add secp256k1 compatibility layer URL to readme 2023-04-27 00:16:29 +02:00
Paul Miller
816077ac0a README 2023-04-24 13:00:43 +02:00
Paul Miller
bc03a07043 readme 2023-04-23 20:31:29 +02:00
Paul Miller
63653255e1 ed448: rename to edwardsToMontgomeryPub 2023-04-23 20:29:17 +02:00
Paul Miller
895ee3a1a4 bls: refactor slightly 2023-04-23 20:29:03 +02:00
Paul Miller
16b31b9087 edwards: use bitmask instead of exp 2023-04-23 20:28:47 +02:00
Paul Miller
213796db4b ed25519: rename to edwardsToMontgomeryPub 2023-04-23 20:28:28 +02:00
Paul Miller
049d3bce54 CI: node.js 20 2023-04-23 20:17:45 +02:00
Paul Miller
b2a04c2393 Merge pull request #32 from mirceanis/31-fix-edwardsToMontgomery
ed25519: fix edwardsToMontgomery formula; implement edwardsToMontgomeryPriv
2023-04-23 20:16:22 +02:00
Paul Miller
cb5e9a6e96 Update benchmarks 2023-04-22 03:20:11 +02:00
Paul Miller
36af62357f test: adjust ed and secp tests a bit 2023-04-22 02:24:41 +02:00
Mircea Nistor
88291eba33 ed25519: fix edwardsToMontgomery formula; implement edwardsToMontgomeryPriv; add tests 2023-04-20 13:37:21 +02:00
Paul Miller
848a1b0226 nist tests: add endomorphism test 2023-04-14 19:53:20 +02:00
Paul Miller
972e549dde bls: no bigint literals 2023-04-13 17:18:39 +02:00
Paul Miller
d61c7ae4e5 Release 1.0.0. 2023-04-12 04:42:02 +02:00
Paul Miller
d3de7c8863 readme 2023-04-12 04:38:33 +02:00
Paul Miller
6316643f51 Rename bn to bn254 2023-04-12 04:33:32 +02:00
Paul Miller
7199f113c6 readme 2023-04-12 04:21:29 +02:00
Paul Miller
71f6948612 Adjust readme and ed25519 docs 2023-04-12 04:16:47 +02:00
Paul Miller
d3d03ff115 README, bls 2023-04-12 04:10:59 +02:00
Paul Miller
e2c3560686 Remove types/node 2023-04-12 03:57:30 +02:00
Paul Miller
4e9c40b3e5 readme 2023-04-11 15:19:02 +02:00
Paul Miller
09085d2ee1 readme 2023-04-11 15:17:24 +02:00
Paul Miller
8c4d781479 readme 2023-04-10 21:12:13 +02:00
Paul Miller
123431de66 nist curves: rename from P256 to p256 for consistency 2023-04-10 21:04:16 +02:00
Paul Miller
7503aff45c README 2023-04-10 19:40:58 +02:00
Paul Miller
81e6046698 test: move vector 2023-04-10 05:23:35 +02:00
Paul Miller
30f7d78c82 hash-to-curve: update benchmarks, lint 2023-04-10 05:10:38 +02:00
Paul Miller
00665b21ab htf: Prohibit expand: undefined. Closes gh-18 2023-04-10 05:02:36 +02:00
Paul Miller
5d54bba846 lint 2023-04-08 21:23:42 +02:00
Paul Miller
851af4f1bc weierstrass: adjust 1 line 2023-04-08 21:23:35 +02:00
Paul Miller
6ea40d9dab Update tests. Update wycheproof from v0.8 to v0.9 2023-04-08 19:00:18 +02:00
Paul Miller
8beb922ded weierstrass: improve DER decoding. Validate curve creation. 2023-04-07 06:09:46 +02:00
Paul Miller
fe380da8c9 edwards: change strict option to zip215 2023-04-02 18:35:34 +02:00
Paul Miller
113d906233 edwards: change API. Add options.strict, context. Add edwardsToMontgomery 2023-04-02 17:35:03 +02:00
Paul Miller
65c0dc6c59 README 2023-04-02 17:34:33 +02:00
Paul Miller
ed3ba3de6e Prettier 2023-04-02 16:50:54 +02:00
Paul Miller
d424c661fb Fix tests 2023-04-02 16:50:27 +02:00
Paul Miller
31d92cce11 README update 2023-04-02 16:42:49 +02:00
Paul Miller
c15c964f77 Refactor BLS, change API 2023-04-02 16:38:03 +02:00
Paul Miller
37ebe6c40f tests of ed25519, ed448: improve 2023-04-02 15:38:36 +02:00
Paul Miller
18eabfd3be Remove unused devdeps 2023-04-02 14:17:50 +02:00
Paul Miller
19f04a4c1c Release 0.9.1. 2023-03-31 10:02:05 +02:00
Paul Miller
d0c3bee4de weierstrass, edwards: make points expose typescript x, y 2023-03-30 09:20:35 +02:00
Paul Miller
4244f97d38 bls: get rid of bigint literals. gh-22 2023-03-28 19:01:42 +02:00
Paul Miller
618508d32c weierstrass, edwards: get rid of bigint literals. Closes gh-22 2023-03-28 19:01:00 +02:00
Paul Miller
3936449e7b edwards: add toRawBytes to ts type 2023-03-26 15:54:04 +02:00
Paul Miller
0ffa38db6b Release 0.9.0. 2023-03-24 11:12:02 +01:00
Paul Miller
c4c580edc0 Bump devdeps 2023-03-24 11:06:48 +01:00
Paul Miller
abe8adac7b README 2023-03-24 10:25:03 +01:00
Paul Miller
4fd2ae82b6 readme 2023-03-21 07:27:45 +01:00
Paul Miller
e2411f7dfd modular: add comment 2023-03-21 07:25:09 +01:00
Paul Miller
cb61e4f292 readme 2023-03-21 07:25:01 +01:00
Paul Miller
bb875791bd docs 2023-03-21 07:11:17 +01:00
Paul Miller
3df2553ced Docs 2023-03-21 07:02:07 +01:00
Paul Miller
8fabc7ff06 All files: rename Fp to Field 2023-03-21 06:51:18 +01:00
Paul Miller
f3c21eb347 weierstrass: make weierstrassPoints fromBytes / toBytes optional 2023-03-21 05:51:10 +01:00
Paul Miller
a8b8192714 Add CURVE.p param 2023-03-21 03:06:06 +01:00
Paul Miller
1c6aa07ff7 Release 0.8.3. 2023-03-16 19:41:20 +01:00
Paul Miller
e110237298 readme 2023-03-16 19:17:34 +01:00
Paul Miller
45393db807 Bump docs 2023-03-16 19:05:33 +01:00
Paul Miller
acc3a9dc4d Bump devdep types/node 2023-03-16 18:52:03 +01:00
Paul Miller
9295b0dbae Upgrade to Typescript 5 2023-03-16 18:49:48 +01:00
Paul Miller
5784ef23f6 Release 0.8.2. 2023-03-14 00:44:02 +01:00
Paul Miller
ef55efe842 Fix common.js build 2023-03-14 00:42:40 +01:00
Paul Miller
1cfd6a76ca Release 0.8.1. 2023-03-14 00:40:05 +01:00
Paul Miller
89f81b2204 pkg.json: improve bench, clean scripts 2023-03-14 00:39:21 +01:00
Paul Miller
d77ac16f51 Bring back common.js for now. Need more thorough work with consumers 2023-03-14 00:32:09 +01:00
Paul Miller
fe68da61f6 Move stark curve to micro-starknet 2023-03-10 20:18:05 +01:00
Paul Miller
32c0841bed Add Trail of Bits audit 2023-03-10 01:09:49 +01:00
Paul Miller
49a659b248 Release 0.8.0. 2023-03-03 05:12:36 +04:00
Paul Miller
9d0a2e25dc readme: esm-only 2023-03-03 05:11:21 +04:00
Paul Miller
7c461af2b2 test: remove common.js support 2023-03-03 05:09:50 +04:00
Paul Miller
4a8f447c8d package.json, tsconfig: remove common.js support. Pure ESM now 2023-03-03 05:09:36 +04:00
Paul Miller
4b2d31ce7f stark: more methods 2023-02-28 23:18:06 +04:00
Paul Miller
16115f27a6 readme update 2023-02-28 14:04:15 +04:00
Paul Miller
0e0d0f530d benchmark: add tonneli-shanks sqrt 2023-02-28 02:59:28 +04:00
Paul Miller
fa5105aef2 ecdsa: remove scalar blinding. CSPRNG dep not good: cryptofuzz, other envs will fail 2023-02-28 01:48:06 +04:00
Paul Miller
11f1626ecc modular: Add comment. Add benchmark 2023-02-27 22:41:24 +04:00
Paul Miller
53ff287bf7 Schnorr: remove getExtendedPublicKey 2023-02-27 20:29:47 +04:00
Paul Miller
214c9aa553 secp256k1: Fix schnorrGetExtPubKey y coordinate 2023-02-27 20:20:13 +04:00
Paul Miller
ec2c3e1248 Add test for ristretto equality testing 2023-02-27 19:33:41 +04:00
Paul Miller
e64a9d654c Fix ristretto255 equals 2023-02-27 19:07:45 +04:00
Paul Miller
088edd0fbb h2c: move params validation. add experimental hash_to_ristretto255 2023-02-27 15:07:24 +01:00
Paul Miller
3e90930e9d Fix types 2023-02-26 19:10:50 +01:00
Paul Miller
b8b2e91f74 Release 0.7.3. 2023-02-26 19:05:53 +01:00
Paul Miller
9ee694ae23 docs updates 2023-02-26 19:05:40 +01:00
Paul Miller
6bc4b35cf4 hash-to-curve: speed-up os2ip, change code a bit 2023-02-26 18:55:30 +01:00
Paul Miller
0163b63532 Release 0.7.2. 2023-02-25 10:13:45 +01:00
Paul Miller
7e825520f1 README 2023-02-25 10:05:48 +01:00
Paul Miller
d739297b2c Move p192, p224 from main pkg to tests for now. Reason: not popular 2023-02-25 10:00:24 +01:00
Paul Miller
285aa6375d stark: refactor 2023-02-20 16:50:29 +01:00
Paul Miller
8c77331ef2 add hash-to-curve benchmark 2023-02-20 16:33:05 +01:00
Paul Miller
669641e0a3 README wording 2023-02-16 17:54:17 +01:00
Paul Miller
68dd57ed31 Cryptofuzz 2023-02-16 17:49:48 +01:00
Paul Miller
a9fdd6df9f readme: typo 2023-02-16 12:33:32 +01:00
Paul Miller
d485d8b0e6 Fix prettier 2023-02-16 12:32:32 +01:00
Paul Miller
0fdd763dc7 montgomery: add randomPrivateKey. Add ecdh benchmark. 2023-02-16 12:32:18 +01:00
Paul Miller
586e2ad5fb Release 0.7.1. 2023-02-16 00:20:37 +01:00
Paul Miller
ed81707bdc readme 2023-02-16 00:12:23 +01:00
Paul Miller
6d56b2d78e readme 2023-02-16 00:08:18 +01:00
Paul Miller
8397241a8f bls, stark: adjust methods 2023-02-16 00:03:20 +01:00
Paul Miller
001d0cc24a weierstrass: rename method, adjust comments 2023-02-16 00:03:10 +01:00
Paul Miller
ce9d165657 readme hash-to-scalar 2023-02-15 23:46:43 +01:00
Paul Miller
2902b0299a readme 2023-02-15 23:38:26 +01:00
Paul Miller
e1cb8549e8 weierstrass, montgomery, secp: add comments 2023-02-15 23:26:56 +01:00
Paul Miller
26ebb5dcce x25519, x448: change param from a24 to a. Change Gu to bigint 2023-02-15 23:07:52 +01:00
Paul Miller
8b2863aeac Fix benchmark 2023-02-15 22:50:32 +01:00
Paul Miller
b1f50d9364 hash-to-curve: bls examples 2023-02-15 00:08:38 +01:00
Paul Miller
b81d74d3cb readme 2023-02-15 00:06:39 +01:00
Paul Miller
d5fe537159 hash-to-curve readme 2023-02-15 00:03:18 +01:00
Paul Miller
cde1d5c488 Fix tests 2023-02-14 23:51:11 +01:00
Paul Miller
3486bbf6b8 Release 0.7.0. 2023-02-14 23:45:53 +01:00
Paul Miller
0d7a8296c5 gitignore update 2023-02-14 23:45:39 +01:00
Paul Miller
0f1e7a5a43 Move output from lib to root. React Native does not support pkg.json#exports 2023-02-14 23:43:28 +01:00
Paul Miller
3da48cf899 bump bmark 2023-02-14 23:24:11 +01:00
Paul Miller
4ec46dd65d Remove scure-base from top-level dep 2023-02-14 18:00:11 +01:00
Paul Miller
7073f63c6b drbg: move from weierstrass to utils 2023-02-14 17:54:57 +01:00
Paul Miller
80966cbd03 hash-to-curve: more type checks. Rename method to createHasher 2023-02-14 17:39:56 +01:00
Paul Miller
98ea15dca4 edwards: improve hex errors 2023-02-14 17:35:19 +01:00
Paul Miller
e1910e85ea mod, utils, weierstrass, secp: improve hex errors. secp: improve verify() logic and schnorr 2023-02-14 17:34:31 +01:00
Paul Miller
4d311d7294 Emit source maps 2023-02-14 17:23:51 +01:00
Paul Miller
c36d90cae6 bump lockfile, add comment to shortw 2023-02-13 23:55:58 +01:00
Paul Miller
af5aa8424f readme: supply chain attacks 2023-02-13 23:32:49 +01:00
Paul Miller
67b99652fc BLS: add docs 2023-02-12 22:25:36 +01:00
Paul Miller
c8d292976b README 2023-02-12 22:25:22 +01:00
Paul Miller
daffaa2339 README: more docs 2023-02-12 21:37:27 +01:00
Paul Miller
a462fc5779 readme updates 2023-02-12 11:30:55 +01:00
Paul Miller
fe3491c5aa Release 0.6.4. 2023-02-09 23:19:15 +01:00
Paul Miller
c0877ba69a Fix weierstrass type 2023-02-09 23:18:32 +01:00
Paul Miller
8e449cc78c ed25519 tests: unify with noble-ed25519 2023-02-09 21:26:24 +01:00
Paul Miller
1b6071cabd weierstrass: rename normPrivKey util. tests: prepare for unification w old noble pkg 2023-02-09 20:26:20 +01:00
138 changed files with 267625 additions and 128783 deletions

View File

@@ -3,15 +3,18 @@ name: Node CI
on: [push, pull_request]
jobs:
test:
name: v18 @ ubuntu-latest
name: v${{ matrix.node }} @ ubuntu-latest
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@v3
with:
node-version: 18
node-version: ${{ matrix.node }}
- run: npm install
- run: npm run build --if-present
- run: npm run lint --if-present
- run: npm test
- run: npm run lint --if-present

23
.github/workflows/publish-npm.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Publish Package to npm
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
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: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

14
.gitignore vendored
View File

@@ -1,7 +1,13 @@
build/
node_modules/
coverage/
/lib/**/*.js
/lib/**/*.ts
/lib/**/*.d.ts.map
/curve-definitions/lib
/*.js
/*.ts
/*.js.map
/*.d.ts.map
/esm/*.js
/esm/*.ts
/esm/*.js.map
/esm/*.d.ts.map
/esm/abstract
/abstract/

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"files.exclude": {
"*.{js,d.ts,js.map,d.ts.map}": true,
"esm/*.{js,d.ts,js.map,d.ts.map}": true
}
}

1054
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,8 @@
| Version | Supported |
| ------- | ------------------ |
| >=0.5.0 | :white_check_mark: |
| <0.5.0 | :x: |
| >=1.0.0 | :white_check_mark: |
| <1.0.0 | :x: |
## Reporting a Vulnerability

Binary file not shown.

11
audit/README.md Normal file
View File

@@ -0,0 +1,11 @@
# Audit
The library has been audited during Jan-Feb 2023 by an independent security firm [Trail of Bits](https://www.trailofbits.com):
[PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
The audit has been funded by Ryan Shea. Audit scope was abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass`, and top-level modules `_shortw_utils` and `secp256k1`. See [changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main).
File in the directory was saved from
[github.com/trailofbits/publications](https://github.com/trailofbits/publications).
Check out their repo and verify checksums to ensure the PDF in this directory has not been altered.
See information about fuzzing in root [README](../README.md).

View File

@@ -1,6 +1,6 @@
import { readFileSync } from 'fs';
import { mark, run } from 'micro-bmark';
import { bls12_381 as bls } from '../lib/bls12-381.js';
import { bls12_381 as bls } from '../bls12-381.js';
const G2_VECTORS = readFileSync('../test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
.trim()
@@ -39,6 +39,21 @@ run(async () => {
await mark('sign', 50, () => bls.sign('09', priv));
await mark('verify', 50, () => bls.verify(sig, '09', pub));
await mark('pairing', 100, () => bls.pairing(p1, p2));
const scalars1 = Array(4096).fill(0).map(i => 2n ** 235n - BigInt(i));
const scalars2 = Array(4096).fill(0).map(i => 2n ** 241n + BigInt(i));
const points = scalars1.map(s => bls.G1.ProjectivePoint.BASE.multiply(s));
await mark('MSM 4096 scalars x points', 1, () => {
// naive approach, not using multi-scalar-multiplication
let sum = bls.G1.ProjectivePoint.ZERO;
for (let i = 0; i < 4096; i++) {
const scalar = scalars2[i];
const G1 = points[i];
const mutliplied = G1.multiplyUnsafe(scalar);
sum = sum.add(mutliplied);
}
});
await mark('aggregatePublicKeys/8', 100, () => bls.aggregatePublicKeys(pubs.slice(0, 8)));
await mark('aggregatePublicKeys/32', 50, () => bls.aggregatePublicKeys(pub32));
await mark('aggregatePublicKeys/128', 20, () => bls.aggregatePublicKeys(pub128));

View File

@@ -1,14 +1,14 @@
import { run, mark, utils } from 'micro-bmark';
import { generateData } from './_shared.js';
import { P256 } from '../lib/p256.js';
import { P384 } from '../lib/p384.js';
import { P521 } from '../lib/p521.js';
import { ed25519 } from '../lib/ed25519.js';
import { ed448 } from '../lib/ed448.js';
import { p256 } from '../p256.js';
import { p384 } from '../p384.js';
import { p521 } from '../p521.js';
import { ed25519 } from '../ed25519.js';
import { ed448 } from '../ed448.js';
run(async () => {
const RAM = false
for (let kv of Object.entries({ P256, P384, P521, ed25519, ed448 })) {
for (let kv of Object.entries({ ed25519, ed448, p256, p384, p521 })) {
const [name, curve] = kv;
console.log();
console.log(`\x1b[36m${name}\x1b[0m`);

18
benchmark/ecdh.js Normal file
View File

@@ -0,0 +1,18 @@
import { run, compare } from 'micro-bmark';
import { secp256k1 } from '../secp256k1.js';
import { p256 } from '../p256.js';
import { p384 } from '../p384.js';
import { p521 } from '../p521.js';
import { x25519 } from '../ed25519.js';
import { x448 } from '../ed448.js';
run(async () => {
const curves = { x25519, secp256k1, p256, p384, p521, x448 };
const fns = {};
for (let [k, c] of Object.entries(curves)) {
const pubB = c.getPublicKey(c.utils.randomPrivateKey());
const privA = c.utils.randomPrivateKey();
fns[k] = () => c.getSharedSecret(privA, pubB);
}
await compare('ecdh', 1000, fns);
});

View File

@@ -0,0 +1,29 @@
import { run, mark, utils } from 'micro-bmark';
import { hash_to_field } from '../abstract/hash-to-curve.js';
import { hashToPrivateScalar } from '../abstract/modular.js';
import { randomBytes } from '@noble/hashes/utils';
import { sha256 } from '@noble/hashes/sha256';
// import { generateData } from './_shared.js';
import { hashToCurve as secp256k1 } from '../secp256k1.js';
import { hashToCurve as p256 } from '../p256.js';
import { hashToCurve as p384 } from '../p384.js';
import { hashToCurve as p521 } from '../p521.js';
import { hashToCurve as ed25519 } from '../ed25519.js';
import { hashToCurve as ed448 } from '../ed448.js';
import { utf8ToBytes } from '../abstract/utils.js';
const N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
run(async () => {
const rand = randomBytes(40);
await mark('hashToPrivateScalar', 1000000, () => hashToPrivateScalar(rand, N));
// - p, the characteristic of F
// - m, the extension degree of F, m >= 1
// - L = ceil((ceil(log2(p)) + k) / 8), where k is the security of suite (e.g. 128)
await mark('hash_to_field', 1000000, () =>
hash_to_field(rand, 1, { DST: 'secp256k1', hash: sha256, expand: 'xmd', p: N, m: 1, k: 128 })
);
const msg = utf8ToBytes('message');
for (let [title, fn] of Object.entries({ secp256k1, p256, p384, p521, ed25519, ed448 })) {
await mark(`hashToCurve ${title}`, 1000, () => fn(msg));
}
});

13
benchmark/modular.js Normal file
View File

@@ -0,0 +1,13 @@
import { run, mark } from 'micro-bmark';
import { secp256k1 } from '../secp256k1.js';
import { Field as Fp } from '../abstract/modular.js';
run(async () => {
console.log(`\x1b[36mmodular, secp256k1 field\x1b[0m`);
const { Fp: secpFp } = secp256k1.CURVE;
await mark('invert a', 300000, () => secpFp.inv(2n ** 232n - 5910n));
await mark('invert b', 300000, () => secpFp.inv(2n ** 231n - 5910n));
await mark('sqrt p = 3 mod 4', 15000, () => secpFp.sqrt(2n ** 231n - 5910n));
const FpStark = Fp(BigInt('0x800000000000011000000000000000000000000000000000000000000000001'));
await mark('sqrt tonneli-shanks', 500, () => FpStark.sqrt(2n ** 231n - 5909n))
});

View File

@@ -16,7 +16,6 @@
},
"dependencies": {
"@noble/hashes": "^1.1.5",
"@starkware-industries/starkware-crypto-utils": "^0.0.2",
"elliptic": "^6.5.4"
}
}

View File

@@ -1,5 +1,5 @@
import { run, mark, utils } from 'micro-bmark';
import { secp256k1, schnorr } from '../lib/secp256k1.js';
import { secp256k1, schnorr } from '../secp256k1.js';
import { generateData } from './_shared.js';
run(async () => {

View File

@@ -1,56 +0,0 @@
import { run, mark, compare, utils } from 'micro-bmark';
import * as starkwareCrypto from '@starkware-industries/starkware-crypto-utils';
import * as stark from '../lib/stark.js';
run(async () => {
const RAM = false;
if (RAM) utils.logMem();
console.log(`\x1b[36mstark\x1b[0m`);
await mark('init', 1, () => stark.utils.precompute(8));
const d = (() => {
const priv = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
const msg = 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47';
const pub = stark.getPublicKey(priv);
const sig = stark.sign(msg, priv);
const privateKey = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
const msgHash = 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47';
const keyPair = starkwareCrypto.default.ec.keyFromPrivate(privateKey, 'hex');
const publicKeyStark = starkwareCrypto.default.ec.keyFromPublic(
keyPair.getPublic(true, 'hex'),
'hex'
);
return { priv, sig, msg, pub, publicKeyStark, msgHash, keyPair };
})();
await compare('pedersen', 500, {
old: () => {
return starkwareCrypto.default.pedersen([
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a',
]);
},
noble: () => {
return stark.pedersen(
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a'
);
},
});
await mark('poseidon', 10000, () => stark.poseidonHash(
0x3d937c035c878245caf64531a5756109c53068da139362728feb561405371cbn,
0x208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31an
));
await compare('verify', 500, {
old: () => {
return starkwareCrypto.default.verify(
d.publicKeyStark,
d.msgHash,
starkwareCrypto.default.sign(d.keyPair, d.msgHash)
);
},
noble: () => {
return stark.verify(stark.sign(d.msg, d.priv), d.msg, d.pub);
},
});
if (RAM) utils.logMem();
});

7
build/README.md Normal file
View File

@@ -0,0 +1,7 @@
# build
The directory is used to build a single file `noble-curves.js` which contains everything.
The output 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.

11
build/input.js Normal file
View File

@@ -0,0 +1,11 @@
import { bytesToHex, concatBytes, hexToBytes } from '@noble/curves/abstract/utils';
export { secp256k1 } from '@noble/curves/secp256k1';
export { ed25519, x25519 } from '@noble/curves/ed25519';
export { ed448, x448 } from '@noble/curves/ed448';
export { p256 } from '@noble/curves/p256';
export { p384 } from '@noble/curves/p384';
export { p521 } from '@noble/curves/p521';
export { bls12_381 } from '@noble/curves/bls12-381';
export const utils = { bytesToHex, concatBytes, hexToBytes };

18
build/package.json Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "build",
"private": true,
"version": "1.0.0",
"description": "Used to build a single file",
"main": "input.js",
"keywords": [],
"type": "module",
"author": "",
"license": "MIT",
"devDependencies": {
"@noble/curves": "..",
"esbuild": "0.17.19"
},
"scripts": {
"build": "npx esbuild --bundle input.js --outfile=noble-curves.js --global-name=nobleCurves"
}
}

View File

@@ -2,6 +2,6 @@
"type": "module",
"browser": {
"crypto": false,
"./crypto": "./esm/cryptoBrowser.js"
"./crypto": "./esm/crypto.js"
}
}

122
package-lock.json generated
View File

@@ -1,107 +1,37 @@
{
"name": "@noble/curves",
"version": "0.6.2",
"version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@noble/curves",
"version": "0.6.2",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"version": "1.1.0",
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.2.0"
"@noble/hashes": "1.3.1"
},
"devDependencies": {
"@scure/base": "~1.1.1",
"@scure/bip32": "~1.1.5",
"@scure/bip39": "~1.1.1",
"@types/node": "18.11.3",
"fast-check": "3.0.0",
"micro-bmark": "0.3.0",
"micro-bmark": "0.3.1",
"micro-should": "0.4.0",
"prettier": "2.8.3",
"typescript": "4.7.3"
"prettier": "2.8.4",
"typescript": "5.0.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz",
"integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==",
"funding": [
{
"type": "individual",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@noble/secp256k1": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
"integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@scure/base": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@scure/bip32": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz",
"integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"@noble/hashes": "~1.2.0",
"@noble/secp256k1": "~1.7.0",
"@scure/base": "~1.1.0"
}
},
"node_modules/@scure/bip39": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz",
"integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"@noble/hashes": "~1.2.0",
"@scure/base": "~1.1.0"
}
},
"node_modules/@types/node": {
"version": "18.11.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz",
"integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==",
"dev": true
},
"node_modules/fast-check": {
"version": "3.0.0",
@@ -120,9 +50,9 @@
}
},
"node_modules/micro-bmark": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/micro-bmark/-/micro-bmark-0.3.0.tgz",
"integrity": "sha512-rYu+AtUq8lC3zPCoxkOOtwhgJoMpCDGe0/BXUCkj6+H9f/U/TunH/n/qkN98yh04dCCtDV8Aj9uYO3+DKxYrcw==",
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/micro-bmark/-/micro-bmark-0.3.1.tgz",
"integrity": "sha512-bNaKObD4yPAAPrpEqp5jO6LJ2sEFgLoFSmRjEY809mJ62+2AehI/K3+RlVpN3Oo92RHpgC2RQhj6b1Tb4dmo+w==",
"dev": true
},
"node_modules/micro-should": {
@@ -132,9 +62,9 @@
"dev": true
},
"node_modules/prettier": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
"integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz",
"integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
@@ -163,16 +93,16 @@
]
},
"node_modules/typescript": {
"version": "4.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz",
"integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==",
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz",
"integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
"node": ">=12.20"
}
}
}

View File

@@ -1,14 +1,21 @@
{
"name": "@noble/curves",
"version": "0.6.3",
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
"version": "1.1.0",
"description": "Audited & minimal JS implementation of elliptic curve cryptography",
"files": [
"lib"
"abstract",
"esm",
"src",
"*.js",
"*.js.map",
"*.d.ts",
"*.d.ts.map"
],
"scripts": {
"bench": "cd benchmark; node secp256k1.js; node curves.js; node stark.js; node bls.js",
"bench": "cd benchmark; node secp256k1.js; node curves.js; node ecdh.js; node hash-to-curve.js; node modular.js; node bls.js",
"build": "tsc && tsc -p tsconfig.esm.json",
"build:release": "rollup -c rollup.config.js",
"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'",
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'",
"test": "node test/index.test.js"
@@ -21,145 +28,126 @@
},
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.2.0"
"@noble/hashes": "1.3.1"
},
"devDependencies": {
"@scure/base": "~1.1.1",
"@scure/bip32": "~1.1.5",
"@scure/bip39": "~1.1.1",
"@types/node": "18.11.3",
"fast-check": "3.0.0",
"micro-bmark": "0.3.0",
"micro-bmark": "0.3.1",
"micro-should": "0.4.0",
"prettier": "2.8.3",
"typescript": "4.7.3"
"prettier": "2.8.4",
"typescript": "5.0.2"
},
"main": "index.js",
"exports": {
".": {
"types": "./lib/index.d.ts",
"import": "./lib/esm/index.js",
"default": "./lib/index.js"
"types": "./index.d.ts",
"import": "./esm/index.js",
"default": "./index.js"
},
"./abstract/edwards": {
"types": "./lib/abstract/edwards.d.ts",
"import": "./lib/esm/abstract/edwards.js",
"default": "./lib/abstract/edwards.js"
"types": "./abstract/edwards.d.ts",
"import": "./esm/abstract/edwards.js",
"default": "./abstract/edwards.js"
},
"./abstract/modular": {
"types": "./lib/abstract/modular.d.ts",
"import": "./lib/esm/abstract/modular.js",
"default": "./lib/abstract/modular.js"
"types": "./abstract/modular.d.ts",
"import": "./esm/abstract/modular.js",
"default": "./abstract/modular.js"
},
"./abstract/montgomery": {
"types": "./lib/abstract/montgomery.d.ts",
"import": "./lib/esm/abstract/montgomery.js",
"default": "./lib/abstract/montgomery.js"
"types": "./abstract/montgomery.d.ts",
"import": "./esm/abstract/montgomery.js",
"default": "./abstract/montgomery.js"
},
"./abstract/weierstrass": {
"types": "./lib/abstract/weierstrass.d.ts",
"import": "./lib/esm/abstract/weierstrass.js",
"default": "./lib/abstract/weierstrass.js"
"types": "./abstract/weierstrass.d.ts",
"import": "./esm/abstract/weierstrass.js",
"default": "./abstract/weierstrass.js"
},
"./abstract/bls": {
"types": "./lib/abstract/bls.d.ts",
"import": "./lib/esm/abstract/bls.js",
"default": "./lib/abstract/bls.js"
"types": "./abstract/bls.d.ts",
"import": "./esm/abstract/bls.js",
"default": "./abstract/bls.js"
},
"./abstract/hash-to-curve": {
"types": "./lib/abstract/hash-to-curve.d.ts",
"import": "./lib/esm/abstract/hash-to-curve.js",
"default": "./lib/abstract/hash-to-curve.js"
"types": "./abstract/hash-to-curve.d.ts",
"import": "./esm/abstract/hash-to-curve.js",
"default": "./abstract/hash-to-curve.js"
},
"./abstract/curve": {
"types": "./lib/abstract/curve.d.ts",
"import": "./lib/esm/abstract/curve.js",
"default": "./lib/abstract/curve.js"
"types": "./abstract/curve.d.ts",
"import": "./esm/abstract/curve.js",
"default": "./abstract/curve.js"
},
"./abstract/utils": {
"types": "./lib/abstract/utils.d.ts",
"import": "./lib/esm/abstract/utils.js",
"default": "./lib/abstract/utils.js"
"types": "./abstract/utils.d.ts",
"import": "./esm/abstract/utils.js",
"default": "./abstract/utils.js"
},
"./abstract/poseidon": {
"types": "./lib/abstract/poseidon.d.ts",
"import": "./lib/esm/abstract/poseidon.js",
"default": "./lib/abstract/poseidon.js"
"types": "./abstract/poseidon.d.ts",
"import": "./esm/abstract/poseidon.js",
"default": "./abstract/poseidon.js"
},
"./_shortw_utils": {
"types": "./lib/_shortw_utils.d.ts",
"import": "./lib/esm/_shortw_utils.js",
"default": "./lib/_shortw_utils.js"
"types": "./_shortw_utils.d.ts",
"import": "./esm/_shortw_utils.js",
"default": "./_shortw_utils.js"
},
"./bls12-381": {
"types": "./lib/bls12-381.d.ts",
"import": "./lib/esm/bls12-381.js",
"default": "./lib/bls12-381.js"
"types": "./bls12-381.d.ts",
"import": "./esm/bls12-381.js",
"default": "./bls12-381.js"
},
"./bn": {
"types": "./lib/bn.d.ts",
"import": "./lib/esm/bn.js",
"default": "./lib/bn.js"
"./bn254": {
"types": "./bn254.d.ts",
"import": "./esm/bn254.js",
"default": "./bn254.js"
},
"./ed25519": {
"types": "./lib/ed25519.d.ts",
"import": "./lib/esm/ed25519.js",
"default": "./lib/ed25519.js"
"types": "./ed25519.d.ts",
"import": "./esm/ed25519.js",
"default": "./ed25519.js"
},
"./ed448": {
"types": "./lib/ed448.d.ts",
"import": "./lib/esm/ed448.js",
"default": "./lib/ed448.js"
"types": "./ed448.d.ts",
"import": "./esm/ed448.js",
"default": "./ed448.js"
},
"./index": {
"types": "./lib/index.d.ts",
"import": "./lib/esm/index.js",
"default": "./lib/index.js"
"types": "./index.d.ts",
"import": "./esm/index.js",
"default": "./index.js"
},
"./jubjub": {
"types": "./lib/jubjub.d.ts",
"import": "./lib/esm/jubjub.js",
"default": "./lib/jubjub.js"
},
"./p192": {
"types": "./lib/p192.d.ts",
"import": "./lib/esm/p192.js",
"default": "./lib/p192.js"
},
"./p224": {
"types": "./lib/p224.d.ts",
"import": "./lib/esm/p224.js",
"default": "./lib/p224.js"
"types": "./jubjub.d.ts",
"import": "./esm/jubjub.js",
"default": "./jubjub.js"
},
"./p256": {
"types": "./lib/p256.d.ts",
"import": "./lib/esm/p256.js",
"default": "./lib/p256.js"
"types": "./p256.d.ts",
"import": "./esm/p256.js",
"default": "./p256.js"
},
"./p384": {
"types": "./lib/p384.d.ts",
"import": "./lib/esm/p384.js",
"default": "./lib/p384.js"
"types": "./p384.d.ts",
"import": "./esm/p384.js",
"default": "./p384.js"
},
"./p521": {
"types": "./lib/p521.d.ts",
"import": "./lib/esm/p521.js",
"default": "./lib/p521.js"
"types": "./p521.d.ts",
"import": "./esm/p521.js",
"default": "./p521.js"
},
"./pasta": {
"types": "./lib/pasta.d.ts",
"import": "./lib/esm/pasta.js",
"default": "./lib/pasta.js"
"types": "./pasta.d.ts",
"import": "./esm/pasta.js",
"default": "./pasta.js"
},
"./secp256k1": {
"types": "./lib/secp256k1.d.ts",
"import": "./lib/esm/secp256k1.js",
"default": "./lib/secp256k1.js"
},
"./stark": {
"types": "./lib/stark.d.ts",
"import": "./lib/esm/stark.js",
"default": "./lib/stark.js"
"types": "./secp256k1.d.ts",
"import": "./esm/secp256k1.js",
"default": "./secp256k1.js"
}
},
"keywords": [
@@ -176,20 +164,17 @@
"secp256k1",
"ed25519",
"ed448",
"x25519",
"ed25519",
"bls12-381",
"bn254",
"pasta",
"bls",
"nist",
"noble",
"ecc",
"ecdsa",
"eddsa",
"schnorr"
],
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
"funding": "https://paulmillr.com/funding/"
}

View File

@@ -4,6 +4,7 @@ import { concatBytes, randomBytes } from '@noble/hashes/utils';
import { weierstrass, CurveType } from './abstract/weierstrass.js';
import { CHash } from './abstract/utils.js';
// connects noble-curves to noble-hashes
export function getHash(hash: CHash) {
return {
hash,

View File

@@ -12,8 +12,8 @@
* Some projects may prefer to swap this relation, it is not supported for now.
*/
import { AffinePoint } from './curve.js';
import { Field, hashToPrivateScalar } from './modular.js';
import { Hex, PrivKey, CHash, bitLen, bitGet, hexToBytes, bytesToHex } from './utils.js';
import { IField, hashToPrivateScalar } from './modular.js';
import { Hex, PrivKey, CHash, bitLen, bitGet, ensureBytes } from './utils.js';
import * as htf from './hash-to-curve.js';
import {
CurvePointsType,
@@ -24,13 +24,16 @@ import {
type Fp = bigint; // Can be different field?
// prettier-ignore
const _2n = BigInt(2), _3n = BigInt(3);
export type SignatureCoder<Fp2> = {
decode(hex: Hex): ProjPointType<Fp2>;
encode(point: ProjPointType<Fp2>): Uint8Array;
fromHex(hex: Hex): ProjPointType<Fp2>;
toRawBytes(point: ProjPointType<Fp2>): Uint8Array;
toHex(point: ProjPointType<Fp2>): string;
};
export type CurveType<Fp, Fp2, Fp6, Fp12> = {
r: bigint;
G1: Omit<CurvePointsType<Fp>, 'n'> & {
mapToCurve: htf.MapToCurve<Fp>;
htfDefaults: htf.Opts;
@@ -40,44 +43,32 @@ export type CurveType<Fp, Fp2, Fp6, Fp12> = {
mapToCurve: htf.MapToCurve<Fp2>;
htfDefaults: htf.Opts;
};
x: bigint;
Fp: Field<Fp>;
Fr: Field<bigint>;
Fp2: Field<Fp2> & {
fields: {
Fp: IField<Fp>;
Fr: IField<bigint>;
Fp2: IField<Fp2> & {
reim: (num: Fp2) => { re: bigint; im: bigint };
multiplyByB: (num: Fp2) => Fp2;
frobeniusMap(num: Fp2, power: number): Fp2;
};
Fp6: Field<Fp6>;
Fp12: Field<Fp12> & {
Fp6: IField<Fp6>;
Fp12: IField<Fp12> & {
frobeniusMap(num: Fp12, power: number): Fp12;
multiplyBy014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
conjugate(num: Fp12): Fp12;
finalExponentiate(num: Fp12): Fp12;
};
};
params: {
x: bigint;
r: bigint;
};
htfDefaults: htf.Opts;
hash: CHash; // Because we need outputLen for DRBG
randomBytes: (bytesLength?: number) => Uint8Array;
};
export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>;
Fr: Field<bigint>;
Fp: Field<Fp>;
Fp2: Field<Fp2>;
Fp6: Field<Fp6>;
Fp12: Field<Fp12>;
G1: CurvePointsRes<Fp>;
G2: CurvePointsRes<Fp2>;
Signature: SignatureCoder<Fp2>;
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
// prettier-ignore
hashToCurve: {
G1: ReturnType<(typeof htf.hashToCurve<Fp>)>,
G2: ReturnType<(typeof htf.hashToCurve<Fp2>)>,
},
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
getPublicKey: (privateKey: PrivKey) => Uint8Array;
sign: {
(message: Hex, privateKey: PrivKey): Uint8Array;
@@ -88,6 +79,11 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
message: Hex | ProjPointType<Fp2>,
publicKey: Hex | ProjPointType<Fp>
) => boolean;
verifyBatch: (
signature: Hex | ProjPointType<Fp2>,
messages: (Hex | ProjPointType<Fp2>)[],
publicKeys: (Hex | ProjPointType<Fp>)[]
) => boolean;
aggregatePublicKeys: {
(publicKeys: Hex[]): Uint8Array;
(publicKeys: ProjPointType<Fp>[]): ProjPointType<Fp>;
@@ -96,24 +92,36 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
(signatures: Hex[]): Uint8Array;
(signatures: ProjPointType<Fp2>[]): ProjPointType<Fp2>;
};
verifyBatch: (
signature: Hex | ProjPointType<Fp2>,
messages: (Hex | ProjPointType<Fp2>)[],
publicKeys: (Hex | ProjPointType<Fp>)[]
) => boolean;
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
Signature: SignatureCoder<Fp2>;
params: {
x: bigint;
r: bigint;
G1b: bigint;
G2b: Fp2;
};
fields: {
Fp: IField<Fp>;
Fp2: IField<Fp2>;
Fp6: IField<Fp6>;
Fp12: IField<Fp12>;
Fr: IField<bigint>;
};
utils: {
stringToBytes: typeof htf.stringToBytes;
hashToField: typeof htf.hash_to_field;
expandMessageXMD: typeof htf.expand_message_xmd;
randomPrivateKey: () => Uint8Array;
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
};
};
export function bls<Fp2, Fp6, Fp12>(
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>
): CurveFn<Fp, Fp2, Fp6, Fp12> {
// Fields looks pretty specific for curve, so for now we need to pass them with options
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
const BLS_X_LEN = bitLen(CURVE.x);
// Fields are specific for curve, so for now we'll need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
const BLS_X_LEN = bitLen(CURVE.params.x);
const groupLen = 32; // TODO: calculate; hardcoded for now
// Pre-compute coefficients for sparse multiplication
@@ -129,18 +137,18 @@ export function bls<Fp2, Fp6, Fp12>(
// Double
let t0 = Fp2.sqr(Ry); // Ry²
let t1 = Fp2.sqr(Rz); // Rz²
let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, 3n); // 3 * T2
let t2 = Fp2.multiplyByB(Fp2.mul(t1, _3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, _3n); // 3 * T2
let t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
ell_coeff.push([
Fp2.sub(t2, t0), // T2 - T0
Fp2.mul(Fp2.sqr(Rx), 3n), // 3 * Rx²
Fp2.mul(Fp2.sqr(Rx), _3n), // 3 * Rx²
Fp2.neg(t4), // -T4
]);
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.sqr(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), _2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), _2n)), Fp2.mul(Fp2.sqr(t2), _3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rz = Fp2.mul(t0, t4); // T0 * T4
if (bitGet(CURVE.x, i)) {
if (bitGet(CURVE.params.x, i)) {
// Addition
let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
@@ -152,7 +160,7 @@ export function bls<Fp2, Fp6, Fp12>(
let t2 = Fp2.sqr(t1); // T1²
let t3 = Fp2.mul(t2, t1); // T2 * T1
let t4 = Fp2.mul(t2, Rx); // T2 * Rx
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
Rx = Fp2.mul(t1, t5); // T1 * T5
Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
Rz = Fp2.mul(Rz, t3); // Rz * T3
@@ -162,7 +170,7 @@ export function bls<Fp2, Fp6, Fp12>(
}
function millerLoop(ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]): Fp12 {
const { x } = CURVE;
const { x } = CURVE.params;
const Px = g1[0];
const Py = g1[1];
let f12 = Fp12.ONE;
@@ -180,31 +188,21 @@ export function bls<Fp2, Fp6, Fp12>(
}
const utils = {
hexToBytes: hexToBytes,
bytesToHex: bytesToHex,
stringToBytes: htf.stringToBytes,
// TODO: do we need to export it here?
hashToField: (
msg: Uint8Array,
count: number,
options: Partial<typeof CURVE.htfDefaults> = {}
) => htf.hash_to_field(msg, count, { ...CURVE.htfDefaults, ...options }),
expandMessageXMD: (msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H = CURVE.hash) =>
htf.expand_message_xmd(msg, DST, lenInBytes, H),
hashToPrivateKey: (hash: Hex): Uint8Array => Fr.toBytes(hashToPrivateScalar(hash, CURVE.r)),
randomBytes: (bytesLength: number = groupLen): Uint8Array => CURVE.randomBytes(bytesLength),
randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
randomPrivateKey: (): Uint8Array => {
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.params.r));
},
calcPairingPrecomputes,
};
// Point on G1 curve: (x, y)
const G1 = weierstrassPoints({
n: Fr.ORDER,
...CURVE.G1,
});
const G1HashToCurve = htf.hashToCurve(G1.ProjectivePoint, CURVE.G1.mapToCurve, {
const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 });
const G1 = Object.assign(
G1_,
htf.createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
...CURVE.htfDefaults,
...CURVE.G1.htfDefaults,
});
})
);
// Sparse multiplication against precomputed coefficients
// TODO: replace with weakmap?
@@ -223,15 +221,14 @@ export function bls<Fp2, Fp6, Fp12>(
// }
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
const G2 = weierstrassPoints({
n: Fr.ORDER,
...CURVE.G2,
});
const C = G2.ProjectivePoint as htf.H2CPointConstructor<Fp2>; // TODO: fix
const G2HashToCurve = htf.hashToCurve(C, CURVE.G2.mapToCurve, {
const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 });
const G2 = Object.assign(
G2_,
htf.createHasher(G2_.ProjectivePoint as htf.H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
...CURVE.htfDefaults,
...CURVE.G2.htfDefaults,
});
})
);
const { Signature } = CURVE.G2;
@@ -255,12 +252,12 @@ export function bls<Fp2, Fp6, Fp12>(
return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point);
}
function normP2(point: G2Hex): G2 {
return point instanceof G2.ProjectivePoint ? point : Signature.decode(point);
return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
}
function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {
return point instanceof G2.ProjectivePoint
? point
: (G2HashToCurve.hashToCurve(point, htfOpts) as G2);
: (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2);
}
// Multiplies generator by private key.
@@ -276,9 +273,9 @@ export function bls<Fp2, Fp6, Fp12>(
function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htf.htfBasicOpts): Uint8Array | G2 {
const msgPoint = normP2Hash(message, htfOpts);
msgPoint.assertValidity();
const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
if (message instanceof G2.ProjectivePoint) return sigPoint;
return Signature.encode(sigPoint);
return Signature.toRawBytes(sigPoint);
}
// Checks if pairing of public key & hash is equal to pairing of generator & signature.
@@ -328,7 +325,7 @@ export function bls<Fp2, Fp6, Fp12>(
aggAffine.assertValidity();
return aggAffine;
}
return Signature.encode(aggAffine);
return Signature.toRawBytes(aggAffine);
}
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
@@ -372,25 +369,30 @@ export function bls<Fp2, Fp6, Fp12>(
G1.ProjectivePoint.BASE._setWindowSize(4);
return {
CURVE,
getPublicKey,
sign,
verify,
verifyBatch,
aggregatePublicKeys,
aggregateSignatures,
millerLoop,
pairing,
G1,
G2,
Signature,
fields: {
Fr,
Fp,
Fp2,
Fp6,
Fp12,
G1,
G2,
Signature,
millerLoop,
calcPairingPrecomputes,
hashToCurve: { G1: G1HashToCurve, G2: G2HashToCurve },
pairing,
getPublicKey,
sign,
verify,
aggregatePublicKeys,
aggregateSignatures,
verifyBatch,
},
params: {
x: CURVE.params.x,
r: CURVE.params.r,
G1b: CURVE.G1.b,
G2b: CURVE.G2.b,
},
utils,
};
}

View File

@@ -1,6 +1,6 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Abelian group utilities
import { Field, validateField, nLength } from './modular.js';
import { IField, validateField, nLength } from './modular.js';
import { validateObject } from './utils.js';
const _0n = BigInt(0);
const _1n = BigInt(1);
@@ -168,7 +168,7 @@ export function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number) {
// Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok.
// Though generator can be different (Fp2 / Fp6 for BLS).
export type BasicCurve<T> = {
Fp: Field<T>; // Field over which we'll do calculations (Fp)
Fp: IField<T>; // Field over which we'll do calculations (Fp)
n: bigint; // Curve order, total count of valid points in the field
nBitLength?: number; // bit length of curve order
nByteLength?: number; // byte length of curve order
@@ -195,5 +195,9 @@ export function validateBasic<FP, T>(curve: BasicCurve<FP> & T) {
}
);
// Set defaults
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve } as const);
return Object.freeze({
...nLength(curve.n, curve.nBitLength),
...curve,
...{ p: curve.Fp.ORDER },
} as const);
}

View File

@@ -5,11 +5,9 @@ import * as ut from './utils.js';
import { ensureBytes, FHash, Hex } from './utils.js';
import { Group, GroupConstructor, wNAF, BasicCurve, validateBasic, AffinePoint } from './curve.js';
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
const _0n = BigInt(0);
const _1n = BigInt(1);
const _2n = BigInt(2);
const _8n = BigInt(8);
// Be friendly to bad ECMAScript parsers by not using bigint literals
// prettier-ignore
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
// Edwards curves must declare params a & d.
export type CurveType = BasicCurve<bigint> & {
@@ -20,10 +18,13 @@ export type CurveType = BasicCurve<bigint> & {
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array; // clears bits to get valid field elemtn
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array; // Used for hashing
uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint }; // Ratio √(u/v)
preHash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
prehash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>; // for hash-to-curve standard
};
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
const VERIFY_DEFAULT = { zip215: true };
function validateOpts(curve: CurveType) {
const opts = validateBasic(curve);
ut.validateObject(
@@ -51,6 +52,8 @@ export interface ExtPointType extends Group<ExtPointType> {
readonly ey: bigint;
readonly ez: bigint;
readonly et: bigint;
get x(): bigint;
get y(): bigint;
assertValidity(): void;
multiply(scalar: bigint): ExtPointType;
multiplyUnsafe(scalar: bigint): ExtPointType;
@@ -58,6 +61,8 @@ export interface ExtPointType extends Group<ExtPointType> {
isTorsionFree(): boolean;
clearCofactor(): ExtPointType;
toAffine(iz?: bigint): AffinePoint<bigint>;
toRawBytes(isCompressed?: boolean): Uint8Array;
toHex(isCompressed?: boolean): string;
}
// Static methods of Extended Point with coordinates in X, Y, Z, T
export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
@@ -70,8 +75,13 @@ export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
export type CurveFn = {
CURVE: ReturnType<typeof validateOpts>;
getPublicKey: (privateKey: Hex) => Uint8Array;
sign: (message: Hex, privateKey: Hex) => Uint8Array;
verify: (sig: Hex, message: Hex, publicKey: Hex) => boolean;
sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array;
verify: (
sig: Hex,
message: Hex,
publicKey: Hex,
options?: { context?: Hex; zip215: boolean }
) => boolean;
ExtendedPoint: ExtPointConstructor;
utils: {
randomPrivateKey: () => Uint8Array;
@@ -88,8 +98,16 @@ export type CurveFn = {
// It is not generic twisted curve for now, but ed25519/ed448 generic implementation
export function twistedEdwards(curveDef: CurveType): CurveFn {
const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;
const { Fp, n: CURVE_ORDER, preHash, hash: cHash, randomBytes, nByteLength, h: cofactor } = CURVE;
const MASK = _2n ** BigInt(nByteLength * 8);
const {
Fp,
n: CURVE_ORDER,
prehash: prehash,
hash: cHash,
randomBytes,
nByteLength,
h: cofactor,
} = CURVE;
const MASK = _2n << (BigInt(nByteLength * 8) - _1n);
const modP = Fp.create; // Function overrides
// sqrt(u/v)
@@ -109,7 +127,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported');
return data;
}); // NOOP
const inBig = (n: bigint) => typeof n === 'bigint' && 0n < n; // n in [1..]
const inBig = (n: bigint) => typeof n === 'bigint' && _0n < n; // n in [1..]
const inRange = (n: bigint, max: bigint) => inBig(n) && inBig(max) && n < max; // n in [1..max-1]
const in0MaskRange = (n: bigint) => n === _0n || inRange(n, MASK); // n in [0..MASK-1]
function assertInRange(n: bigint, max: bigint) {
@@ -297,8 +315,9 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
// 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.
// Does NOT allow scalars higher than CURVE.n.
multiplyUnsafe(scalar: bigint): Point {
let n = assertGE0(scalar);
let n = assertGE0(scalar); // 0 <= scalar < CURVE.n
if (n === _0n) return I;
if (this.equals(I) || n === _1n) return this;
if (this.equals(G)) return this.wNAF(n).p;
@@ -341,10 +360,10 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
// Converts hash string or Uint8Array to Point.
// Uses algo from RFC8032 5.1.3.
static fromHex(hex: Hex, strict = true): Point {
static fromHex(hex: Hex, zip215 = false): Point {
const { d, a } = CURVE;
const len = Fp.BYTES;
hex = ensureBytes(hex, len); // copy hex to a new array
hex = ensureBytes('pointHex', hex, len); // copy hex to a new array
const normed = hex.slice(); // copy again, we'll manipulate it
const lastByte = hex[len - 1]; // select last byte
normed[len - 1] = lastByte & ~0x80; // clear last bit
@@ -353,8 +372,8 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
// y=0 is allowed
} else {
// RFC8032 prohibits >= p, but ZIP215 doesn't
if (strict) assertInRange(y, Fp.ORDER); // strict=true [1..P-1] (2^255-19-1 for ed25519)
else assertInRange(y, MASK); // strict=false [1..MASK-1] (2^256-1 for ed25519)
if (zip215) assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519)
else assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519)
}
// Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:
@@ -365,7 +384,10 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
let { isValid, value: x } = uvRatio(u, v); // √(u/v)
if (!isValid) throw new Error('Point.fromHex: invalid y coordinate');
const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper
const isLastByteOdd = (lastByte & 0x80) !== 0; // if x=0 and x_0 = 1, fail
const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
if (!zip215 && x === _0n && isLastByteOdd)
// if x=0 and x_0 = 1, fail
throw new Error('Point.fromHex: x=0 and x_0=1');
if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x
return Point.fromAffine({ x, y });
}
@@ -392,18 +414,14 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
function modN_LE(hash: Uint8Array): bigint {
return modN(ut.bytesToNumberLE(hash));
}
function isHex(item: Hex, err: string) {
if (typeof item !== 'string' && !(item instanceof Uint8Array))
throw new Error(`${err} must be hex string or Uint8Array`);
}
/** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */
function getExtendedPublicKey(key: Hex) {
isHex(key, 'private key');
const len = nByteLength;
key = ensureBytes('private key', key, len);
// Hash private key with curve's hash function to produce uniformingly random input
// Check byte lengths: ensure(64, h(ensure(32, key)))
const hashed = ensureBytes(cHash(ensureBytes(key, len)), 2 * len);
const hashed = ensureBytes('hashed private key', cHash(key), 2 * len);
const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE
const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)
const scalar = modN_LE(head); // The actual private scalar
@@ -420,35 +438,44 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
// int('LE', SHA512(dom2(F, C) || msgs)) mod N
function hashDomainToScalar(context: Hex = new Uint8Array(), ...msgs: Uint8Array[]) {
const msg = ut.concatBytes(...msgs);
return modN_LE(cHash(domain(msg, ensureBytes(context), !!preHash)));
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash)));
}
/** Signs message with privateKey. RFC8032 5.1.6 */
function sign(msg: Hex, privKey: Hex, context?: Hex): Uint8Array {
isHex(msg, 'message');
msg = ensureBytes(msg);
if (preHash) msg = preHash(msg); // for ed25519ph etc.
function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array {
msg = ensureBytes('message', msg);
if (prehash) msg = prehash(msg); // for ed25519ph etc.
const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const R = G.multiply(r).toRawBytes(); // R = rG
const k = hashDomainToScalar(context, R, pointBytes, msg); // R || A || PH(M)
const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
const s = modN(r + k * scalar); // S = (r + k * s) mod L
assertGE0(s); // 0 <= s < l
const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
return ensureBytes(res, nByteLength * 2); // 64-byte signature
return ensureBytes('result', res, nByteLength * 2); // 64-byte signature
}
function verify(sig: Hex, msg: Hex, publicKey: Hex, context?: Hex): boolean {
isHex(sig, 'sig');
isHex(msg, 'message');
const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT;
function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean {
const { context, zip215 } = options;
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
sig = ensureBytes(sig, 2 * len); // An extended group equation is checked.
msg = ensureBytes(msg); // ZIP215 compliant, which means not fully RFC8032 compliant.
if (preHash) msg = preHash(msg); // for ed25519ph, etc
const A = Point.fromHex(publicKey, false); // Check for s bounds, hex validity
const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)); // 0 <= s < l
const SB = G.multiplyUnsafe(s);
sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
msg = ensureBytes('message', msg);
if (prehash) msg = prehash(msg); // for ed25519ph, etc
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len));
// zip215: true is good for consensus-critical apps and allows points < 2^256
// zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p
let A, R, SB;
try {
A = Point.fromHex(publicKey, zip215);
R = Point.fromHex(sig.slice(0, len), zip215);
SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
} catch (error) {
return false;
}
if (!zip215 && A.isSmallOrder()) return false;
const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);
const RkA = R.add(A.multiplyUnsafe(k));
// [8][S]B = [8]R + [8][k]A'

View File

@@ -1,45 +1,36 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
import { mod, Field } from './modular.js';
import { CHash, Hex, concatBytes, ensureBytes, validateObject } from './utils.js';
import { mod, IField } from './modular.js';
import { bytesToNumberBE, CHash, concatBytes, utf8ToBytes, validateObject } from './utils.js';
/**
* * `DST` is a domain separation tag, defined in section 2.2.5
* * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
* * `m` is extension degree (1 for prime fields)
* * `k` is the target security target in bits (e.g. 128), from section 5.1
* * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF)
* * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
*/
type UnicodeOrBytes = string | Uint8Array;
export type Opts = {
DST: string; // DST: a domain separation tag, defined in section 2.2.5
encodeDST: string;
p: bigint; // characteristic of F, where F is a finite field of characteristic p and order q = p^m
m: number; // extension degree of F, m >= 1
k: number; // k: the target security level for the suite in bits, defined in section 5.1
expand?: 'xmd' | 'xof'; // use a message that has already been processed by expand_message_xmd
// Hash functions for: expand_message_xmd is appropriate for use with a
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
// TODO: verify that hash is shake if expand==='xof' via types
DST: UnicodeOrBytes;
p: bigint;
m: number;
k: number;
expand: 'xmd' | 'xof';
hash: CHash;
};
// Global symbols in both browsers and Node.js since v11
// See https://github.com/microsoft/TypeScript/issues/31535
declare const TextEncoder: any;
declare const TextDecoder: any;
export function stringToBytes(str: string): Uint8Array {
if (typeof str !== 'string') {
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
}
return new TextEncoder().encode(str);
function validateDST(dst: UnicodeOrBytes): Uint8Array {
if (dst instanceof Uint8Array) return dst;
if (typeof dst === 'string') return utf8ToBytes(dst);
throw new Error('DST must be Uint8Array or string');
}
// Octet Stream to Integer (bytesToNumberBE)
function os2ip(bytes: Uint8Array): bigint {
let result = 0n;
for (let i = 0; i < bytes.length; i++) {
result <<= 8n;
result += BigInt(bytes[i]);
}
return result;
}
// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
const os2ip = bytesToNumberBE;
// Integer to Octet Stream
// Integer to Octet Stream (numberToBytesBE)
function i2osp(value: number, length: number): Uint8Array {
if (value < 0 || value >= 1 << (8 * length)) {
throw new Error(`bad I2OSP call: value=${value} length=${length}`);
@@ -60,6 +51,13 @@ function strxor(a: Uint8Array, b: Uint8Array): Uint8Array {
return arr;
}
function isBytes(item: unknown): void {
if (!(item instanceof Uint8Array)) throw new Error('Uint8Array expected');
}
function isNum(item: unknown): void {
if (!Number.isSafeInteger(item)) throw new Error('number expected');
}
// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1
export function expand_message_xmd(
@@ -68,15 +66,17 @@ export function expand_message_xmd(
lenInBytes: number,
H: CHash
): Uint8Array {
isBytes(msg);
isBytes(DST);
isNum(lenInBytes);
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
if (DST.length > 255) DST = H(concatBytes(stringToBytes('H2C-OVERSIZE-DST-'), DST));
const b_in_bytes = H.outputLen;
const r_in_bytes = H.blockLen;
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
const ell = Math.ceil(lenInBytes / b_in_bytes);
if (ell > 255) throw new Error('Invalid xmd length');
const DST_prime = concatBytes(DST, i2osp(DST.length, 1));
const Z_pad = i2osp(0, r_in_bytes);
const l_i_b_str = i2osp(lenInBytes, 2);
const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str
const b = new Array<Uint8Array>(ell);
const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));
b[0] = H(concatBytes(b_0, i2osp(1, 1), DST_prime));
@@ -95,11 +95,14 @@ export function expand_message_xof(
k: number,
H: CHash
): Uint8Array {
isBytes(msg);
isBytes(DST);
isNum(lenInBytes);
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
if (DST.length > 255) {
const dkLen = Math.ceil((2 * k) / 8);
DST = H.create({ dkLen }).update(stringToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
}
if (lenInBytes > 65535 || DST.length > 255)
throw new Error('expand_message_xof: invalid lenInBytes');
@@ -119,36 +122,49 @@ export function expand_message_xof(
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
* @param msg a byte string containing the message to hash
* @param count the number of elements of F to output
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
*/
export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] {
// if options is provided but incomplete, fill any missing fields with the
// value in hftDefaults (ie hash to G2).
const log2p = options.p.toString(2).length;
const L = Math.ceil((log2p + options.k) / 8); // section 5.1 of ietf draft link above
const len_in_bytes = count * options.m * L;
const DST = stringToBytes(options.DST);
let pseudo_random_bytes = msg;
if (options.expand === 'xmd') {
pseudo_random_bytes = expand_message_xmd(msg, DST, len_in_bytes, options.hash);
} else if (options.expand === 'xof') {
pseudo_random_bytes = expand_message_xof(msg, DST, len_in_bytes, options.k, options.hash);
validateObject(options, {
DST: 'string',
p: 'bigint',
m: 'isSafeInteger',
k: 'isSafeInteger',
hash: 'hash',
});
const { p, k, m, hash, expand, DST: _DST } = options;
isBytes(msg);
isNum(count);
const DST = validateDST(_DST);
const log2p = p.toString(2).length;
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
const len_in_bytes = count * m * L;
let prb; // pseudo_random_bytes
if (expand === 'xmd') {
prb = expand_message_xmd(msg, DST, len_in_bytes, hash);
} else if (expand === 'xof') {
prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);
} else if (expand === '_internal_pass') {
// for internal tests only
prb = msg;
} else {
throw new Error('expand must be "xmd" or "xof"');
}
const u = new Array(count);
for (let i = 0; i < count; i++) {
const e = new Array(options.m);
for (let j = 0; j < options.m; j++) {
const elm_offset = L * (j + i * options.m);
const tv = pseudo_random_bytes.subarray(elm_offset, elm_offset + L);
e[j] = mod(os2ip(tv), options.p);
const e = new Array(m);
for (let j = 0; j < m; j++) {
const elm_offset = L * (j + i * m);
const tv = prb.subarray(elm_offset, elm_offset + L);
e[j] = mod(os2ip(tv), p);
}
u[i] = e;
}
return u;
}
export function isogenyMap<T, F extends Field<T>>(field: F, map: [T[], T[], T[], T[]]) {
export function isogenyMap<T, F extends IField<T>>(field: F, map: [T[], T[], T[], T[]]) {
// Make same order as in spec
const COEFF = map.map((i) => Array.from(i).reverse());
return (x: T, y: T) => {
@@ -176,42 +192,28 @@ export type MapToCurve<T> = (scalar: bigint[]) => AffinePoint<T>;
// Separated from initialization opts, so users won't accidentally change per-curve parameters
// (changing DST is ok!)
export type htfBasicOpts = { DST: string };
export type htfBasicOpts = { DST: UnicodeOrBytes };
export function hashToCurve<T>(
export function createHasher<T>(
Point: H2CPointConstructor<T>,
mapToCurve: MapToCurve<T>,
def: Opts
def: Opts & { encodeDST?: UnicodeOrBytes }
) {
validateObject(def, {
DST: 'string',
p: 'bigint',
m: 'isSafeInteger',
k: 'isSafeInteger',
hash: 'hash',
});
if (def.expand !== 'xmd' && def.expand !== 'xof' && def.expand !== undefined)
throw new Error('Invalid htf/expand');
if (typeof mapToCurve !== 'function')
throw new Error('hashToCurve: mapToCurve() has not been defined');
if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined');
return {
// Encodes byte string to elliptic curve
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
hashToCurve(msg: Hex, options?: htfBasicOpts) {
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
msg = ensureBytes(msg);
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
hashToCurve(msg: Uint8Array, options?: htfBasicOpts) {
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
const P = Point.fromAffine(mapToCurve(u[0]))
.add(Point.fromAffine(mapToCurve(u[1])))
.clearCofactor();
const u0 = Point.fromAffine(mapToCurve(u[0]));
const u1 = Point.fromAffine(mapToCurve(u[1]));
const P = u0.add(u1).clearCofactor();
P.assertValidity();
return P;
},
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
encodeToCurve(msg: Hex, options?: htfBasicOpts) {
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
msg = ensureBytes(msg);
encodeToCurve(msg: Uint8Array, options?: htfBasicOpts) {
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
P.assertValidity();

View File

@@ -22,10 +22,10 @@ export function mod(a: bigint, b: bigint): bigint {
return result >= _0n ? result : b + result;
}
/**
* Efficiently exponentiate num to power and do modular division.
* Efficiently raise num to power and do modular division.
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
* @example
* powMod(2n, 6n, 11n) // 64n % 11n == 9n
* pow(2n, 6n, 11n) // 64n % 11n == 9n
*/
// TODO: use field version && remove
export function pow(num: bigint, power: bigint, modulo: bigint): bigint {
@@ -55,7 +55,8 @@ export function invert(number: bigint, modulo: bigint): bigint {
if (number === _0n || modulo <= _0n) {
throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
}
// Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
// Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
let a = mod(number, modulo);
let b = modulo;
// prettier-ignore
@@ -96,7 +97,7 @@ export function tonelliShanks(P: bigint) {
// Fast-path
if (S === 1) {
const p1div4 = (P + _1n) / _4n;
return function tonelliFast<T>(Fp: Field<T>, n: T) {
return function tonelliFast<T>(Fp: IField<T>, n: T) {
const root = Fp.pow(n, p1div4);
if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root');
return root;
@@ -105,7 +106,7 @@ export function tonelliShanks(P: bigint) {
// Slow-path
const Q1div2 = (Q + _1n) / _2n;
return function tonelliSlow<T>(Fp: Field<T>, n: T): T {
return function tonelliSlow<T>(Fp: IField<T>, n: T): T {
// Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1
if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root');
let r = S;
@@ -145,7 +146,7 @@ export function FpSqrt(P: bigint) {
// 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
// const NUM = 72057594037927816n;
const p1div4 = (P + _1n) / _4n;
return function sqrt3mod4<T>(Fp: Field<T>, n: T) {
return function sqrt3mod4<T>(Fp: IField<T>, n: T) {
const root = Fp.pow(n, p1div4);
// Throw if root**2 != n
if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root');
@@ -156,7 +157,7 @@ export function FpSqrt(P: bigint) {
// Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)
if (P % _8n === _5n) {
const c1 = (P - _5n) / _8n;
return function sqrt5mod8<T>(Fp: Field<T>, n: T) {
return function sqrt5mod8<T>(Fp: IField<T>, n: T) {
const n2 = Fp.mul(n, _2n);
const v = Fp.pow(n2, c1);
const nv = Fp.mul(n, v);
@@ -197,12 +198,8 @@ export function FpSqrt(P: bigint) {
// Little-endian check for first LE bit (last BE bit);
export const isNegativeLE = (num: bigint, modulo: bigint) => (mod(num, modulo) & _1n) === _1n;
// Currently completly inconsistent naming:
// - readable: add, mul, sqr, sqrt, inv, div, pow, eq, sub
// - unreadable mess: addition, multiply, square, squareRoot, inversion, divide, power, equals, subtract
// Field is not always over prime, Fp2 for example has ORDER(q)=p^m
export interface Field<T> {
export interface IField<T> {
ORDER: bigint;
BYTES: number;
BITS: number;
@@ -248,7 +245,7 @@ const FIELD_FIELDS = [
'eql', 'add', 'sub', 'mul', 'pow', 'div',
'addN', 'subN', 'mulN', 'sqrN'
] as const;
export function validateField<T>(field: Field<T>) {
export function validateField<T>(field: IField<T>) {
const initial = {
ORDER: 'bigint',
MASK: 'bigint',
@@ -263,7 +260,7 @@ export function validateField<T>(field: Field<T>) {
}
// Generic field functions
export function FpPow<T>(f: Field<T>, num: T, power: bigint): T {
export function FpPow<T>(f: IField<T>, num: T, power: bigint): T {
// Should have same speed as pow for bigints
// TODO: benchmark!
if (power < _0n) throw new Error('Expected power > 0');
@@ -274,12 +271,13 @@ export function FpPow<T>(f: Field<T>, num: T, power: bigint): T {
while (power > _0n) {
if (power & _1n) p = f.mul(p, d);
d = f.sqr(d);
power >>= 1n;
power >>= _1n;
}
return p;
}
export function FpInvertBatch<T>(f: Field<T>, nums: T[]): T[] {
// 0 is non-invertible: non-batched version will throw on 0
export function FpInvertBatch<T>(f: IField<T>, nums: T[]): T[] {
const tmp = new Array(nums.length);
// Walk from first to last, multiply them by each other MOD p
const lastMultiplied = nums.reduce((acc, num, i) => {
@@ -298,12 +296,12 @@ export function FpInvertBatch<T>(f: Field<T>, nums: T[]): T[] {
return tmp;
}
export function FpDiv<T>(f: Field<T>, lhs: T, rhs: T | bigint): T {
export function FpDiv<T>(f: IField<T>, lhs: T, rhs: T | bigint): T {
return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs));
}
// This function returns True whenever the value x is a square in the field F.
export function FpIsSquare<T>(f: Field<T>) {
export function FpIsSquare<T>(f: IField<T>) {
const legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic
return (x: T): boolean => {
const p = f.pow(x, legendreConst);
@@ -319,16 +317,24 @@ export function nLength(n: bigint, nBitLength?: number) {
return { nBitLength: _nBitLength, nByteLength };
}
// NOTE: very fragile, always bench. Major performance points:
// - NonNormalized ops
// - Object.freeze
// - same shape of object (don't add/remove keys)
type FpField = Field<bigint> & Required<Pick<Field<bigint>, 'isOdd'>>;
export function Fp(
type FpField = IField<bigint> & Required<Pick<IField<bigint>, 'isOdd'>>;
/**
* Initializes a galois field over prime. Non-primes are not supported for now.
* Do not init in loop: slow. Very fragile: always run a benchmark on change.
* Major performance gains:
* a) non-normalized operations like mulN instead of mul
* b) `Object.freeze`
* c) Same object shape: never add or remove keys
* @param ORDER prime positive bigint
* @param bitLen how many bits the field consumes
* @param isLE (def: false) if encoding / decoding should be in little-endian
* @param redef optional faster redefinitions of sqrt and other methods
*/
export function Field(
ORDER: bigint,
bitLen?: number,
isLE = false,
redef: Partial<Field<bigint>> = {}
redef: Partial<IField<bigint>> = {}
): Readonly<FpField> {
if (ORDER <= _0n) throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);
@@ -381,13 +387,13 @@ export function Fp(
return Object.freeze(f);
}
export function FpSqrtOdd<T>(Fp: Field<T>, elm: T) {
export function FpSqrtOdd<T>(Fp: IField<T>, elm: T) {
if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`);
const root = Fp.sqrt(elm);
return Fp.isOdd(root) ? root : Fp.neg(root);
}
export function FpSqrtEven<T>(Fp: Field<T>, elm: T) {
export function FpSqrtEven<T>(Fp: IField<T>, elm: T) {
if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`);
const root = Fp.sqrt(elm);
return Fp.isOdd(root) ? Fp.neg(root) : root;
@@ -396,10 +402,12 @@ export function FpSqrtEven<T>(Fp: Field<T>, elm: T) {
/**
* FIPS 186 B.4.1-compliant "constant-time" private key generation utility.
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
* and convert them into private scalar, with the modulo bias being neglible.
* and convert them into private scalar, with the modulo bias being negligible.
* Needs at least 40 bytes of input for 32-byte private key.
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
* @param hash hash output from SHA3 or a similar function
* @param groupOrder size of subgroup - (e.g. curveFn.CURVE.n)
* @param isLE interpret hash bytes as LE num
* @returns valid private scalar
*/
export function hashToPrivateScalar(
@@ -407,7 +415,7 @@ export function hashToPrivateScalar(
groupOrder: bigint,
isLE = false
): bigint {
hash = ensureBytes(hash);
hash = ensureBytes('privateHash', hash);
const hashLen = hash.length;
const minLen = nLength(groupOrder).nByteLength + 8;
if (minLen < 24 || hashLen < minLen || hashLen > 1024)

View File

@@ -11,25 +11,27 @@ export type CurveType = {
nByteLength: number;
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
a24: bigint; // Related to d, but cannot be derived from it
a: bigint;
montgomeryBits: number;
powPminus2?: (x: bigint) => bigint;
xyToU?: (x: bigint, y: bigint) => bigint;
Gu: string;
Gu: bigint;
randomBytes?: (bytesLength?: number) => Uint8Array;
};
export type CurveFn = {
scalarMult: (scalar: Hex, u: Hex) => Uint8Array;
scalarMultBase: (scalar: Hex) => Uint8Array;
getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array;
getPublicKey: (privateKey: Hex) => Uint8Array;
Gu: string;
utils: { randomPrivateKey: () => Uint8Array };
GuBytes: Uint8Array;
};
function validateOpts(curve: CurveType) {
validateObject(
curve,
{
a24: 'bigint',
a: 'bigint',
},
{
montgomeryBits: 'isSafeInteger',
@@ -37,7 +39,7 @@ function validateOpts(curve: CurveType) {
adjustScalarBytes: 'function',
domain: 'function',
powPminus2: 'function',
Gu: 'string',
Gu: 'bigint',
}
);
// Set defaults
@@ -49,7 +51,7 @@ function validateOpts(curve: CurveType) {
export function montgomery(curveDef: CurveType): CurveFn {
const CURVE = validateOpts(curveDef);
const { P } = CURVE;
const modP = (a: bigint) => mod(a, P);
const modP = (n: bigint) => mod(n, P);
const montgomeryBits = CURVE.montgomeryBits;
const montgomeryBytes = Math.ceil(montgomeryBits / 8);
const fieldLen = CURVE.nByteLength;
@@ -73,12 +75,15 @@ export function montgomery(curveDef: CurveType): CurveFn {
return [x_2, x_3];
}
// Accepts 0 as well
function assertFieldElement(n: bigint): bigint {
if (typeof n === 'bigint' && _0n <= n && n < P) return n;
throw new Error('Expected valid scalar 0 < scalar < CURVE.P');
}
// x25519 from 4
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
const a24 = (CURVE.a - BigInt(2)) / BigInt(4);
/**
*
* @param pointU u coordinate (x) on Montgomery Curve 25519
@@ -90,8 +95,6 @@ export function montgomery(curveDef: CurveType): CurveFn {
// Section 5: Implementations MUST accept non-canonical values and process them as
// if they had been reduced modulo the field prime.
const k = assertFieldElement(scalar);
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
const a24 = CURVE.a24;
const x_1 = u;
let x_2 = _1n;
let z_2 = _0n;
@@ -149,13 +152,13 @@ export function montgomery(curveDef: CurveType): CurveFn {
// MUST mask the most significant bit in the final byte.
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = ensureBytes(uEnc, montgomeryBytes);
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
return bytesToNumberLE(u);
}
function decodeScalar(n: Hex): bigint {
const bytes = ensureBytes(n);
const bytes = ensureBytes('scalar', n);
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
return bytesToNumberLE(adjustScalarBytes(bytes));
@@ -170,8 +173,9 @@ export function montgomery(curveDef: CurveType): CurveFn {
return encodeUCoordinate(pu);
}
// Computes public key from private. By doing scalar multiplication of base point.
const GuBytes = encodeUCoordinate(CURVE.Gu);
function scalarMultBase(scalar: Hex): Uint8Array {
return scalarMult(scalar, CURVE.Gu);
return scalarMult(scalar, GuBytes);
}
return {
@@ -179,6 +183,7 @@ export function montgomery(curveDef: CurveType): CurveFn {
scalarMultBase,
getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey),
getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey),
Gu: CURVE.Gu,
utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) },
GuBytes: GuBytes,
};
}

View File

@@ -1,10 +1,10 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Poseidon Hash: https://eprint.iacr.org/2019/458.pdf, https://www.poseidon-hash.info
import { Field, FpPow, validateField } from './modular.js';
import { IField, FpPow, validateField } from './modular.js';
// We don't provide any constants, since different implementations use different constants.
// For reference constants see './test/poseidon.test.js'.
export type PoseidonOpts = {
Fp: Field<bigint>;
Fp: IField<bigint>;
t: number;
roundsFull: number;
roundsPartial: number;

View File

@@ -1,13 +1,14 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// 100 lines of code in the file are duplicated from noble-hashes (utils).
// This is OK: `abstract` directory does not use noble-hashes.
// User may opt-in into using different hashing library. This way, noble-hashes
// won't be included into their bundle.
const _0n = BigInt(0);
const _1n = BigInt(1);
const _2n = BigInt(2);
const u8a = (a: any): a is Uint8Array => a instanceof Uint8Array;
// We accept hex strings besides Uint8Array for simplicity
export type Hex = Uint8Array | string;
// Very few implementations accept numbers, we do it to ease learning curve
export type PrivKey = Hex | bigint;
export type Hex = Uint8Array | string; // hex strings are accepted for simplicity
export type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve
export type CHash = {
(message: Uint8Array | string): Uint8Array;
blockLen: number;
@@ -17,6 +18,9 @@ export type CHash = {
export type FHash = (message: Uint8Array | string) => Uint8Array;
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
/**
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/
export function bytesToHex(bytes: Uint8Array): string {
if (!u8a(bytes)) throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x
@@ -33,27 +37,30 @@ export function numberToHexUnpadded(num: number | bigint): string {
}
export function hexToNumber(hex: string): bigint {
if (typeof hex !== 'string') throw new Error('string expected, got ' + typeof hex);
if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
// Big Endian
return BigInt(hex === '' ? '0' : `0x${hex}`);
}
// Caching slows it down 2-3x
/**
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
*/
export function hexToBytes(hex: string): Uint8Array {
if (typeof hex !== 'string') throw new Error('string expected, got ' + typeof hex);
if (hex.length % 2) throw new Error('hex string is invalid: unpadded ' + hex.length);
const array = new Uint8Array(hex.length / 2);
if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
const len = hex.length;
if (len % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + len);
const array = new Uint8Array(len / 2);
for (let i = 0; i < array.length; i++) {
const j = i * 2;
const hexByte = hex.slice(j, j + 2);
const byte = Number.parseInt(hexByte, 16);
if (Number.isNaN(byte) || byte < 0) throw new Error('invalid byte sequence');
if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence');
array[i] = byte;
}
return array;
}
// Big Endian
// BE: Big Endian, LE: Little Endian
export function bytesToNumberBE(bytes: Uint8Array): bigint {
return hexToNumber(bytesToHex(bytes));
}
@@ -62,26 +69,54 @@ export function bytesToNumberLE(bytes: Uint8Array): bigint {
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
}
export const numberToBytesBE = (n: bigint, len: number) =>
hexToBytes(n.toString(16).padStart(len * 2, '0'));
export const numberToBytesLE = (n: bigint, len: number) => numberToBytesBE(n, len).reverse();
// Returns variable number bytes (minimal bigint encoding?)
export const numberToVarBytesBE = (n: bigint) => hexToBytes(numberToHexUnpadded(n));
export function ensureBytes(hex: Hex, expectedLength?: number): Uint8Array {
// Uint8Array.from() instead of hash.slice() because node.js Buffer
// is instance of Uint8Array, and its slice() creates **mutable** copy
const bytes = u8a(hex) ? Uint8Array.from(hex) : hexToBytes(hex);
if (typeof expectedLength === 'number' && bytes.length !== expectedLength)
throw new Error(`Expected ${expectedLength} bytes`);
return bytes;
export function numberToBytesBE(n: number | bigint, len: number): Uint8Array {
return hexToBytes(n.toString(16).padStart(len * 2, '0'));
}
export function numberToBytesLE(n: number | bigint, len: number): Uint8Array {
return numberToBytesBE(n, len).reverse();
}
// Unpadded, rarely used
export function numberToVarBytesBE(n: number | bigint): Uint8Array {
return hexToBytes(numberToHexUnpadded(n));
}
// Copies several Uint8Arrays into one.
export function concatBytes(...arrs: Uint8Array[]): Uint8Array {
const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));
/**
* Takes hex string or Uint8Array, converts to Uint8Array.
* Validates output length.
* Will throw error for other types.
* @param title descriptive title for an error e.g. 'private key'
* @param hex hex string or Uint8Array
* @param expectedLength optional, will compare to result array's length
* @returns
*/
export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array {
let res: Uint8Array;
if (typeof hex === 'string') {
try {
res = hexToBytes(hex);
} catch (e) {
throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
}
} else if (u8a(hex)) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer
// is instance of Uint8Array, and its slice() creates **mutable** copy
res = Uint8Array.from(hex);
} else {
throw new Error(`${title} must be hex string or Uint8Array`);
}
const len = res.length;
if (typeof expectedLength === 'number' && len !== expectedLength)
throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
return res;
}
/**
* Copies several Uint8Arrays into one.
*/
export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
let pad = 0; // walk through each item, ensure they have proper type
arrs.forEach((a) => {
arrays.forEach((a) => {
if (!u8a(a)) throw new Error('Uint8Array expected');
r.set(a, pad);
pad += a.length;
@@ -96,24 +131,116 @@ export function equalBytes(b1: Uint8Array, b2: Uint8Array) {
return true;
}
// Global symbols in both browsers and Node.js since v11
// See https://github.com/microsoft/TypeScript/issues/31535
declare const TextEncoder: any;
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
export function utf8ToBytes(str: string): Uint8Array {
if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
}
// Bit operations
// Amount of bits inside bigint (Same as n.toString(2).length)
/**
* Calculates amount of bits in a bigint.
* Same as `n.toString(2).length`
*/
export function bitLen(n: bigint) {
let len;
for (len = 0; n > 0n; n >>= _1n, len += 1);
for (len = 0; n > _0n; n >>= _1n, len += 1);
return len;
}
// Gets single bit at position. NOTE: first bit position is 0 (same as arrays)
// Same as !!+Array.from(n.toString(2)).reverse()[pos]
export const bitGet = (n: bigint, pos: number) => (n >> BigInt(pos)) & 1n;
// Sets single bit at position
export const bitSet = (n: bigint, pos: number, value: boolean) =>
n | ((value ? _1n : _0n) << BigInt(pos));
// Return mask for N bits (Same as BigInt(`0b${Array(i).fill('1').join('')}`))
// Not using ** operator with bigints for old engines.
/**
* Gets single bit at position.
* NOTE: first bit position is 0 (same as arrays)
* Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
*/
export function bitGet(n: bigint, pos: number) {
return (n >> BigInt(pos)) & _1n;
}
/**
* Sets single bit at position.
*/
export const bitSet = (n: bigint, pos: number, value: boolean) => {
return n | ((value ? _1n : _0n) << BigInt(pos));
};
/**
* Calculate mask for N bits. Not using ** operator with bigints because of old engines.
* Same as BigInt(`0b${Array(i).fill('1').join('')}`)
*/
export const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;
// DRBG
const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array
const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut
type Pred<T> = (v: Uint8Array) => T | undefined;
/**
* Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
* @returns function that will call DRBG until 2nd arg returns something meaningful
* @example
* const drbg = createHmacDRBG<Key>(32, 32, hmac);
* drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
*/
export function createHmacDrbg<T>(
hashLen: number,
qByteLen: number,
hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array
): (seed: Uint8Array, predicate: Pred<T>) => T {
if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');
if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');
if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
let i = 0; // Iterations counter, will throw when over 1000
const reset = () => {
v.fill(1);
k.fill(0);
i = 0;
};
const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
const reseed = (seed = u8n()) => {
// HMAC-DRBG reseed() function. Steps D-G
k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)
v = h(); // v = hmac(k || v)
if (seed.length === 0) return;
k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)
v = h(); // v = hmac(k || v)
};
const gen = () => {
// HMAC-DRBG generate() function
if (i++ >= 1000) throw new Error('drbg: tried 1000 values');
let len = 0;
const out: Uint8Array[] = [];
while (len < qByteLen) {
v = h();
const sl = v.slice();
out.push(sl);
len += v.length;
}
return concatBytes(...out);
};
const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {
reset();
reseed(seed); // Steps D-G
let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
while (!(res = pred(gen()))) reseed();
reset();
return res;
};
return genUntil;
}
// Validating curves and fields
const validatorFns = {
bigint: (val: any) => typeof val === 'bigint',
function: (val: any) => typeof val === 'function',

View File

@@ -58,10 +58,9 @@ export interface ProjPointType<T> extends Group<ProjPointType<T>> {
readonly px: T;
readonly py: T;
readonly pz: T;
get x(): T;
get y(): T;
multiply(scalar: bigint): ProjPointType<T>;
multiplyUnsafe(scalar: bigint): ProjPointType<T>;
multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
_setWindowSize(windowSize: number): void;
toAffine(iz?: T): AffinePoint<T>;
isTorsionFree(): boolean;
clearCofactor(): ProjPointType<T>;
@@ -69,6 +68,10 @@ export interface ProjPointType<T> extends Group<ProjPointType<T>> {
hasEvenY(): boolean;
toRawBytes(isCompressed?: boolean): Uint8Array;
toHex(isCompressed?: boolean): string;
multiplyUnsafe(scalar: bigint): ProjPointType<T>;
multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
_setWindowSize(windowSize: number): void;
}
// Static methods for 3d XYZ points
export interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
@@ -81,8 +84,8 @@ export interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
export type CurvePointsType<T> = BasicWCurve<T> & {
// Bytes
fromBytes: (bytes: Uint8Array) => AffinePoint<T>;
toBytes: (c: ProjConstructor<T>, point: ProjPointType<T>, compressed: boolean) => Uint8Array;
fromBytes?: (bytes: Uint8Array) => AffinePoint<T>;
toBytes?: (c: ProjConstructor<T>, point: ProjPointType<T>, isCompressed: boolean) => Uint8Array;
};
function validatePointOpts<T>(curve: CurvePointsType<T>) {
@@ -92,8 +95,6 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
{
a: 'field',
b: 'field',
fromBytes: 'function',
toBytes: 'function',
},
{
allowedPrivateKeyLengths: 'array',
@@ -101,6 +102,8 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
isTorsionFree: 'function',
clearCofactor: 'function',
allowInfinityPoint: 'boolean',
fromBytes: 'function',
toBytes: 'function',
}
);
const { endo, Fp, a } = opts;
@@ -121,14 +124,14 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
export type CurvePointsRes<T> = {
ProjectivePoint: ProjConstructor<T>;
normalizePrivateKey: (key: PrivKey) => bigint;
normPrivateKeyToScalar: (key: PrivKey) => bigint;
weierstrassEquation: (x: T) => T;
isWithinCurveOrder: (num: bigint) => boolean;
};
// ASN.1 DER encoding utilities
const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
const DER = {
export const DER = {
// asn.1 DER encoding utils
Err: class DERErr extends Error {
constructor(m = '') {
@@ -141,9 +144,13 @@ const DER = {
const len = data[1];
const res = data.subarray(2, len + 2);
if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length');
if (res[0] === 0x00 && res[1] <= 0x7f)
throw new E('Invalid signature integer: trailing length');
// ^ Weird condition: not about length, but about first bytes of number.
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
// since we always use positive integers here. It must always be empty:
// - add zero byte if exists
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative');
if (res[0] === 0x00 && !(res[1] & 0b10000000))
throw new E('Invalid signature integer: unnecessary leading zero');
return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left
},
toSig(hex: string | Uint8Array): { r: bigint; s: bigint } {
@@ -160,7 +167,8 @@ const DER = {
return { r, s };
},
hexFromSig(sig: { r: bigint; s: bigint }): string {
const slice = (s: string): string => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER
// Add leading zero if first byte has negative bit enabled. More details in '_parseInt'
const slice = (s: string): string => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
const h = (num: number | bigint) => {
const hex = num.toString(16);
return hex.length & 1 ? `0${hex}` : hex;
@@ -175,14 +183,31 @@ const DER = {
},
};
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
const _0n = BigInt(0);
const _1n = BigInt(1);
// Be friendly to bad ECMAScript parsers by not using bigint literals
// prettier-ignore
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
const CURVE = validatePointOpts(opts);
const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
const toBytes =
CURVE.toBytes ||
((c: ProjConstructor<T>, point: ProjPointType<T>, isCompressed: boolean) => {
const a = point.toAffine();
return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
});
const fromBytes =
CURVE.fromBytes ||
((bytes: Uint8Array) => {
// const head = bytes[0];
const tail = bytes.subarray(1);
// if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');
const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
return { x, y };
});
/**
* y² = x³ + ax + b: Short weierstrass curve formula
* @returns y²
@@ -193,6 +218,12 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
const x3 = Fp.mul(x2, x); // x2 * x
return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
}
// Validate whether the passed curve params are valid.
// We check if curve equation works for generator point.
// `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
// ProjectivePoint class has not been initialized yet.
if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error('bad generator point: equation left != right');
// Valid group elements reside in range 1..n-1
function isWithinCurveOrder(num: bigint): boolean {
@@ -202,8 +233,8 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
if (!isWithinCurveOrder(num)) throw new Error('Expected valid bigint: 0 < bigint < curve.n');
}
// Validates if priv key is valid and converts it to bigint.
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
function normalizePrivateKey(key: PrivKey): bigint {
// Supports options allowedPrivateKeyLengths and wrapPrivateKey.
function normPrivateKeyToScalar(key: PrivKey): bigint {
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array) key = ut.bytesToHex(key);
@@ -213,7 +244,10 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
}
let num: bigint;
try {
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE(ensureBytes(key, nByteLength));
num =
typeof key === 'bigint'
? key
: ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength));
} catch (error) {
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
}
@@ -276,14 +310,14 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
* @param hex short/long ECDSA hex
*/
static fromHex(hex: Hex): Point {
const P = Point.fromAffine(CURVE.fromBytes(ensureBytes(hex)));
const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));
P.assertValidity();
return P;
}
// Multiplies generator point by privateKey.
static fromPrivateKey(privateKey: PrivKey) {
return Point.BASE.multiply(normalizePrivateKey(privateKey));
return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
}
// We calculate precomputes for elliptic curve point multiplication
@@ -344,7 +378,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
double() {
const { a, b } = CURVE;
const b3 = Fp.mul(b, 3n);
const b3 = Fp.mul(b, _3n);
const { px: X1, py: Y1, pz: Z1 } = this;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
let t0 = Fp.mul(X1, X1); // step 1
@@ -391,7 +425,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
const { px: X2, py: Y2, pz: Z2 } = other;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
const a = CURVE.a;
const b3 = Fp.mul(CURVE.b, 3n);
const b3 = Fp.mul(CURVE.b, _3n);
let t0 = Fp.mul(X1, X2); // step 1
let t1 = Fp.mul(Y1, Y2);
let t2 = Fp.mul(Z1, Z2);
@@ -484,8 +518,9 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
* Constant time multiplication.
* Uses wNAF method. Windowed method may be 10% faster,
* but takes 2x longer to generate and consumes 2x memory.
* Uses precomputes when available.
* Uses endomorphism for Koblitz curves.
* @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: bigint): Point {
@@ -513,6 +548,8 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
/**
* Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
* Not using Strauss-Shamir trick: precomputation tables are faster.
* The trick could be useful if both P and Q are not G (not in our case).
* @returns non-zero affine point
*/
multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined {
@@ -556,7 +593,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
toRawBytes(isCompressed = true): Uint8Array {
this.assertValidity();
return CURVE.toBytes(Point, this, isCompressed);
return toBytes(Point, this, isCompressed);
}
toHex(isCompressed = true): string {
@@ -565,10 +602,11 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
}
const _bits = CURVE.nBitLength;
const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
// Validate if generator point is on curve
return {
CURVE,
ProjectivePoint: Point as ProjConstructor<T>,
normalizePrivateKey,
normPrivateKeyToScalar,
weierstrassEquation,
isWithinCurveOrder,
};
@@ -580,7 +618,7 @@ export interface SignatureType {
readonly s: bigint;
readonly recovery?: number;
assertValidity(): void;
addRecoveryBit(recovery: number): SignatureType;
addRecoveryBit(recovery: number): RecoveredSignatureType;
hasHighS(): boolean;
normalizeS(): SignatureType;
recoverPublicKey(msgHash: Hex): ProjPointType<bigint>;
@@ -590,6 +628,9 @@ export interface SignatureType {
toDERRawBytes(isCompressed?: boolean): Uint8Array;
toDERHex(isCompressed?: boolean): string;
}
export type RecoveredSignatureType = SignatureType & {
readonly recovery: number;
};
// Static methods
export type SignatureConstructor = {
new (r: bigint, s: bigint): SignatureType;
@@ -631,75 +672,21 @@ export type CurveFn = {
CURVE: ReturnType<typeof validateOpts>;
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType;
verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean;
ProjectivePoint: ProjConstructor<bigint>;
Signature: SignatureConstructor;
utils: {
_normalizePrivateKey: (key: PrivKey) => bigint;
normPrivateKeyToScalar: (key: PrivKey) => bigint;
isValidPrivateKey(privateKey: PrivKey): boolean;
hashToPrivateKey: (hash: Hex) => Uint8Array;
randomPrivateKey: () => Uint8Array;
precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
};
};
const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array
const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut
// Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
type Pred<T> = (v: Uint8Array) => T | undefined;
function hmacDrbg<T>(
hashLen: number,
qByteLen: number,
hmacFn: HmacFnSync
): (seed: Uint8Array, predicate: Pred<T>) => T {
if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');
if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');
if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
let i = 0; // Iterations counter, will throw when over 1000
const reset = () => {
v.fill(1);
k.fill(0);
i = 0;
};
const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
const reseed = (seed = u8n()) => {
// HMAC-DRBG reseed() function. Steps D-G
k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)
v = h(); // v = hmac(k || v)
if (seed.length === 0) return;
k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)
v = h(); // v = hmac(k || v)
};
const gen = () => {
// HMAC-DRBG generate() function
if (i++ >= 1000) throw new Error('drbg: tried 1000 values');
let len = 0;
const out: Uint8Array[] = [];
while (len < qByteLen) {
v = h();
const sl = v.slice();
out.push(sl);
len += v.length;
}
return ut.concatBytes(...out);
};
const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {
reset();
reseed(seed); // Steps D-G
let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
while (!(res = pred(gen()))) reseed();
reset();
return res;
};
return genUntil;
}
export function weierstrass(curveDef: CurveType): CurveFn {
const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;
const CURVE_ORDER = CURVE.n;
const Fp = CURVE.Fp;
const { Fp, n: CURVE_ORDER } = CURVE;
const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
@@ -715,7 +702,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
const {
ProjectivePoint: Point,
normalizePrivateKey,
normPrivateKeyToScalar,
weierstrassEquation,
isWithinCurveOrder,
} = weierstrassPoints({
@@ -725,7 +712,6 @@ export function weierstrass(curveDef: CurveType): CurveFn {
const x = Fp.toBytes(a.x);
const cat = ut.concatBytes;
if (isCompressed) {
// TODO: hasEvenY
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
} else {
return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
@@ -781,36 +767,33 @@ export function weierstrass(curveDef: CurveType): CurveFn {
// pair (bytes of r, bytes of s)
static fromCompact(hex: Hex) {
const gl = CURVE.nByteLength;
hex = ensureBytes(hex, gl * 2);
return new Signature(slcNum(hex, 0, gl), slcNum(hex, gl, 2 * gl));
const l = CURVE.nByteLength;
hex = ensureBytes('compactSignature', hex, l * 2);
return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
}
// DER encoded ECDSA signature
// https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
static fromDER(hex: Hex) {
if (typeof hex !== 'string' && !(hex instanceof Uint8Array))
throw new Error(`Signature.fromDER: Expected string or Uint8Array`);
const { r, s } = DER.toSig(ensureBytes(hex));
const { r, s } = DER.toSig(ensureBytes('DER', hex));
return new Signature(r, s);
}
assertValidity(): void {
// can use assertGE here
if (!isWithinCurveOrder(this.r)) throw new Error('r must be 0 < r < n');
if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < n');
if (!isWithinCurveOrder(this.r)) throw new Error('r must be 0 < r < CURVE.n');
if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < CURVE.n');
}
addRecoveryBit(recovery: number) {
return new Signature(this.r, this.s, recovery);
addRecoveryBit(recovery: number): RecoveredSignature {
return new Signature(this.r, this.s, recovery) as RecoveredSignature;
}
recoverPublicKey(msgHash: Hex): typeof Point.BASE {
const { n: N } = CURVE; // ECDSA public key recovery secg.org/sec1-v2.pdf 4.1.6
const { r, s, recovery: rec } = this;
const h = bits2int_modN(ensureBytes(msgHash)); // Truncate hash
const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid');
const radj = rec === 2 || rec === 3 ? r + N : r;
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid');
const prefix = (rec & 1) === 0 ? '02' : '03';
const R = Point.fromHex(prefix + numToNByteStr(radj));
@@ -848,41 +831,40 @@ export function weierstrass(curveDef: CurveType): CurveFn {
return numToNByteStr(this.r) + numToNByteStr(this.s);
}
}
type RecoveredSignature = Signature & { recovery: number };
const utils = {
isValidPrivateKey(privateKey: PrivKey) {
try {
normalizePrivateKey(privateKey);
normPrivateKeyToScalar(privateKey);
return true;
} catch (error) {
return false;
}
},
_normalizePrivateKey: normalizePrivateKey,
/**
* Converts some bytes to a valid private key. Needs at least (nBitLength+64) bytes.
*/
hashToPrivateKey: (hash: Hex): Uint8Array =>
ut.numberToBytesBE(mod.hashToPrivateScalar(hash, CURVE_ORDER), CURVE.nByteLength),
normPrivateKeyToScalar: normPrivateKeyToScalar,
/**
* Produces cryptographically secure private key from random of size (nBitLength+64)
* as per FIPS 186 B.4.1 with modulo bias being neglible.
*/
randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(CURVE.randomBytes(Fp.BYTES + 8)),
randomPrivateKey: (): Uint8Array => {
const rand = CURVE.randomBytes(Fp.BYTES + 8);
const num = mod.hashToPrivateScalar(rand, CURVE_ORDER);
return ut.numberToBytesBE(num, CURVE.nByteLength);
},
/**
* 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
* Creates precompute table for an arbitrary EC point. Makes point "cached".
* Allows to massively speed-up `point.multiply(scalar)`.
* @returns cached point
* @example
* const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
* fast.multiply(privKey); // much faster ECDH now
*/
precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE {
point._setWindowSize(windowSize);
point.multiply(BigInt(3));
point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
return point;
},
};
@@ -913,7 +895,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
/**
* ECDH (Elliptic Curve Diffie Hellman).
* Computes shared public key from private key and public key.
* Checks: 1) private key validity 2) shared key is on-curve
* Checks: 1) private key validity 2) shared key is on-curve.
* Does NOT hash the result.
* @param privateA private key
* @param publicB different public key
* @param isCompressed whether to return compact (default), or full key
@@ -923,7 +906,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
if (isProbPub(privateA)) throw new Error('first arg must be private key');
if (!isProbPub(publicB)) throw new Error('second arg must be public key');
const b = Point.fromHex(publicB); // check for being on-curve
return b.multiply(normalizePrivateKey(privateA)).toRawBytes(isCompressed);
return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
}
// RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
@@ -935,8 +918,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
function (bytes: Uint8Array): bigint {
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
// for some cases, since bytes.length * 8 is not actual bitLength.
const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
const num = ut.bytesToNumberBE(bytes); // check for == u8 done here
const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
return delta > 0 ? num >> BigInt(delta) : num;
};
const bits2int_modN =
@@ -946,10 +929,12 @@ export function weierstrass(curveDef: CurveType): CurveFn {
};
// NOTE: pads output with zero as per spec
const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
/**
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
*/
function int2octets(num: bigint): Uint8Array {
if (typeof num !== 'bigint') throw new Error('bigint expected');
if (!(_0n <= num && num < ORDER_MASK))
// n in [0..ORDER_MASK-1]
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
// works with order, can have different size than numToField!
return ut.numberToBytesBE(num, CURVE.nByteLength);
@@ -961,31 +946,30 @@ export function weierstrass(curveDef: CurveType): CurveFn {
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
// Also it can be bigger for P224 + SHA256
function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {
const { hash, randomBytes } = CURVE;
if (msgHash == null) throw new Error(`sign: expected valid message hash, not "${msgHash}"`);
if (['recovered', 'canonical'].some((k) => k in opts))
// Ban legacy options
throw new Error('sign() legacy options not supported');
const { hash, randomBytes } = CURVE;
let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
if (prehash) msgHash = hash(ensureBytes(msgHash));
if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
msgHash = ensureBytes('msgHash', msgHash);
if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
// We can't later call bits2octets, since nested bits2int is broken for curves
// with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
const h1int = bits2int_modN(ensureBytes(msgHash));
const d = normalizePrivateKey(privateKey); // validate private key, convert to bigint
const h1int = bits2int_modN(msgHash);
const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
const seedArgs = [int2octets(d), int2octets(h1int)];
// extraEntropy. RFC6979 3.6: additional k' (optional).
if (ent != null) {
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
// Either pass as-is, or generate random bytes. Then validate for being ui8a of size BYTES
seedArgs.push(ensureBytes(ent === true ? randomBytes(Fp.BYTES) : ent, Fp.BYTES));
const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
seedArgs.push(ensureBytes('extraEntropy', e, Fp.BYTES)); // check for being of size BYTES
}
const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
// Converts signature params into point w r/s, checks result for validity.
function k2sig(kBytes: Uint8Array): Signature | undefined {
function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined {
// RFC 6979 Section 3.2, step 3: k = bits2int(T)
const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
if (!isWithinCurveOrder(k)) return; // Important: all mod() calls here must be done over N
@@ -993,7 +977,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
const q = Point.BASE.multiply(k).toAffine(); // q = Gk
const r = modN(q.x); // r = q.x mod n
if (r === _0n) return;
const s = modN(ik * modN(m + modN(d * r))); // s = k^-1(m + rd) mod n
// Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q1] according to
// https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
// a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
const s = modN(ik * modN(m + r * d)); // Not using blinding here
if (s === _0n) return;
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
let normS = s;
@@ -1001,7 +988,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
normS = normalizeS(s); // if lowS was passed, ensure s is always
recovery ^= 1; // // in the bottom half of N
}
return new Signature(r, normS, recovery); // use normS, not s
return new Signature(r, normS, recovery) as RecoveredSignature; // use normS, not s
}
return { seed, k2sig };
}
@@ -1009,19 +996,23 @@ export function weierstrass(curveDef: CurveType): CurveFn {
const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false };
/**
* Signs message hash (not message: you need to hash it by yourself).
* Signs message hash with a private key.
* ```
* sign(m, d, k) where
* (x, y) = G × k
* r = x mod n
* s = (m + dr)/k mod n
* ```
* @param opts `lowS, extraEntropy, prehash`
* @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.
* @param privKey private key
* @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.
* @returns signature with recovery param
*/
function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): Signature {
function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature {
const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
const genUntil = hmacDrbg<Signature>(CURVE.hash.outputLen, CURVE.nByteLength, CURVE.hmac);
return genUntil(seed, k2sig); // Steps B, C, D, E, F, G
const C = CURVE;
const drbg = ut.createHmacDrbg<RecoveredSignature>(C.hash.outputLen, C.nByteLength, C.hmac);
return drbg(seed, k2sig); // Steps B, C, D, E, F, G
}
// Enable precomputes. Slows down first publicKey computation by 20ms.
@@ -1047,30 +1038,38 @@ export function weierstrass(curveDef: CurveType): CurveFn {
publicKey: Hex,
opts = defaultVerOpts
): boolean {
let P: ProjPointType<bigint>;
const sg = signature;
msgHash = ensureBytes('msgHash', msgHash);
publicKey = ensureBytes('publicKey', publicKey);
if ('strict' in opts) throw new Error('options.strict was renamed to lowS');
const { lowS, prehash } = opts;
let _sig: Signature | undefined = undefined;
if (publicKey instanceof Point) throw new Error('publicKey must be hex');
let P: ProjPointType<bigint>;
try {
if (signature && typeof signature === 'object' && !(signature instanceof Uint8Array)) {
const { r, s } = signature;
_sig = new Signature(r, s); // assertValidity() is executed on creation
} else {
if (typeof sg === 'string' || sg instanceof Uint8Array) {
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
// Since DER can also be 2*nByteLength bytes, we check for it first.
try {
_sig = Signature.fromDER(signature as Hex);
_sig = Signature.fromDER(sg);
} catch (derError) {
if (!(derError instanceof DER.Err)) throw derError;
_sig = Signature.fromCompact(signature as Hex);
_sig = Signature.fromCompact(sg);
}
} else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {
const { r, s } = sg;
_sig = new Signature(r, s);
} else {
throw new Error('PARSE');
}
msgHash = ensureBytes(msgHash);
P = Point.fromHex(publicKey);
} catch (error) {
if ((error as Error).message === 'PARSE')
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
return false;
}
if (opts.lowS && _sig.hasHighS()) return false;
if (opts.prehash) msgHash = CURVE.hash(msgHash);
if (lowS && _sig.hasHighS()) return false;
if (prehash) msgHash = CURVE.hash(msgHash);
const { r, s } = _sig;
const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
const is = invN(s); // s^-1
@@ -1093,23 +1092,31 @@ export function weierstrass(curveDef: CurveType): CurveFn {
};
}
// Implementation of the Shallue and van de Woestijne method for any Weierstrass curve
// TODO: check if there is a way to merge this with uvRatio in Edwards && move to modular?
// b = True and y = sqrt(u / v) if (u / v) is square in F, and
// b = False and y = sqrt(Z * (u / v)) otherwise.
export function SWUFpSqrtRatio<T>(Fp: mod.Field<T>, Z: T) {
/**
* Implementation of the Shallue and van de Woestijne method for any weierstrass curve.
* TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.
* b = True and y = sqrt(u / v) if (u / v) is square in F, and
* b = False and y = sqrt(Z * (u / v)) otherwise.
* @param Fp
* @param Z
* @returns
*/
export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
// Generic implementation
const q = Fp.ORDER;
let l = 0n;
for (let o = q - 1n; o % 2n === 0n; o /= 2n) l += 1n;
let l = _0n;
for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n;
const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
const c2 = (q - 1n) / 2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
const c3 = (c2 - 1n) / 2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
const c4 = 2n ** c1 - 1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
const c5 = 2n ** (c1 - 1n); // 5. c5 = 2^(c1 - 1) # Integer arithmetic
// We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.
// 2n ** c1 == 2n << (c1-1)
const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);
const _2n_pow_c1 = _2n_pow_c1_1 * _2n;
const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic
const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
const c7 = Fp.pow(Z, (c2 + 1n) / 2n); // 7. c7 = Z^((c2 + 1) / 2)
const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)
let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => {
let tv1 = c6; // 1. tv1 = c6
let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
@@ -1128,8 +1135,9 @@ export function SWUFpSqrtRatio<T>(Fp: mod.Field<T>, Z: T) {
tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
// 17. for i in (c1, c1 - 1, ..., 2):
for (let i = c1; i > 1; i--) {
let tv5 = 2n ** (i - 2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5
for (let i = c1; i > _1n; i--) {
let tv5 = i - _2n; // 18. tv5 = i - 2
tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5
let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
@@ -1140,9 +1148,9 @@ export function SWUFpSqrtRatio<T>(Fp: mod.Field<T>, Z: T) {
}
return { isValid: isQR, value: tv3 };
};
if (Fp.ORDER % 4n === 3n) {
if (Fp.ORDER % _4n === _3n) {
// sqrt_ratio_3mod4(u, v)
const c1 = (Fp.ORDER - 3n) / 4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)
sqrtRatio = (u: T, v: T) => {
let tv1 = Fp.sqr(v); // 1. tv1 = v^2
@@ -1158,12 +1166,14 @@ export function SWUFpSqrtRatio<T>(Fp: mod.Field<T>, Z: T) {
};
}
// No curves uses that
// if (Fp.ORDER % 8n === 5n) // sqrt_ratio_5mod8
// if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8
return sqrtRatio;
}
// From draft-irtf-cfrg-hash-to-curve-16
/**
* From draft-irtf-cfrg-hash-to-curve-16
*/
export function mapToCurveSimpleSWU<T>(
Fp: mod.Field<T>,
Fp: mod.IField<T>,
opts: {
A: T;
B: T;

View File

@@ -1,16 +1,32 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// The pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
// bls12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
// - Construct zk-SNARKs at the 128-bit security
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
// Differences from @noble/bls12-381 1.4:
// - PointG1 -> G1.Point
// - PointG2 -> G2.Point
// - PointG2.fromSignature -> Signature.decode
// - PointG2.toSignature -> Signature.encode
// - Fixed Fp2 ORDER
// - Points now have only two coordinates
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and
// verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
//
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).
//
// ### Summary
// 1. BLS Relies on Bilinear Pairing (expensive)
// 2. Private Keys: 32 bytes
// 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes.
// 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays.
// - The signature is a point on the G2 subgroup, which is defined over a finite field
// with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the complex numbers).
// 5. The 12 stands for the Embedding degree.
//
// ### Formulas
// - `P = pk x G` - public keys
// - `S = pk x H(m)` - signing
// - `e(P, H(m)) == e(G, S)` - verification using pairings
// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
// Filecoin uses little endian byte arrays for private keys -
// so ensure to reverse byte order if you'll use it with FIL.
import { sha256 } from '@noble/hashes/sha256';
import { randomBytes } from '@noble/hashes/utils';
import { bls, CurveFn } from './abstract/bls.js';
@@ -25,6 +41,7 @@ import {
bitGet,
Hex,
bitMask,
bytesToHex,
} from './abstract/utils.js';
// Types
import {
@@ -35,16 +52,22 @@ import {
} from './abstract/weierstrass.js';
import { isogenyMap } from './abstract/hash-to-curve.js';
// Be friendly to bad ECMAScript parsers by not using bigint literals
// prettier-ignore
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
// prettier-ignore
const _8n = BigInt(8), _16n = BigInt(16);
// CURVE FIELDS
// Finite field over p.
const Fp =
mod.Fp(
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn
const Fp_raw = BigInt(
'0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'
);
const Fp = mod.Field(Fp_raw);
type Fp = bigint;
// Finite field over r.
// This particular field is not used anywhere in bls12-381, but it is still useful.
const Fr = mod.Fp(0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n);
const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
// Fp₂ over complex plane
type BigintTuple = [bigint, bigint];
@@ -86,11 +109,9 @@ type Fp2Utils = {
// G² - 1
// h2q
// NOTE: ORDER was wrong!
const FP2_ORDER =
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn **
2n;
const FP2_ORDER = Fp_raw * Fp_raw;
const Fp2: mod.Field<Fp2> & Fp2Utils = {
const Fp2: mod.IField<Fp2> & Fp2Utils = {
ORDER: FP2_ORDER,
BITS: bitLen(FP2_ORDER),
BYTES: Math.ceil(bitLen(FP2_ORDER) / 8),
@@ -141,7 +162,7 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
// https://github.com/zkcrypto/bls12_381/blob/080eaa74ec0e394377caa1ba302c8c121df08b07/src/fp2.rs#L250
// https://github.com/supranational/blst/blob/aae0c7d70b799ac269ff5edf29d8191dbd357876/src/exp2.c#L1
// Inspired by https://github.com/dalek-cryptography/curve25519-dalek/blob/17698df9d4c834204f83a3574143abacb4fc81a5/src/field.rs#L99
const candidateSqrt = Fp2.pow(num, (Fp2.ORDER + 8n) / 16n);
const candidateSqrt = Fp2.pow(num, (Fp2.ORDER + _8n) / _16n);
const check = Fp2.div(Fp2.sqr(candidateSqrt), num); // candidateSqrt.square().div(this);
const R = FP2_ROOTS_OF_UNITY;
const divisor = [R[0], R[2], R[4], R[6]].find((r) => Fp2.eql(r, check));
@@ -159,10 +180,10 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
// Same as sgn0_fp2 in draft-irtf-cfrg-hash-to-curve-16
isOdd: (x: Fp2) => {
const { re: x0, im: x1 } = Fp2.reim(x);
const sign_0 = x0 % 2n;
const zero_0 = x0 === 0n;
const sign_1 = x1 % 2n;
return BigInt(sign_0 || (zero_0 && sign_1)) == 1n;
const sign_0 = x0 % _2n;
const zero_0 = x0 === _0n;
const sign_1 = x1 % _2n;
return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
},
// Bytes util
fromBytes(b: Uint8Array): Fp2 {
@@ -182,8 +203,8 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
// multiply by u + 1
mulByNonresidue: ({ c0, c1 }) => ({ c0: Fp.sub(c0, c1), c1: Fp.add(c0, c1) }),
multiplyByB: ({ c0, c1 }) => {
let t0 = Fp.mul(c0, 4n); // 4 * c0
let t1 = Fp.mul(c1, 4n); // 4 * c1
let t0 = Fp.mul(c0, _4n); // 4 * c0
let t1 = Fp.mul(c1, _4n); // 4 * c1
// (T0-T1) + (T0+T1)*i
return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) };
},
@@ -200,33 +221,36 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
// Finite extension field over irreducible polynominal.
// Fp(u) / (u² - β) where β = -1
const FP2_FROBENIUS_COEFFICIENTS = [
0x1n,
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan,
BigInt('0x1'),
BigInt(
'0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'
),
].map((item) => Fp.create(item));
// For Fp2 roots of unity.
const rv1 =
0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n;
const rv1 = BigInt(
'0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'
);
// const ev1 =
// 0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90n;
// BigInt('0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90');
// const ev2 =
// 0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5n;
// BigInt('0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5');
// const ev3 =
// 0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17n;
// BigInt('0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17');
// const ev4 =
// 0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1n;
// BigInt('0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1');
// Eighth roots of unity, used for computing square roots in Fp2.
// To verify or re-calculate:
// Array(8).fill(new Fp2([1n, 1n])).map((fp2, k) => fp2.pow(Fp2.ORDER * BigInt(k) / 8n))
const FP2_ROOTS_OF_UNITY = [
[1n, 0n],
[_1n, _0n],
[rv1, -rv1],
[0n, 1n],
[_0n, _1n],
[rv1, rv1],
[-1n, 0n],
[-_1n, _0n],
[-rv1, rv1],
[0n, -1n],
[_0n, -_1n],
[-rv1, -rv1],
].map((pair) => Fp2.fromBigTuple(pair));
// eta values, used for computing sqrt(g(X1(t)))
@@ -280,8 +304,8 @@ const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => {
};
const Fp6Square = ({ c0, c1, c2 }: Fp6) => {
let t0 = Fp2.sqr(c0); // c0²
let t1 = Fp2.mul(Fp2.mul(c0, c1), 2n); // 2 * c0 * c1
let t3 = Fp2.mul(Fp2.mul(c1, c2), 2n); // 2 * c1 * c2
let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
let t4 = Fp2.sqr(c2); // c2²
return {
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
@@ -299,7 +323,7 @@ type Fp6Utils = {
multiplyByFp2(lhs: Fp6, rhs: Fp2): Fp6;
};
const Fp6: mod.Field<Fp6> & Fp6Utils = {
const Fp6: mod.IField<Fp6> & Fp6Utils = {
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
BITS: 3 * Fp2.BITS,
BYTES: 3 * Fp2.BYTES,
@@ -406,46 +430,64 @@ const Fp6: mod.Field<Fp6> & Fp6Utils = {
};
const FP6_FROBENIUS_COEFFICIENTS_1 = [
[0x1n, 0x0n],
[BigInt('0x1'), BigInt('0x0')],
[
0x0n,
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn,
BigInt('0x0'),
BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'
),
],
[
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen,
0x0n,
BigInt(
'0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
),
BigInt('0x0'),
],
[0x0n, 0x1n],
[BigInt('0x0'), BigInt('0x1')],
[
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn,
0x0n,
BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'
),
BigInt('0x0'),
],
[
0x0n,
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen,
BigInt('0x0'),
BigInt(
'0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
),
],
].map((pair) => Fp2.fromBigTuple(pair));
const FP6_FROBENIUS_COEFFICIENTS_2 = [
[0x1n, 0x0n],
[BigInt('0x1'), BigInt('0x0')],
[
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaadn,
0x0n,
BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad'
),
BigInt('0x0'),
],
[
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn,
0x0n,
BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'
),
BigInt('0x0'),
],
[
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan,
0x0n,
BigInt(
'0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'
),
BigInt('0x0'),
],
[
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen,
0x0n,
BigInt(
'0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
),
BigInt('0x0'),
],
[
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffffn,
0x0n,
BigInt(
'0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff'
),
BigInt('0x0'),
],
].map((pair) => Fp2.fromBigTuple(pair));
@@ -454,7 +496,7 @@ const FP6_FROBENIUS_COEFFICIENTS_2 = [
// Fp₆(w) / (w² - γ) where γ = v
type Fp12 = { c0: Fp6; c1: Fp6 };
// The BLS parameter x for BLS12-381
const BLS_X = 0xd201000000010000n;
const BLS_X = BigInt('0xd201000000010000');
const BLS_X_LEN = bitLen(BLS_X);
// prettier-ignore
@@ -511,7 +553,7 @@ type Fp12Utils = {
_cyclotomicExp(num: Fp12, n: bigint): Fp12;
};
const Fp12: mod.Field<Fp12> & Fp12Utils = {
const Fp12: mod.IField<Fp12> & Fp12Utils = {
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
BITS: 2 * Fp2.BITS,
BYTES: 2 * Fp2.BYTES,
@@ -612,14 +654,14 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
let t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
return {
c0: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), 2n), t3), // 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), 2n), t5), // 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), 2n), t7),
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
}), // 2 * (T7 - c0c2) + T7
c1: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), 2n), t9), // 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), 2n), t4), // 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), 2n), t6),
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
}),
}; // 2 * (T6 + c1c2) + T6
},
@@ -654,50 +696,84 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
},
};
const FP12_FROBENIUS_COEFFICIENTS = [
[0x1n, 0x0n],
[BigInt('0x1'), BigInt('0x0')],
[
0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8n,
0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3n,
BigInt(
'0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8'
),
BigInt(
'0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3'
),
],
[
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffffn,
0x0n,
BigInt(
'0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff'
),
BigInt('0x0'),
],
[
0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2n,
0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n,
BigInt(
'0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2'
),
BigInt(
'0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'
),
],
[
0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen,
0x0n,
BigInt(
'0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
),
BigInt('0x0'),
],
[
0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995n,
0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116n,
BigInt(
'0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995'
),
BigInt(
'0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116'
),
],
[
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan,
0x0n,
BigInt(
'0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'
),
BigInt('0x0'),
],
[
0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3n,
0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8n,
BigInt(
'0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3'
),
BigInt(
'0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8'
),
],
[
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn,
0x0n,
BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'
),
BigInt('0x0'),
],
[
0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n,
0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2n,
BigInt(
'0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'
),
BigInt(
'0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2'
),
],
[
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaadn,
0x0n,
BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad'
),
BigInt('0x0'),
],
[
0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116n,
0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995n,
BigInt(
'0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116'
),
BigInt(
'0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995'
),
],
].map((n) => Fp2.fromBigTuple(n));
// END OF CURVE FIELDS
@@ -853,19 +929,23 @@ const isogenyMapG1 = isogenyMap(
// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i
const G2_SWU = mapToCurveSimpleSWU(Fp2, {
A: Fp2.create({ c0: Fp.create(0n), c1: Fp.create(240n) }), // A' = 240 * I
B: Fp2.create({ c0: Fp.create(1012n), c1: Fp.create(1012n) }), // B' = 1012 * (1 + I)
Z: Fp2.create({ c0: Fp.create(-2n), c1: Fp.create(-1n) }), // Z: -(2 + I)
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I)
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
});
// Optimized SWU Map - Fp to G1
const G1_SWU = mapToCurveSimpleSWU(Fp, {
A: Fp.create(
0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1dn
BigInt(
'0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d'
)
),
B: Fp.create(
0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0n
BigInt(
'0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0'
)
),
Z: Fp.create(11n),
Z: Fp.create(BigInt(11)),
});
// Endomorphisms (for fast cofactor clearing)
@@ -888,8 +968,9 @@ function G2psi(c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) {
}
// Ψ²(P) endomorphism
// 1 / F2(2)^((p-1)/3) in GF(p²)
const PSI2_C1 =
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn;
const PSI2_C1 = BigInt(
'0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'
);
function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] {
return [Fp2.mul(x, PSI2_C1), Fp2.neg(y)];
@@ -910,7 +991,7 @@ function G2psi2(c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) {
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
// m = 2 (or 1 for G1 see section 8.8.1)
// k = 128
const htfDefaults = {
const htfDefaults = Object.freeze({
// DST: a domain separation tag
// defined in section 2.2.5
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
@@ -932,7 +1013,7 @@ const htfDefaults = {
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
hash: sha256,
} as const;
} as const);
// Encoding utils
// Point on G1 curve: (x, y)
@@ -940,7 +1021,23 @@ const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
// Compressed point of infinity
const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
function signatureG2ToRawBytes(point: ProjPointType<Fp2>) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
const len = Fp.BYTES;
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const { x, y } = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
const aflag1 = Boolean((tmp / Fp.ORDER) & _1n);
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
const z2 = x0;
return concatB(numberToBytesBE(z1, len), numberToBytesBE(z2, len));
}
// To verify curve parameters, see pairing-friendly-curves spec:
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-09
@@ -954,26 +1051,30 @@ const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(0n, I_BIT_POS, true), S_BIT_POS
// Here goes constants && point encoding format
export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// Fields
Fr,
fields: {
Fp,
Fp2,
Fp6,
Fp12,
// order; z⁴ z² + 1
r: Fr.ORDER, // Same as N in other curves
Fr,
},
// G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where
// characteristic; z + (z⁴ - z² + 1)(z - 1)²/3
G1: {
Fp,
// cofactor; (z - 1)²/3
h: 0x396c8c005555e1568c00aaab0000aaabn,
h: BigInt('0x396c8c005555e1568c00aaab0000aaab'),
// generator's coordinates
// x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
// y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
Gx: 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bbn,
Gy: 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1n,
Gx: BigInt(
'0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
),
Gy: BigInt(
'0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'
),
a: Fp.ZERO,
b: 4n,
b: _4n,
htfDefaults: { ...htfDefaults, m: 1 },
wrapPrivateKey: true,
allowInfinityPoint: true,
@@ -983,18 +1084,19 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// https://eprint.iacr.org/2021/1130.pdf
isTorsionFree: (c, point): boolean => {
// φ endomorphism
const cubicRootOfUnityModP =
0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen;
const cubicRootOfUnityModP = BigInt(
'0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
);
const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz);
// todo: unroll
const xP = point.multiplyUnsafe(bls12_381.CURVE.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(bls12_381.CURVE.x); // [u2]P
const xP = point.multiplyUnsafe(bls12_381.params.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(bls12_381.params.x); // [u2]P
return u2P.equals(phi);
// https://eprint.iacr.org/2019/814.pdf
// (z² 1)/3
// const c1 = 0x396c8c005555e1560000000055555555n;
// const c1 = BigInt('0x396c8c005555e1560000000055555555');
// const P = this;
// const S = P.sigma();
// const Q = S.double();
@@ -1008,31 +1110,33 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// https://eprint.iacr.org/2019/403
clearCofactor: (c, point) => {
// return this.multiplyUnsafe(CURVE.h);
return point.multiplyUnsafe(bls12_381.CURVE.x).add(point); // x*P + P
return point.multiplyUnsafe(bls12_381.params.x).add(point); // x*P + P
},
mapToCurve: (scalars: bigint[]) => {
const { x, y } = G1_SWU(Fp.create(scalars[0]));
return isogenyMapG1(x, y);
},
fromBytes: (bytes: Uint8Array): AffinePoint<Fp> => {
bytes = bytes.slice();
if (bytes.length === 48) {
// TODO: Fp.bytes
const P = Fp.ORDER;
const compressedValue = bytesToNumberBE(bytes);
const bflag = bitGet(compressedValue, I_BIT_POS);
// Zero
if (bflag === 1n) return { x: 0n, y: 0n };
if (bflag === _1n) return { x: _0n, y: _0n };
const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, 3n), Fp.create(bls12_381.CURVE.G1.b)); // y² = x³ + b
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);
if (!y) throw new Error('Invalid compressed G1 point');
const aflag = bitGet(compressedValue, C_BIT_POS);
if ((y * 2n) / P !== aflag) y = Fp.neg(y);
if ((y * _2n) / P !== aflag) y = Fp.neg(y);
return { x: Fp.create(x), y: Fp.create(y) };
} else if (bytes.length === 96) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0) return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = bytesToNumberBE(bytes.slice(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.slice(Fp.BYTES));
const x = bytesToNumberBE(bytes.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.subarray(Fp.BYTES));
return { x: Fp.create(x), y: Fp.create(y) };
} else {
throw new Error('Invalid point G1, expected 48/96 bytes');
@@ -1045,7 +1149,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
if (isZero) return COMPRESSED_ZERO.slice();
const P = Fp.ORDER;
let num;
num = bitSet(x, C_BIT_POS, Boolean((y * 2n) / P)); // set aflag
num = bitSet(x, C_BIT_POS, Boolean((y * _2n) / P)); // set aflag
num = bitSet(num, S_BIT_POS, true);
return numberToBytesBE(num, Fp.BYTES);
} else {
@@ -1066,21 +1170,33 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
G2: {
Fp: Fp2,
// cofactor
h: 0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5n,
h: BigInt(
'0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5'
),
Gx: Fp2.fromBigTuple([
0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8n,
0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7en,
BigInt(
'0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8'
),
BigInt(
'0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e'
),
]),
// y =
// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582,
// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
Gy: Fp2.fromBigTuple([
0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801n,
0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79ben,
BigInt(
'0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801'
),
BigInt(
'0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be'
),
]),
a: Fp2.ZERO,
b: Fp2.fromBigTuple([4n, 4n]),
hEff: 0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551n,
b: Fp2.fromBigTuple([_4n, _4n]),
hEff: BigInt(
'0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'
),
htfDefaults: { ...htfDefaults },
wrapPrivateKey: true,
allowInfinityPoint: true,
@@ -1093,7 +1209,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// It returns false for shitty points.
// https://eprint.iacr.org/2021/1130.pdf
isTorsionFree: (c, P): boolean => {
return P.multiplyUnsafe(bls12_381.CURVE.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
return P.multiplyUnsafe(bls12_381.params.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
// Older version: https://eprint.iacr.org/2019/814.pdf
// Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O
// return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero();
@@ -1103,7 +1219,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// https://eprint.iacr.org/2017/419.pdf
// prettier-ignore
clearCofactor: (c, P) => {
const { x } = bls12_381.CURVE;
const x = bls12_381.params.x;
let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
let t2 = G2psi(c, P); // Ψ(P)
let t3 = P.double(); // 2P
@@ -1117,6 +1233,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
},
fromBytes: (bytes: Uint8Array): AffinePoint<Fp2> => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;
if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {
throw new Error('Invalid encoding flag: ' + m_byte);
@@ -1127,7 +1244,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
const L = Fp.BYTES;
const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to));
if (bytes.length === 96 && bitC) {
const { b } = bls12_381.CURVE.G2;
const b = bls12_381.params.G2b;
const P = Fp.ORDER;
bytes[0] = bytes[0] & 0x1f; // clear flags
@@ -1141,9 +1258,9 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
const x_1 = slc(bytes, 0, L);
const x_0 = slc(bytes, L, 2 * L);
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
const right = Fp2.add(Fp2.pow(x, 3n), b); // y² = x³ + 4 * (u+1) = x³ + b
const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b
let y = Fp2.sqrt(right);
const Y_bit = y.c1 === 0n ? (y.c0 * 2n) / P : (y.c1 * 2n) / P ? 1n : 0n;
const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
return { x, y };
} else if (bytes.length === 192 && !bitC) {
@@ -1161,32 +1278,32 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
}
},
toBytes: (c, point, isCompressed) => {
const { BYTES: len, ORDER: P } = Fp;
const isZero = point.equals(c.ZERO);
const { x, y } = point.toAffine();
if (isCompressed) {
const P = Fp.ORDER;
if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
const flag = Boolean(y.c1 === 0n ? (y.c0 * 2n) / P : (y.c1 * 2n) / P);
if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
let x_1 = bitSet(x.c1, C_BIT_POS, flag);
x_1 = bitSet(x_1, S_BIT_POS, true);
return concatB(numberToBytesBE(x_1, Fp.BYTES), numberToBytesBE(x.c0, Fp.BYTES));
return concatB(numberToBytesBE(x_1, len), numberToBytesBE(x.c0, len));
} else {
if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * Fp.BYTES - 1)); // bytes[0] |= 1 << 6;
if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
return concatB(
numberToBytesBE(x1, Fp.BYTES),
numberToBytesBE(x0, Fp.BYTES),
numberToBytesBE(y1, Fp.BYTES),
numberToBytesBE(y0, Fp.BYTES)
numberToBytesBE(x1, len),
numberToBytesBE(x0, len),
numberToBytesBE(y1, len),
numberToBytesBE(y0, len)
);
}
},
Signature: {
// TODO: Optimize, it's very slow because of sqrt.
decode(hex: Hex): ProjPointType<Fp2> {
hex = ensureBytes(hex);
fromHex(hex: Hex): ProjPointType<Fp2> {
hex = ensureBytes('signatureHex', hex);
const P = Fp.ORDER;
const half = hex.length / 2;
if (half !== 48 && half !== 96)
@@ -1195,12 +1312,12 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
const z2 = bytesToNumberBE(hex.slice(half));
// Indicates the infinity point
const bflag1 = bitGet(z1, I_BIT_POS);
if (bflag1 === 1n) return bls12_381.G2.ProjectivePoint.ZERO;
if (bflag1 === _1n) return bls12_381.G2.ProjectivePoint.ZERO;
const x1 = Fp.create(z1 & Fp.MASK);
const x2 = Fp.create(z2);
const x = Fp2.create({ c0: x2, c1: x1 });
const y2 = Fp2.add(Fp2.pow(x, 3n), bls12_381.CURVE.G2.b); // y² = x³ + 4
const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b); // y² = x³ + 4
// The slow part
let y = Fp2.sqrt(y2);
if (!y) throw new Error('Failed to find a square root');
@@ -1209,32 +1326,25 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// If y1 happens to be zero, then use the bit of y0
const { re: y0, im: y1 } = Fp2.reim(y);
const aflag1 = bitGet(z1, 381);
const isGreater = y1 > 0n && (y1 * 2n) / P !== aflag1;
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;
const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;
if (isGreater || isZero) y = Fp2.neg(y);
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
// console.log('Signature.decode', point);
point.assertValidity();
return point;
},
encode(point: ProjPointType<Fp2>) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
const a = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(a.x);
const { re: y0, im: y1 } = Fp2.reim(a.y);
const tmp = y1 > 0n ? y1 * 2n : y0 * 2n;
const aflag1 = Boolean((tmp / Fp.ORDER) & 1n);
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
const z2 = x0;
return concatB(numberToBytesBE(z1, Fp.BYTES), numberToBytesBE(z2, Fp.BYTES));
toRawBytes(point: ProjPointType<Fp2>) {
return signatureG2ToRawBytes(point);
},
toHex(point: ProjPointType<Fp2>) {
return bytesToHex(signatureG2ToRawBytes(point));
},
},
},
// The BLS parameter x for BLS12-381
x: BLS_X,
params: {
x: BLS_X, // The BLS parameter x for BLS12-381
r: Fr.ORDER, // order; z⁴ z² + 1; CURVE.n from other curves
},
htfDefaults,
hash: sha256,
randomBytes,

View File

@@ -2,7 +2,7 @@
import { sha256 } from '@noble/hashes/sha256';
import { weierstrass } from './abstract/weierstrass.js';
import { getHash } from './_shortw_utils.js';
import { Fp } from './abstract/modular.js';
import { Field } from './abstract/modular.js';
/**
* bn254 pairing-friendly curve.
* Previously known as alt_bn_128, when it had 128-bit security.
@@ -12,7 +12,7 @@ import { Fp } from './abstract/modular.js';
export const bn254 = weierstrass({
a: BigInt(0),
b: BigInt(3),
Fp: Fp(BigInt('0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47')),
Fp: Field(BigInt('0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47')),
n: BigInt('0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001'),
Gx: BigInt(1),
Gy: BigInt(2),

View File

@@ -1,18 +1,19 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { sha512 } from '@noble/hashes/sha512';
import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils';
import { twistedEdwards, ExtPointType } from './abstract/edwards.js';
import { ExtPointType, twistedEdwards } from './abstract/edwards.js';
import { montgomery } from './abstract/montgomery.js';
import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.js';
import {
ensureBytes,
equalBytes,
bytesToHex,
bytesToNumberLE,
numberToBytesLE,
ensureBytes,
equalBytes,
Hex,
numberToBytesLE,
} from './abstract/utils.js';
import * as htf from './abstract/hash-to-curve.js';
import { createHasher, htfBasicOpts, expand_message_xmd } from './abstract/hash-to-curve.js';
import { AffinePoint } from './abstract/curve.js';
/**
* ed25519 Twisted Edwards curve with following addons:
@@ -33,6 +34,7 @@ const ED25519_SQRT_M1 = BigInt(
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _5n = BigInt(5);
// prettier-ignore
const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
function ed25519_pow_2_252_3(x: bigint) {
const P = ED25519_P;
const x2 = (x * x) % P;
@@ -50,6 +52,7 @@ function ed25519_pow_2_252_3(x: bigint) {
// ^ To pow to (p+3)/8, multiply it by x.
return { pow_p_5_8, b2 };
}
function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
// Section 5: For X25519, in order to decode 32 random bytes as an integer scalar,
// set the three least significant bits of the first byte
@@ -60,6 +63,7 @@ function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
bytes[31] |= 64; // 0b0100_0000
return bytes;
}
// sqrt(u/v)
function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } {
const P = ED25519_P;
@@ -94,15 +98,15 @@ export const ED25519_TORSION_SUBGROUP = [
const Fp = Field(ED25519_P, undefined, true);
const ED25519_DEF = {
const ed25519Defaults = {
// Param: a
a: BigInt(-1),
// Equal to -121665/121666 over finite field.
a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster
// d is equal to -121665/121666 over finite field.
// Negative number is P - number, and division is invert(number, P)
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
// Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n
Fp,
// Subgroup order: how many points ed25519 has
// Subgroup order: how many points curve has
// 2n**252n + 27742317777372353535851937790883648493n;
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
// Cofactor
@@ -119,7 +123,8 @@ const ED25519_DEF = {
uvRatio,
} as const;
export const ed25519 = twistedEdwards(ED25519_DEF);
export const ed25519 = twistedEdwards(ed25519Defaults);
function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) {
if (ctx.length > 255) throw new Error('Context is too big');
return concatBytes(
@@ -129,19 +134,21 @@ function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) {
data
);
}
export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
export const ed25519ctx = twistedEdwards({ ...ed25519Defaults, domain: ed25519_domain });
export const ed25519ph = twistedEdwards({
...ED25519_DEF,
...ed25519Defaults,
domain: ed25519_domain,
preHash: sha512,
prehash: sha512,
});
export const x25519 = montgomery({
export const x25519 = /* @__PURE__ */ (() =>
montgomery({
P: ED25519_P,
a24: BigInt('121665'),
a: BigInt(486662),
montgomeryBits: 255, // n is 253 bits
nByteLength: 32,
Gu: '0900000000000000000000000000000000000000000000000000000000000000',
Gu: BigInt(9),
powPminus2: (x: bigint): bigint => {
const P = ED25519_P;
// x^(p-2) aka x^(2^255-21)
@@ -149,7 +156,36 @@ export const x25519 = montgomery({
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
},
adjustScalarBytes,
});
randomBytes,
}))();
/**
* Converts ed25519 public key to x25519 public key. Uses formula:
* * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
* * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
* @example
* const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey());
* const aPriv = x25519.utils.randomPrivateKey();
* x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub))
*/
export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array {
const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y)));
}
export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
/**
* Converts ed25519 secret key to x25519 secret key.
* @example
* const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey());
* const aPriv = ed25519.utils.randomPrivateKey();
* x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub)
*/
export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array {
const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32));
return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32);
}
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
@@ -202,12 +238,13 @@ function map_to_curve_elligator2_curve25519(u: bigint) {
let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
y = Fp.cmov(y, Fp.neg(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1)
return { xMn: xn, xMd: xd, yMn: y, yMd: _1n }; // 39. return (xn, xd, y, 1)
}
const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.neg(BigInt(486664))); // sgn0(c1) MUST equal 0
function map_to_curve_elligator2_edwards25519(u: bigint) {
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) = map_to_curve_elligator2_curve25519(u)
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) =
// map_to_curve_elligator2_curve25519(u)
let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
xn = Fp.mul(xn, ELL2_C1_EDWARDS); // 3. xn = xn * c1
let xd = Fp.mul(xMd, yMn); // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM
@@ -223,7 +260,9 @@ function map_to_curve_elligator2_edwards25519(u: bigint) {
const inv = Fp.invertBatch([xd, yd]); // batch division
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
}
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
const htf = /* @__PURE__ */ (() =>
createHasher(
ed25519.ExtendedPoint,
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
{
@@ -235,16 +274,16 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
expand: 'xmd',
hash: sha512,
}
);
export { hashToCurve, encodeToCurve };
))();
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();
function assertRstPoint(other: unknown) {
if (!(other instanceof RistrettoPoint)) throw new Error('RistrettoPoint expected');
if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected');
}
// √(-1) aka √(a) aka 2^((p-1)/4)
const SQRT_M1 = BigInt(
'19681161376707505956807079304988542015446066515923890162744021073123829784752'
);
const SQRT_M1 = ED25519_SQRT_M1;
// √(ad - 1)
const SQRT_AD_MINUS_ONE = BigInt(
'25063068953384623474111414158702152701244531502492656460079210482610430750235'
@@ -301,27 +340,31 @@ function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint {
* but it should work in its own namespace: do not combine those two.
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
*/
export class RistrettoPoint {
static BASE = new RistrettoPoint(ed25519.ExtendedPoint.BASE);
static ZERO = new RistrettoPoint(ed25519.ExtendedPoint.ZERO);
class RistPoint {
static BASE: RistPoint;
static ZERO: RistPoint;
// Private property to discourage combining ExtendedPoint + RistrettoPoint
// Always use Ristretto encoding/decoding instead.
constructor(private readonly ep: ExtendedPoint) {}
static fromAffine(ap: AffinePoint<bigint>) {
return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap));
}
/**
* Takes uniform output of 64-bit hash function like sha512 and converts it to `RistrettoPoint`.
* Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`.
* The hash-to-group operation applies Elligator twice and adds the results.
* **Note:** this is one-way map, there is no conversion from point to hash.
* https://ristretto.group/formulas/elligator.html
* @param hex 64-bit output of a hash function
* @param hex 64-byte output of a hash function
*/
static hashToCurve(hex: Hex): RistrettoPoint {
hex = ensureBytes(hex, 64);
static hashToCurve(hex: Hex): RistPoint {
hex = ensureBytes('ristrettoHash', hex, 64);
const r1 = bytes255ToNumberLE(hex.slice(0, 32));
const R1 = calcElligatorRistrettoMap(r1);
const r2 = bytes255ToNumberLE(hex.slice(32, 64));
const R2 = calcElligatorRistrettoMap(r2);
return new RistrettoPoint(R1.add(R2));
return new RistPoint(R1.add(R2));
}
/**
@@ -329,8 +372,8 @@ export class RistrettoPoint {
* https://ristretto.group/formulas/decoding.html
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
*/
static fromHex(hex: Hex): RistrettoPoint {
hex = ensureBytes(hex, 32);
static fromHex(hex: Hex): RistPoint {
hex = ensureBytes('ristrettoHex', hex, 32);
const { a, d } = ed25519.CURVE;
const P = ed25519.CURVE.Fp.ORDER;
const mod = ed25519.CURVE.Fp.create;
@@ -353,7 +396,7 @@ export class RistrettoPoint {
const y = mod(u1 * Dy); // 11
const t = mod(x * y); // 12
if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg);
return new RistrettoPoint(new ed25519.ExtendedPoint(x, y, _1n, t));
return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t));
}
/**
@@ -397,10 +440,10 @@ export class RistrettoPoint {
}
// Compare one point to another.
equals(other: RistrettoPoint): boolean {
equals(other: RistPoint): boolean {
assertRstPoint(other);
const { ex: X1, ey: Y1 } = this.ep;
const { ex: X2, ey: Y2 } = this.ep;
const { ex: X2, ey: Y2 } = other.ep;
const mod = ed25519.CURVE.Fp.create;
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
const one = mod(X1 * Y2) === mod(Y1 * X2);
@@ -408,21 +451,36 @@ export class RistrettoPoint {
return one || two;
}
add(other: RistrettoPoint): RistrettoPoint {
add(other: RistPoint): RistPoint {
assertRstPoint(other);
return new RistrettoPoint(this.ep.add(other.ep));
return new RistPoint(this.ep.add(other.ep));
}
subtract(other: RistrettoPoint): RistrettoPoint {
subtract(other: RistPoint): RistPoint {
assertRstPoint(other);
return new RistrettoPoint(this.ep.subtract(other.ep));
return new RistPoint(this.ep.subtract(other.ep));
}
multiply(scalar: bigint): RistrettoPoint {
return new RistrettoPoint(this.ep.multiply(scalar));
multiply(scalar: bigint): RistPoint {
return new RistPoint(this.ep.multiply(scalar));
}
multiplyUnsafe(scalar: bigint): RistrettoPoint {
return new RistrettoPoint(this.ep.multiplyUnsafe(scalar));
multiplyUnsafe(scalar: bigint): RistPoint {
return new RistPoint(this.ep.multiplyUnsafe(scalar));
}
}
export const RistrettoPoint = /* @__PURE__ */ (() => {
if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE);
if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO);
return RistPoint;
})();
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/
// Appendix B. Hashing to ristretto255
export const hash_to_ristretto255 = (msg: Uint8Array, options: htfBasicOpts) => {
const d = options.DST;
const DST = typeof d === 'string' ? utf8ToBytes(d) : d;
const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512);
const P = RistPoint.hashToCurve(uniform_bytes);
return P;
};

View File

@@ -2,9 +2,9 @@
import { shake256 } from '@noble/hashes/sha3';
import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils';
import { twistedEdwards } from './abstract/edwards.js';
import { mod, pow2, Fp as Field } from './abstract/modular.js';
import { mod, pow2, Field } from './abstract/modular.js';
import { montgomery } from './abstract/montgomery.js';
import * as htf from './abstract/hash-to-curve.js';
import { createHasher } from './abstract/hash-to-curve.js';
/**
* Edwards448 (not Ed448-Goldilocks) curve with following addons:
@@ -54,6 +54,7 @@ function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
}
const Fp = Field(ed448P, 456, true);
const _4n = BigInt(4);
const ED448_DEF = {
// Param: a
@@ -119,14 +120,15 @@ const ED448_DEF = {
export const ed448 = twistedEdwards(ED448_DEF);
// NOTE: there is no ed448ctx, since ed448 supports ctx by default
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
export const ed448ph = twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });
export const x448 = montgomery({
a24: BigInt(39081),
export const x448 = /* @__PURE__ */ (() =>
montgomery({
a: BigInt(156326),
montgomeryBits: 448,
nByteLength: 57,
P: ed448P,
Gu: '0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
Gu: BigInt(5),
powPminus2: (x: bigint): bigint => {
const P = ed448P;
const Pminus3div4 = ed448_pow_Pminus3div4(x);
@@ -134,21 +136,23 @@ export const x448 = montgomery({
return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2
},
adjustScalarBytes,
// The 4-isogeny maps between the Montgomery curve and this Edwards
// curve are:
// (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
// (x, y) = (4*v*(u^2 - 1)/(u^4 - 2*u^2 + 4*v^2 + 1),
// -(u^5 - 2*u^3 - 4*u*v^2 + u)/
// (u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u))
// xyToU: (p: PointType) => {
// const P = ed448P;
// const { x, y } = p;
// if (x === _0n) throw new Error(`Point with x=0 doesn't have mapping`);
// const invX = invert(x * x, P); // x^2
// const u = mod(y * y * invX, P); // (y^2/x^2)
// return numberToBytesLE(u, 56);
// },
});
randomBytes,
}))();
/**
* Converts edwards448 public key to x448 public key. Uses formula:
* * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
* * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
* @example
* const aPub = ed448.getPublicKey(utils.randomPrivateKey());
* x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array {
const { y } = ed448.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
// Hash To Curve Elligator2 Map
const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
@@ -194,10 +198,10 @@ function map_to_curve_elligator2_edwards448(u: bigint) {
xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
xEn = Fp.mul(xEn, _4n); // 12. xEn = xEn * 4
tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
let tv3 = Fp.mul(yn2, _4n); // 15. tv3 = 4 * yn2
let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
@@ -225,7 +229,8 @@ function map_to_curve_elligator2_edwards448(u: bigint) {
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
}
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
const htf = /* @__PURE__ */ (() =>
createHasher(
ed448.ExtendedPoint,
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
{
@@ -237,5 +242,6 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
expand: 'xof',
hash: shake256,
}
);
export { hashToCurve, encodeToCurve };
))();
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();

View File

@@ -3,7 +3,7 @@ import { sha512 } from '@noble/hashes/sha512';
import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils';
import { twistedEdwards } from './abstract/edwards.js';
import { blake2s } from '@noble/hashes/blake2s';
import { Fp } from './abstract/modular.js';
import { Field } from './abstract/modular.js';
/**
* jubjub Twisted Edwards curve.
@@ -17,7 +17,7 @@ export const jubjub = twistedEdwards({
d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'),
// Finite field 𝔽p over which we'll do calculations
// Same value as bls12-381 Fr (not Fp)
Fp: Fp(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')),
Fp: Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')),
// Subgroup order: how many points curve has
n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'),
// Cofactor

View File

@@ -1,25 +0,0 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from './_shortw_utils.js';
import { sha256 } from '@noble/hashes/sha256';
import { Fp } from './abstract/modular.js';
// NIST secp192r1 aka P192
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1
export const P192 = createCurve(
{
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
// Field over which we'll do calculations; 2n ** 192n - 2n ** 64n - 1n
Fp: Fp(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')),
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
// Base point (x, y) aka generator point
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
h: BigInt(1),
lowS: false,
} as const,
sha256
);
export const secp192r1 = P192;

View File

@@ -1,25 +0,0 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from './_shortw_utils.js';
import { sha224 } from '@noble/hashes/sha256';
import { Fp } from './abstract/modular.js';
// NIST secp224r1 aka P224
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-224
export const P224 = createCurve(
{
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
// Field over which we'll do calculations;
Fp: Fp(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),
// Curve order, total count of valid points in the field
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
// Base point (x, y) aka generator point
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
h: BigInt(1),
lowS: false,
} as const,
sha224
);
export const secp224r1 = P224;

View File

@@ -1,46 +1,41 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from './_shortw_utils.js';
import { sha256 } from '@noble/hashes/sha256';
import { Fp as Field } from './abstract/modular.js';
import { Field } from './abstract/modular.js';
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
import * as htf from './abstract/hash-to-curve.js';
import { createHasher } from './abstract/hash-to-curve.js';
// NIST secp256r1 aka P256
// NIST secp256r1 aka p256
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
// Field over which we'll do calculations; 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
const Fp = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));
const CURVE_A = Fp.create(BigInt('-3'));
const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b');
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-10')),
});
export const P256 = createCurve(
{
// Params: a, b
a: CURVE_A,
// prettier-ignore
export const p256 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
Fp, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
// Curve order, total count of valid points in the field
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base point (x, y) aka generator point
// Base (generator) point (x, y)
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
h: BigInt(1),
lowS: false,
} as const,
sha256
);
export const secp256r1 = P256;
} as const, sha256);
export const secp256r1 = p256;
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
secp256r1.ProjectivePoint,
(scalars: bigint[]) => mapSWU(scalars[0]),
{
const mapSWU = /* @__PURE__ */ (() =>
mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-10')),
}))();
const htf = /* @__PURE__ */ (() =>
createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), {
DST: 'P256_XMD:SHA-256_SSWU_RO_',
encodeDST: 'P256_XMD:SHA-256_SSWU_NU_',
p: Fp.ORDER,
@@ -48,6 +43,6 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
k: 128,
expand: 'xmd',
hash: sha256,
}
);
export { hashToCurve, encodeToCurve };
}))();
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();

View File

@@ -1,14 +1,14 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from './_shortw_utils.js';
import { sha384 } from '@noble/hashes/sha512';
import { Fp as Field } from './abstract/modular.js';
import { Field } from './abstract/modular.js';
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
import * as htf from './abstract/hash-to-curve.js';
import { createHasher } from './abstract/hash-to-curve.js';
// NIST secp384r1 aka P384
// NIST secp384r1 aka p384
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Field over which we'll do calculations.
// prettier-ignore
const P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');
const Fp = Field(P);
@@ -16,35 +16,30 @@ const CURVE_A = Fp.create(BigInt('-3'));
// prettier-ignore
const CURVE_B = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef');
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-12')),
});
// prettier-ignore
export const P384 = createCurve({
// Params: a, b
a: CURVE_A,
export const p384 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
Fp,
Fp, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
// Base point (x, y) aka generator point
// Base (generator) point (x, y)
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),
Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
h: BigInt(1),
lowS: false,
} as const,
sha384
);
export const secp384r1 = P384;
} as const, sha384);
export const secp384r1 = p384;
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
secp384r1.ProjectivePoint,
(scalars: bigint[]) => mapSWU(scalars[0]),
{
const mapSWU = /* @__PURE__ */ (() =>
mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-12')),
}))();
const htf = /* @__PURE__ */ (() =>
createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), {
DST: 'P384_XMD:SHA-384_SSWU_RO_',
encodeDST: 'P384_XMD:SHA-384_SSWU_NU_',
p: Fp.ORDER,
@@ -52,6 +47,6 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
k: 192,
expand: 'xmd',
hash: sha384,
}
);
export { hashToCurve, encodeToCurve };
}))();
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();

View File

@@ -1,50 +1,61 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from './_shortw_utils.js';
import { sha512 } from '@noble/hashes/sha512';
import { Fp as Field } from './abstract/modular.js';
import { Field } from './abstract/modular.js';
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
import * as htf from './abstract/hash-to-curve.js';
import { createHasher } from './abstract/hash-to-curve.js';
// NIST secp521r1 aka P521
// NIST secp521r1 aka p521
// Note that it's 521, which differs from 512 of its hash function.
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521
// Field over which we'll do calculations; 2n**521n - 1n
// Field over which we'll do calculations.
// prettier-ignore
const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
const Fp = Field(P);
const CURVE_A = Fp.create(BigInt('-3'));
// prettier-ignore
const CURVE_B = BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00');
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-4')),
});
// prettier-ignore
export const P521 = createCurve({
// Params: a, b
a: CURVE_A,
b: CURVE_B,
const CURVE = {
a: Fp.create(BigInt('-3')),
b: BigInt(
'0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'
),
Fp,
// Curve order, total count of valid points in the field
n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
// Base point (x, y) aka generator point
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
n: BigInt(
'0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'
),
Gx: BigInt(
'0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'
),
Gy: BigInt(
'0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'
),
h: BigInt(1),
};
// prettier-ignore
export const p521 = createCurve({
a: CURVE.a, // Equation params: a, b
b: CURVE.b,
Fp, // Field: 2n**521n - 1n
// Curve order, total count of valid points in the field
n: CURVE.n,
Gx: CURVE.Gx, // Base point (x, y) aka generator point
Gy: CURVE.Gy,
h: CURVE.h,
lowS: false,
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
} as const, sha512);
export const secp521r1 = P521;
export const secp521r1 = p521;
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
secp521r1.ProjectivePoint,
(scalars: bigint[]) => mapSWU(scalars[0]),
{
const mapSWU = /* @__PURE__ */ (() =>
mapToCurveSimpleSWU(Fp, {
A: CURVE.a,
B: CURVE.b,
Z: Fp.create(BigInt('-4')),
}))();
const htf = /* @__PURE__ */ (() =>
createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), {
DST: 'P521_XMD:SHA-512_SSWU_RO_',
encodeDST: 'P521_XMD:SHA-512_SSWU_NU_',
p: Fp.ORDER,
@@ -52,6 +63,6 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
k: 256,
expand: 'xmd',
hash: sha512,
}
);
export { hashToCurve, encodeToCurve };
}))();
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();

View File

@@ -11,7 +11,7 @@ export const q = BigInt('0x40000000000000000000000000000000224698fc0994a8dd8c46e
export const pallas = weierstrass({
a: BigInt(0),
b: BigInt(5),
Fp: mod.Fp(p),
Fp: mod.Field(p),
n: q,
Gx: mod.mod(BigInt(-1), p),
Gy: BigInt(2),
@@ -22,7 +22,7 @@ export const pallas = weierstrass({
export const vesta = weierstrass({
a: BigInt(0),
b: BigInt(5),
Fp: mod.Fp(q),
Fp: mod.Field(q),
n: p,
Gx: mod.mod(BigInt(-1), q),
Gy: BigInt(2),

View File

@@ -1,26 +1,12 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { sha256 } from '@noble/hashes/sha256';
import { Fp as Field, mod, pow2 } from './abstract/modular.js';
import { createCurve } from './_shortw_utils.js';
import { ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js';
import {
ensureBytes,
concatBytes,
Hex,
bytesToNumberBE as bytesToInt,
PrivKey,
numberToBytesBE,
} from './abstract/utils.js';
import { randomBytes } from '@noble/hashes/utils';
import * as htf from './abstract/hash-to-curve.js';
/**
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
* Should always be used for Projective's double-and-add multiplication.
* For affines cached multiplication, it trades off 1/2 init time & 1/3 ram for 20% perf hit.
* https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
*/
import { Field, mod, pow2 } from './abstract/modular.js';
import { ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js';
import type { Hex, PrivKey } from './abstract/utils.js';
import { bytesToNumberBE, concatBytes, ensureBytes, numberToBytesBE } from './abstract/utils.js';
import { createHasher, isogenyMap } from './abstract/hash-to-curve.js';
import { createCurve } from './_shortw_utils.js';
const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
@@ -57,27 +43,25 @@ function sqrtMod(y: bigint): bigint {
}
const Fp = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
type Fp = bigint;
export const secp256k1 = createCurve(
{
// Params: a, b
// Seem to be rigid https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
a: BigInt(0),
b: BigInt(7),
// Field over which we'll do calculations;
// 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
Fp,
// Curve order, total count of valid points in the field
n: secp256k1N,
a: BigInt(0), // equation params: a, b
b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
n: secp256k1N, // Curve order, total count of valid points in the field
// Base point (x, y) aka generator point
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
h: BigInt(1),
// Alllow only low-S signatures by default in sign() and verify()
lowS: true,
h: BigInt(1), // Cofactor
lowS: true, // Allow only low-S signatures by default in sign() and verify()
/**
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
* Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
*/
endo: {
// Params taken from https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
splitScalar: (k: bigint) => {
const n = secp256k1N;
@@ -105,19 +89,11 @@ export const secp256k1 = createCurve(
sha256
);
// Schnorr signatures are superior to ECDSA from above.
// Below is Schnorr-specific code as per BIP0340.
// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
const _0n = BigInt(0);
const fe = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1P;
const ge = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1N;
const TAGS = {
challenge: 'BIP0340/challenge',
aux: 'BIP0340/aux',
nonce: 'BIP0340/nonce',
} as const;
/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {};
function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
@@ -130,56 +106,70 @@ function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
return sha256(concatBytes(tagP, ...messages));
}
// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
const pointToBytes = (point: PointType<bigint>) => point.toRawBytes(true).slice(1);
const numTo32b = (n: bigint) => numberToBytesBE(n, 32);
const modP = (x: bigint) => mod(x, secp256k1P);
const modN = (x: bigint) => mod(x, secp256k1N);
const Point = secp256k1.ProjectivePoint;
const GmulAdd = (Q: PointType<bigint>, a: bigint, b: bigint) =>
Point.BASE.multiplyAndAddUnsafe(Q, a, b);
const hex32ToInt = (key: Hex) => bytesToInt(ensureBytes(key, 32));
// Calculate point, scalar and bytes
function schnorrGetExtPubKey(priv: PrivKey) {
let d = typeof priv === 'bigint' ? priv : hex32ToInt(priv);
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
return { point, scalar, bytes: pointToBytes(point) };
let d_ = secp256k1.utils.normPrivateKeyToScalar(priv); // same method executed in fromPrivateKey
let p = Point.fromPrivateKey(d_); // P = d'⋅G; 0 < d' < n check is done inside
const scalar = p.hasEvenY() ? d_ : modN(-d_);
return { scalar: scalar, bytes: pointToBytes(p) };
}
/**
* lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.
* @returns valid point checked for being on-curve
*/
function lift_x(x: bigint): PointType<bigint> {
if (!fe(x)) throw new Error('bad x: need 0 < x < p'); // Fail if x ≥ p.
const c = mod(x * x * x + BigInt(7), secp256k1P); // Let c = x³ + 7 mod p.
const xx = modP(x * x);
const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.
let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.
if (y % 2n !== 0n) y = mod(-y, secp256k1P); // Return the unique point P such that x(P) = x and
if (y % _2n !== _0n) y = modP(-y); // Return the unique point P such that x(P) = x and
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
p.assertValidity();
return p;
}
/**
* Create tagged hash, convert it to bigint, reduce modulo-n.
*/
function challenge(...args: Uint8Array[]): bigint {
return modN(bytesToInt(taggedHash(TAGS.challenge, ...args)));
return modN(bytesToNumberBE(taggedHash('BIP0340/challenge', ...args)));
}
// Schnorr's pubkey is just `x` of Point (BIP340)
/**
* Schnorr public key is just `x` coordinate of Point as per BIP340.
*/
function schnorrGetPublicKey(privateKey: Hex): Uint8Array {
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
}
// Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
// auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous
/**
* Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
* auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.
*/
function schnorrSign(
message: Hex,
privateKey: PrivKey,
auxRand: Hex = randomBytes(32)
): Uint8Array {
if (message == null) throw new Error(`sign: Expected valid message, not "${message}"`);
const m = ensureBytes(message); // checks for isWithinCurveOrder
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
const a = ensureBytes(auxRand, 32); // Auxiliary random data a: a 32-byte array
const t = numTo32b(d ^ bytesToInt(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
const rand = taggedHash(TAGS.nonce, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
const k_ = modN(bytesToInt(rand)); // Let k' = int(rand) mod n
const m = ensureBytes('message', message);
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey); // checks for isWithinCurveOrder
const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array
const t = numTo32b(d ^ bytesToNumberBE(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
const k_ = modN(bytesToNumberBE(rand)); // Let k' = int(rand) mod n
if (k_ === _0n) throw new Error('sign failed: k is zero'); // Fail if k' = 0.
const { point: R, bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
sig.set(numTo32b(R.px), 0);
sig.set(rx, 0);
sig.set(numTo32b(modN(k + e * d)), 32);
// If Verify(bytes(P), m, sig) (see below) returns failure, abort
if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced');
@@ -187,18 +177,20 @@ function schnorrSign(
}
/**
* Verifies Schnorr signature synchronously.
* Verifies Schnorr signature.
* Will swallow errors & return false except for initial type validation of arguments.
*/
function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {
const sig = ensureBytes('signature', signature, 64);
const m = ensureBytes('message', message);
const pub = ensureBytes('publicKey', publicKey, 32);
try {
const P = lift_x(hex32ToInt(publicKey)); // P = lift_x(int(pk)); fail if that fails
const sig = ensureBytes(signature, 64);
const r = bytesToInt(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
const P = lift_x(bytesToNumberBE(pub)); // P = lift_x(int(pk)); fail if that fails
const r = bytesToNumberBE(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
if (!fe(r)) return false;
const s = bytesToInt(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
const s = bytesToNumberBE(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
if (!ge(s)) return false;
const m = ensureBytes(message);
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P
if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false; // -eP == (n-e)P
return true; // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.
@@ -207,22 +199,23 @@ function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {
}
}
export const schnorr = {
export const schnorr = /* @__PURE__ */ (() => ({
getPublicKey: schnorrGetPublicKey,
sign: schnorrSign,
verify: schnorrVerify,
utils: {
getExtendedPublicKey: schnorrGetExtPubKey,
randomPrivateKey: secp256k1.utils.randomPrivateKey,
lift_x,
pointToBytes,
numberToBytesBE,
bytesToNumberBE: bytesToInt,
bytesToNumberBE,
taggedHash,
mod,
},
};
}))();
const isoMap = htf.isogenyMap(
const isoMap = /* @__PURE__ */ (() =>
isogenyMap(
Fp,
[
// xNum
@@ -252,14 +245,16 @@ const isoMap = htf.isogenyMap(
'0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f',
'0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1
],
].map((i) => i.map((j) => BigInt(j))) as [Fp[], Fp[], Fp[], Fp[]]
);
const mapSWU = mapToCurveSimpleSWU(Fp, {
].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]]
))();
const mapSWU = /* @__PURE__ */ (() =>
mapToCurveSimpleSWU(Fp, {
A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'),
B: BigInt('1771'),
Z: Fp.create(BigInt('-11')),
});
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
}))();
const htf = /* @__PURE__ */ (() =>
createHasher(
secp256k1.ProjectivePoint,
(scalars: bigint[]) => {
const { x, y } = mapSWU(Fp.create(scalars[0]));
@@ -274,5 +269,6 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
expand: 'xmd',
hash: sha256,
}
);
export { hashToCurve, encodeToCurve };
))();
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();

View File

@@ -1,356 +0,0 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { keccak_256 } from '@noble/hashes/sha3';
import { sha256 } from '@noble/hashes/sha256';
import { weierstrass, ProjPointType } from './abstract/weierstrass.js';
import * as cutils from './abstract/utils.js';
import { Fp, mod, Field, validateField } from './abstract/modular.js';
import { getHash } from './_shortw_utils.js';
import * as poseidon from './abstract/poseidon.js';
import { utf8ToBytes } from '@noble/hashes/utils';
type ProjectivePoint = ProjPointType<bigint>;
// Stark-friendly elliptic curve
// https://docs.starkware.co/starkex/stark-curve.html
const CURVE_N = BigInt(
'3618502788666131213697322783095070105526743751716087489154079457884512865583'
);
const nBitLength = 252;
// Copy-pasted from weierstrass.ts
function bits2int(bytes: Uint8Array): bigint {
const delta = bytes.length * 8 - nBitLength;
const num = cutils.bytesToNumberBE(bytes);
return delta > 0 ? num >> BigInt(delta) : num;
}
function bits2int_modN(bytes: Uint8Array): bigint {
return mod(bits2int(bytes), CURVE_N);
}
export const starkCurve = weierstrass({
// Params: a, b
a: BigInt(1),
b: BigInt('3141592653589793238462643383279502884197169399375105820974944592307816406665'),
// Field over which we'll do calculations; 2n**251n + 17n * 2n**192n + 1n
// There is no efficient sqrt for field (P%4==1)
Fp: Fp(BigInt('0x800000000000011000000000000000000000000000000000000000000000001')),
// Curve order, total count of valid points in the field.
n: CURVE_N,
nBitLength: nBitLength, // len(bin(N).replace('0b',''))
// Base point (x, y) aka generator point
Gx: BigInt('874739451078007766457464989774322083649278607533249481151382481072868806602'),
Gy: BigInt('152666792071518830868575557812948353041420400780739481342941381225525861407'),
h: BigInt(1),
// Default options
lowS: false,
...getHash(sha256),
// Custom truncation routines for stark curve
bits2int: (bytes: Uint8Array): bigint => {
while (bytes[0] === 0) bytes = bytes.subarray(1);
return bits2int(bytes);
},
bits2int_modN: (bytes: Uint8Array): bigint => {
let hashS = cutils.bytesToNumberBE(bytes).toString(16);
if (hashS.length === 63) {
hashS += '0';
bytes = hexToBytes0x(hashS);
}
// Truncate zero bytes on left (compat with elliptic)
while (bytes[0] === 0) bytes = bytes.subarray(1);
return bits2int_modN(bytes);
},
});
// Custom Starknet type conversion functions that can handle 0x and unpadded hex
function hexToBytes0x(hex: string): Uint8Array {
if (typeof hex !== 'string') {
throw new Error('hexToBytes: expected string, got ' + typeof hex);
}
hex = strip0x(hex);
if (hex.length & 1) hex = '0' + hex; // padding
if (hex.length % 2) throw new Error('hexToBytes: received invalid unpadded hex ' + hex.length);
const array = new Uint8Array(hex.length / 2);
for (let i = 0; i < array.length; i++) {
const j = i * 2;
const hexByte = hex.slice(j, j + 2);
const byte = Number.parseInt(hexByte, 16);
if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence');
array[i] = byte;
}
return array;
}
function hexToNumber0x(hex: string): bigint {
if (typeof hex !== 'string') {
throw new Error('hexToNumber: expected string, got ' + typeof hex);
}
// Big Endian
// TODO: strip vs no strip?
return BigInt(`0x${strip0x(hex)}`);
}
function bytesToNumber0x(bytes: Uint8Array): bigint {
return hexToNumber0x(cutils.bytesToHex(bytes));
}
function ensureBytes0x(hex: Hex): Uint8Array {
// Uint8Array.from() instead of hash.slice() because node.js Buffer
// is instance of Uint8Array, and its slice() creates **mutable** copy
return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes0x(hex);
}
function normalizePrivateKey(privKey: Hex) {
return cutils.bytesToHex(ensureBytes0x(privKey)).padStart(64, '0');
}
function getPublicKey0x(privKey: Hex, isCompressed = false) {
return starkCurve.getPublicKey(normalizePrivateKey(privKey), isCompressed);
}
function getSharedSecret0x(privKeyA: Hex, pubKeyB: Hex) {
return starkCurve.getSharedSecret(normalizePrivateKey(privKeyA), pubKeyB);
}
function sign0x(msgHash: Hex, privKey: Hex, opts?: any) {
if (typeof privKey === 'string') privKey = strip0x(privKey).padStart(64, '0');
return starkCurve.sign(ensureBytes0x(msgHash), normalizePrivateKey(privKey), opts);
}
function verify0x(signature: Hex, msgHash: Hex, pubKey: Hex) {
const sig = signature instanceof Signature ? signature : ensureBytes0x(signature);
return starkCurve.verify(sig, ensureBytes0x(msgHash), ensureBytes0x(pubKey));
}
const { CURVE, ProjectivePoint, Signature } = starkCurve;
export const utils = starkCurve.utils;
export {
CURVE,
Signature,
ProjectivePoint,
getPublicKey0x as getPublicKey,
getSharedSecret0x as getSharedSecret,
sign0x as sign,
verify0x as verify,
};
const stripLeadingZeros = (s: string) => s.replace(/^0+/gm, '');
export const bytesToHexEth = (uint8a: Uint8Array): string =>
`0x${stripLeadingZeros(cutils.bytesToHex(uint8a))}`;
export const strip0x = (hex: string) => hex.replace(/^0x/i, '');
export const numberToHexEth = (num: bigint | number) => `0x${num.toString(16)}`;
// We accept hex strings besides Uint8Array for simplicity
type Hex = Uint8Array | string;
// 1. seed generation
function hashKeyWithIndex(key: Uint8Array, index: number) {
let indexHex = cutils.numberToHexUnpadded(index);
if (indexHex.length & 1) indexHex = '0' + indexHex;
return sha256Num(cutils.concatBytes(key, hexToBytes0x(indexHex)));
}
export function grindKey(seed: Hex) {
const _seed = ensureBytes0x(seed);
const sha256mask = 2n ** 256n;
const limit = sha256mask - mod(sha256mask, CURVE_N);
for (let i = 0; ; i++) {
const key = hashKeyWithIndex(_seed, i);
// key should be in [0, limit)
if (key < limit) return mod(key, CURVE_N).toString(16);
}
}
export function getStarkKey(privateKey: Hex) {
return bytesToHexEth(getPublicKey0x(privateKey, true).slice(1));
}
export function ethSigToPrivate(signature: string) {
signature = strip0x(signature.replace(/^0x/, ''));
if (signature.length !== 130) throw new Error('Wrong ethereum signature');
return grindKey(signature.substring(0, 64));
}
const MASK_31 = 2n ** 31n - 1n;
const int31 = (n: bigint) => Number(n & MASK_31);
export function getAccountPath(
layer: string,
application: string,
ethereumAddress: string,
index: number
) {
const layerNum = int31(sha256Num(layer));
const applicationNum = int31(sha256Num(application));
const eth = hexToNumber0x(ethereumAddress);
return `m/2645'/${layerNum}'/${applicationNum}'/${int31(eth)}'/${int31(eth >> 31n)}'/${index}`;
}
// https://docs.starkware.co/starkex/pedersen-hash-function.html
const PEDERSEN_POINTS_AFFINE = [
new ProjectivePoint(
2089986280348253421170679821480865132823066470938446095505822317253594081284n,
1713931329540660377023406109199410414810705867260802078187082345529207694986n,
1n
),
new ProjectivePoint(
996781205833008774514500082376783249102396023663454813447423147977397232763n,
1668503676786377725805489344771023921079126552019160156920634619255970485781n,
1n
),
new ProjectivePoint(
2251563274489750535117886426533222435294046428347329203627021249169616184184n,
1798716007562728905295480679789526322175868328062420237419143593021674992973n,
1n
),
new ProjectivePoint(
2138414695194151160943305727036575959195309218611738193261179310511854807447n,
113410276730064486255102093846540133784865286929052426931474106396135072156n,
1n
),
new ProjectivePoint(
2379962749567351885752724891227938183011949129833673362440656643086021394946n,
776496453633298175483985398648758586525933812536653089401905292063708816422n,
1n
),
];
// for (const p of PEDERSEN_POINTS) p._setWindowSize(8);
const PEDERSEN_POINTS = PEDERSEN_POINTS_AFFINE;
function pedersenPrecompute(p1: ProjectivePoint, p2: ProjectivePoint): ProjectivePoint[] {
const out: ProjectivePoint[] = [];
let p = p1;
for (let i = 0; i < 248; i++) {
out.push(p);
p = p.double();
}
// NOTE: we cannot use wNAF here, because last 4 bits will require full 248 bits multiplication
// We can add support for this to wNAF, but it will complicate wNAF.
p = p2;
for (let i = 0; i < 4; i++) {
out.push(p);
p = p.double();
}
return out;
}
const PEDERSEN_POINTS1 = pedersenPrecompute(PEDERSEN_POINTS[1], PEDERSEN_POINTS[2]);
const PEDERSEN_POINTS2 = pedersenPrecompute(PEDERSEN_POINTS[3], PEDERSEN_POINTS[4]);
type PedersenArg = Hex | bigint | number;
function pedersenArg(arg: PedersenArg): bigint {
let value: bigint;
if (typeof arg === 'bigint') value = arg;
else if (typeof arg === 'number') {
if (!Number.isSafeInteger(arg)) throw new Error(`Invalid pedersenArg: ${arg}`);
value = BigInt(arg);
} else value = bytesToNumber0x(ensureBytes0x(arg));
// [0..Fp)
if (!(0n <= value && value < starkCurve.CURVE.Fp.ORDER))
throw new Error(`PedersenArg should be 0 <= value < CURVE.P: ${value}`);
return value;
}
function pedersenSingle(point: ProjectivePoint, value: PedersenArg, constants: ProjectivePoint[]) {
let x = pedersenArg(value);
for (let j = 0; j < 252; j++) {
const pt = constants[j];
if (pt.px === point.px) throw new Error('Same point');
if ((x & 1n) !== 0n) point = point.add(pt);
x >>= 1n;
}
return point;
}
// shift_point + x_low * P_0 + x_high * P1 + y_low * P2 + y_high * P3
export function pedersen(x: PedersenArg, y: PedersenArg) {
let point: ProjectivePoint = PEDERSEN_POINTS[0];
point = pedersenSingle(point, x, PEDERSEN_POINTS1);
point = pedersenSingle(point, y, PEDERSEN_POINTS2);
return bytesToHexEth(point.toRawBytes(true).slice(1));
}
export function hashChain(data: PedersenArg[], fn = pedersen) {
if (!Array.isArray(data) || data.length < 1)
throw new Error('data should be array of at least 1 element');
if (data.length === 1) return numberToHexEth(pedersenArg(data[0]));
return Array.from(data)
.reverse()
.reduce((acc, i) => fn(i, acc));
}
// Same as hashChain, but computes hash even for single element and order is not revesed
export const computeHashOnElements = (data: PedersenArg[], fn = pedersen) =>
[0, ...data, data.length].reduce((x, y) => fn(x, y));
const MASK_250 = cutils.bitMask(250);
export const keccak = (data: Uint8Array): bigint => bytesToNumber0x(keccak_256(data)) & MASK_250;
const sha256Num = (data: Uint8Array | string): bigint => cutils.bytesToNumberBE(sha256(data));
// Poseidon hash
export const Fp253 = Fp(
BigInt('14474011154664525231415395255581126252639794253786371766033694892385558855681')
); // 2^253 + 2^199 + 1
export const Fp251 = Fp(
BigInt('3618502788666131213697322783095070105623107215331596699973092056135872020481')
); // 2^251 + 17 * 2^192 + 1
function poseidonRoundConstant(Fp: Field<bigint>, name: string, idx: number) {
const val = Fp.fromBytes(sha256(utf8ToBytes(`${name}${idx}`)));
return Fp.create(val);
}
// NOTE: doesn't check eiginvalues and possible can create unsafe matrix. But any filtration here will break compatibility with starknet
// Please use only if you really know what you doing.
// https://eprint.iacr.org/2019/458.pdf Section 2.3 (Avoiding Insecure Matrices)
export function _poseidonMDS(Fp: Field<bigint>, name: string, m: number, attempt = 0) {
const x_values: bigint[] = [];
const y_values: bigint[] = [];
for (let i = 0; i < m; i++) {
x_values.push(poseidonRoundConstant(Fp, `${name}x`, attempt * m + i));
y_values.push(poseidonRoundConstant(Fp, `${name}y`, attempt * m + i));
}
if (new Set([...x_values, ...y_values]).size !== 2 * m)
throw new Error('X and Y values are not distinct');
return x_values.map((x) => y_values.map((y) => Fp.inv(Fp.sub(x, y))));
}
const MDS_SMALL = [
[3, 1, 1],
[1, -1, 1],
[1, 1, -2],
].map((i) => i.map(BigInt));
export type PoseidonOpts = {
Fp: Field<bigint>;
rate: number;
capacity: number;
roundsFull: number;
roundsPartial: number;
};
export function poseidonBasic(opts: PoseidonOpts, mds: bigint[][]) {
validateField(opts.Fp);
if (!Number.isSafeInteger(opts.rate) || !Number.isSafeInteger(opts.capacity))
throw new Error(`Wrong poseidon opts: ${opts}`);
const m = opts.rate + opts.capacity;
const rounds = opts.roundsFull + opts.roundsPartial;
const roundConstants = [];
for (let i = 0; i < rounds; i++) {
const row = [];
for (let j = 0; j < m; j++) row.push(poseidonRoundConstant(opts.Fp, 'Hades', m * i + j));
roundConstants.push(row);
}
return poseidon.poseidon({
...opts,
t: m,
sboxPower: 3,
reversePartialPowIdx: true, // Why?!
mds,
roundConstants,
});
}
export function poseidonCreate(opts: PoseidonOpts, mdsAttempt = 0) {
const m = opts.rate + opts.capacity;
if (!Number.isSafeInteger(mdsAttempt)) throw new Error(`Wrong mdsAttempt=${mdsAttempt}`);
return poseidonBasic(opts, _poseidonMDS(opts.Fp, 'HadesMDS', m, mdsAttempt));
}
export const poseidonSmall = poseidonBasic(
{ Fp: Fp251, rate: 2, capacity: 1, roundsFull: 8, roundsPartial: 83 },
MDS_SMALL
);
export function poseidonHash(x: bigint, y: bigint, fn = poseidonSmall) {
return fn([x, y, 2n])[0];
}

View File

@@ -0,0 +1,44 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from '../esm/_shortw_utils.js';
import { sha224, sha256 } from '@noble/hashes/sha256';
import { Field as Fp } from '../esm/abstract/modular.js';
// NIST secp192r1 aka p192
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1
export const p192 = createCurve(
{
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
// Field over which we'll do calculations; 2n ** 192n - 2n ** 64n - 1n
Fp: Fp(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')),
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
// Base point (x, y) aka generator point
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
h: BigInt(1),
lowS: false,
},
sha256
);
export const secp192r1 = p192;
export const p224 = createCurve(
{
// Params: a, b
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
// Field over which we'll do calculations;
Fp: Fp(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),
// Curve order, total count of valid points in the field
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
// Base point (x, y) aka generator point
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
h: BigInt(1),
lowS: false,
},
sha224
);
export const secp224r1 = p224;

103
test/_poseidon.helpers.js Normal file
View File

@@ -0,0 +1,103 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { sha256 } from '@noble/hashes/sha256';
import { utf8ToBytes } from '@noble/hashes/utils';
import { Field as Fp, validateField } from '../esm/abstract/modular.js';
import { poseidon } from '../esm/abstract/poseidon.js';
import * as u from '../esm/abstract/utils.js';
// Poseidon hash https://docs.starkware.co/starkex/stark-curve.html
export const Fp253 = Fp(
BigInt('14474011154664525231415395255581126252639794253786371766033694892385558855681')
); // 2^253 + 2^199 + 1
export const Fp251 = Fp(
BigInt('3618502788666131213697322783095070105623107215331596699973092056135872020481')
); // 2^251 + 17 * 2^192 + 1
function poseidonRoundConstant(Fp, name, idx) {
const val = Fp.fromBytes(sha256(utf8ToBytes(`${name}${idx}`)));
return Fp.create(val);
}
// NOTE: doesn't check eiginvalues and possible can create unsafe matrix. But any filtration here will break compatibility with starknet
// Please use only if you really know what you doing.
// https://eprint.iacr.org/2019/458.pdf Section 2.3 (Avoiding Insecure Matrices)
export function _poseidonMDS(Fp, name, m, attempt = 0) {
const x_values = [];
const y_values = [];
for (let i = 0; i < m; i++) {
x_values.push(poseidonRoundConstant(Fp, `${name}x`, attempt * m + i));
y_values.push(poseidonRoundConstant(Fp, `${name}y`, attempt * m + i));
}
if (new Set([...x_values, ...y_values]).size !== 2 * m)
throw new Error('X and Y values are not distinct');
return x_values.map((x) => y_values.map((y) => Fp.inv(Fp.sub(x, y))));
}
const MDS_SMALL = [
[3, 1, 1],
[1, -1, 1],
[1, 1, -2],
].map((i) => i.map(BigInt));
export function poseidonBasic(opts, mds) {
validateField(opts.Fp);
if (!Number.isSafeInteger(opts.rate) || !Number.isSafeInteger(opts.capacity))
throw new Error(`Wrong poseidon opts: ${opts}`);
const m = opts.rate + opts.capacity;
const rounds = opts.roundsFull + opts.roundsPartial;
const roundConstants = [];
for (let i = 0; i < rounds; i++) {
const row = [];
for (let j = 0; j < m; j++) row.push(poseidonRoundConstant(opts.Fp, 'Hades', m * i + j));
roundConstants.push(row);
}
const res = poseidon({
...opts,
t: m,
sboxPower: 3,
reversePartialPowIdx: true, // Why?!
mds,
roundConstants,
});
res.m = m;
res.rate = opts.rate;
res.capacity = opts.capacity;
return res;
}
export function poseidonCreate(opts, mdsAttempt = 0) {
const m = opts.rate + opts.capacity;
if (!Number.isSafeInteger(mdsAttempt)) throw new Error(`Wrong mdsAttempt=${mdsAttempt}`);
return poseidonBasic(opts, _poseidonMDS(opts.Fp, 'HadesMDS', m, mdsAttempt));
}
export const poseidonSmall = poseidonBasic(
{ Fp: Fp251, rate: 2, capacity: 1, roundsFull: 8, roundsPartial: 83 },
MDS_SMALL
);
export function poseidonHash(x, y, fn = poseidonSmall) {
return fn([x, y, 2n])[0];
}
export function poseidonHashFunc(x, y, fn = poseidonSmall) {
return u.numberToVarBytesBE(poseidonHash(u.bytesToNumberBE(x), u.bytesToNumberBE(y), fn));
}
export function poseidonHashSingle(x, fn = poseidonSmall) {
return fn([x, 0n, 1n])[0];
}
export function poseidonHashMany(values, fn = poseidonSmall) {
const { m, rate } = fn;
if (!Array.isArray(values)) throw new Error('bigint array expected in values');
const padded = Array.from(values); // copy
padded.push(1n);
while (padded.length % rate !== 0) padded.push(0n);
let state = new Array(m).fill(0n);
for (let i = 0; i < padded.length; i += rate) {
for (let j = 0; j < rate; j++) state[j] += padded[i + j];
state = fn(state);
}
return state[0];
}

View File

@@ -1,22 +1,24 @@
import { deepStrictEqual, throws } from 'assert';
import { should, describe } from 'micro-should';
import * as fc from 'fast-check';
import * as mod from '../lib/esm/abstract/modular.js';
import { bytesToHex as toHex } from '../lib/esm/abstract/utils.js';
import * as mod from '../esm/abstract/modular.js';
import { bytesToHex as toHex } from '../esm/abstract/utils.js';
// Generic tests for all curves in package
import { secp192r1 } from '../lib/esm/p192.js';
import { secp224r1 } from '../lib/esm/p224.js';
import { secp256r1 } from '../lib/esm/p256.js';
import { secp384r1 } from '../lib/esm/p384.js';
import { secp521r1 } from '../lib/esm/p521.js';
import { secp256k1 } from '../lib/esm/secp256k1.js';
import { ed25519, ed25519ctx, ed25519ph, x25519 } from '../lib/esm/ed25519.js';
import { ed448, ed448ph } from '../lib/esm/ed448.js';
import { starkCurve } from '../lib/esm/stark.js';
import { pallas, vesta } from '../lib/esm/pasta.js';
import { bn254 } from '../lib/esm/bn.js';
import { jubjub } from '../lib/esm/jubjub.js';
import { bls12_381 } from '../lib/esm/bls12-381.js';
import { secp192r1, secp224r1 } from './_more-curves.helpers.js';
import { secp256r1 } from '../esm/p256.js';
import { secp384r1 } from '../esm/p384.js';
import { secp521r1 } from '../esm/p521.js';
import { secp256k1 } from '../esm/secp256k1.js';
import { ed25519, ed25519ctx, ed25519ph, x25519 } from '../esm/ed25519.js';
import { ed448, ed448ph } from '../esm/ed448.js';
import { pallas, vesta } from '../esm/pasta.js';
import { bn254 } from '../esm/bn254.js';
import { jubjub } from '../esm/jubjub.js';
import { bls12_381 } from '../esm/bls12-381.js';
import { default as wyche_curves } from './wycheproof/ec_prime_order_curves_test.json' assert { type: 'json' };
import { createCurve } from '../esm/_shortw_utils.js';
import { Field } from '../esm/abstract/modular.js';
import { sha256 } from '@noble/hashes/sha256';
// Fields tests
const FIELDS = {
@@ -25,7 +27,6 @@ const FIELDS = {
secp256r1: { Fp: [secp256r1.CURVE.Fp] },
secp521r1: { Fp: [secp521r1.CURVE.Fp] },
secp256k1: { Fp: [secp256k1.CURVE.Fp] },
stark: { Fp: [starkCurve.CURVE.Fp] },
jubjub: { Fp: [jubjub.CURVE.Fp] },
ed25519: { Fp: [ed25519.CURVE.Fp] },
ed448: { Fp: [ed448.CURVE.Fp] },
@@ -33,19 +34,19 @@ const FIELDS = {
pallas: { Fp: [pallas.CURVE.Fp] },
vesta: { Fp: [vesta.CURVE.Fp] },
bls12: {
Fp: [bls12_381.CURVE.Fp],
Fp: [bls12_381.fields.Fp],
Fp2: [
bls12_381.CURVE.Fp2,
fc.array(fc.bigInt(1n, bls12_381.CURVE.Fp.ORDER - 1n), {
bls12_381.fields.Fp2,
fc.array(fc.bigInt(1n, bls12_381.fields.Fp.ORDER - 1n), {
minLength: 2,
maxLength: 2,
}),
(Fp2, num) => Fp2.fromBigTuple([num[0], num[1]]),
],
// Fp6: [bls12_381.CURVE.Fp6],
// Fp6: [bls12_381.fields.Fp6],
Fp12: [
bls12_381.CURVE.Fp12,
fc.array(fc.bigInt(1n, bls12_381.CURVE.Fp.ORDER - 1n), {
bls12_381.fields.Fp12,
fc.array(fc.bigInt(1n, bls12_381.fields.Fp.ORDER - 1n), {
minLength: 12,
maxLength: 12,
}),
@@ -224,7 +225,7 @@ for (const c in FIELDS) {
const isSquare = mod.FpIsSquare(Fp);
// Not implemented
if (Fp !== bls12_381.CURVE.Fp12) {
if (Fp !== bls12_381.fields.Fp12) {
should('multiply/sqrt', () => {
fc.assert(
fc.property(FC_BIGINT, (num) => {
@@ -315,7 +316,6 @@ const CURVES = {
secp256k1,
ed25519, ed25519ctx, ed25519ph,
ed448, ed448ph,
starkCurve,
pallas, vesta,
bn254,
jubjub,
@@ -557,6 +557,7 @@ for (const name in CURVES) {
});
}
describe(name, () => {
if (['bn254', 'pallas', 'vesta'].includes(name)) return;
// Generic complex things (getPublicKey/sign/verify/getSharedSecret)
should('.getPublicKey() type check', () => {
throws(() => C.getPublicKey(0), '0');
@@ -745,6 +746,54 @@ should('bigInt private keys', () => {
secp256k1.sign('', 123n);
});
describe('wycheproof curve creation', () => {
const VECTORS = wyche_curves.testGroups[0].tests;
for (const v of VECTORS) {
should(`${v.name}`, () => {
const CURVE = createCurve(
{
Fp: Field(BigInt(`0x${v.p}`)),
a: BigInt(`0x${v.a}`),
b: BigInt(`0x${v.b}`),
n: BigInt(`0x${v.n}`),
h: BigInt(v.h),
Gx: BigInt(`0x${v.gx}`),
Gy: BigInt(`0x${v.gy}`),
},
sha256
);
});
const CURVE = CURVES[v.name];
if (!CURVE) continue;
should(`${v.name} parms verify`, () => {
deepStrictEqual(CURVE.CURVE.Fp.ORDER, BigInt(`0x${v.p}`));
deepStrictEqual(CURVE.CURVE.a, BigInt(`0x${v.a}`));
deepStrictEqual(CURVE.CURVE.b, BigInt(`0x${v.b}`));
deepStrictEqual(CURVE.CURVE.n, BigInt(`0x${v.n}`));
deepStrictEqual(CURVE.CURVE.Gx, BigInt(`0x${v.gx}`));
deepStrictEqual(CURVE.CURVE.Gy, BigInt(`0x${v.gy}`));
deepStrictEqual(CURVE.CURVE.h, BigInt(v.h));
});
}
});
should('validate generator point is on curve', () => {
throws(() =>
createCurve(
{
Fp: Field(BigInt(`0x00c302f41d932a36cda7a3463093d18db78fce476de1a86297`)),
a: BigInt(`0x00c302f41d932a36cda7a3463093d18db78fce476de1a86294`),
b: BigInt(`0x13d56ffaec78681e68f9deb43b35bec2fb68542e27897b79`),
n: BigInt(`0x00c302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1`),
h: BigInt(1),
Gx: BigInt(`0x3ae9e58c82f63c30282e1fe7bbf43fa72c446af6f4618129`),
Gy: BigInt(`0x097e2c5667c2223a902ab5ca449d0084b7e5b3de7ccc01c8`), // last 9 -> 8
},
sha256
)
);
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {

View File

@@ -1,18 +1,14 @@
import { bls12_381 } from '../lib/esm/bls12-381.js';
import { describe, should } from 'micro-should';
import { deepStrictEqual, notDeepStrictEqual, throws } from 'assert';
import { sha512 } from '@noble/hashes/sha512';
import * as fc from 'fast-check';
import { readFileSync } from 'fs';
import { describe, should } from 'micro-should';
import { wNAF } from '../esm/abstract/curve.js';
import { bytesToHex, utf8ToBytes } from '../esm/abstract/utils.js';
import { hash_to_field } from '../esm/abstract/hash-to-curve.js';
import { bls12_381 as bls } from '../esm/bls12-381.js';
import zkVectors from './bls12-381/zkcrypto/converted.json' assert { type: 'json' };
import pairingVectors from './bls12-381/go_pairing_vectors/pairing.json' assert { type: 'json' };
import { wNAF } from '../lib/esm/abstract/curve.js';
const bls = bls12_381;
const { Fp2 } = bls;
const G1Point = bls.G1.ProjectivePoint;
const G2Point = bls.G2.ProjectivePoint;
const G1Aff = (x, y) => G1Point.fromAffine({ x, y });
const G2_VECTORS = readFileSync('./test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
.trim()
.split('\n')
@@ -28,8 +24,10 @@ const SCALAR_VECTORS = readFileSync('./test/bls12-381/bls12-381-scalar-test-vect
const NUM_RUNS = Number(process.env.RUNS_COUNT || 10); // reduce to 1 to shorten test time
fc.configureGlobal({ numRuns: NUM_RUNS });
// @ts-ignore
const CURVE_ORDER = bls.CURVE.r;
const G1Point = bls.G1.ProjectivePoint;
const G2Point = bls.G2.ProjectivePoint;
const G1Aff = (x, y) => G1Point.fromAffine({ x, y });
const CURVE_ORDER = bls.params.r;
const FC_MSG = fc.hexaString({ minLength: 64, maxLength: 64 });
const FC_MSG_5 = fc.array(FC_MSG, { minLength: 5, maxLength: 5 });
@@ -43,10 +41,10 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
function equal(a, b, comment) {
deepStrictEqual(a.equals(b), true, `eq(${comment})`);
}
const { Fp, Fp2 } = bls.fields;
// Fp
describe('bls12-381 Fp', () => {
const Fp = bls.Fp;
const FC_BIGINT = fc.bigInt(1n, Fp.ORDER - 1n);
should('multiply/sqrt', () => {
@@ -61,8 +59,7 @@ describe('bls12-381 Fp', () => {
// Fp2
describe('bls12-381 Fp2', () => {
const Fp = bls.Fp;
const Fp2 = bls.Fp2;
const { Fp, Fp2 } = bls.fields;
const FC_BIGINT = fc.bigInt(1n, Fp.ORDER - 1n);
const FC_BIGINT_2 = fc.array(FC_BIGINT, { minLength: 2, maxLength: 2 });
@@ -150,7 +147,7 @@ describe('bls12-381 Fp2', () => {
// Point
describe('bls12-381 Point', () => {
const Fp = bls.Fp;
const { Fp } = bls.fields;
const FC_BIGINT = fc.bigInt(1n, Fp.ORDER - 1n);
const PointG1 = G1Point;
const PointG2 = G2Point;
@@ -558,9 +555,12 @@ describe('bls12-381 Point', () => {
];
// Use wNAF allow scalars higher than CURVE.r
const w = wNAF(G2Point, 1);
const hEff = BigInt(
'0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'
);
for (let p of points) {
const ours = p.clearCofactor();
const shouldBe = w.unsafeLadder(p, bls.CURVE.G2.hEff);
const shouldBe = w.unsafeLadder(p, hEff);
deepStrictEqual(ours.equals(shouldBe), true, 'clearLast');
}
});
@@ -578,12 +578,12 @@ describe('bls12-381/basic', () => {
deepStrictEqual(g1.x, G1Point.ZERO.x);
deepStrictEqual(g1.y, G1Point.ZERO.y);
// Test Non-Zero
const x = bls.Fp.create(
const x = Fp.create(
BigInt(
'0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
)
);
const y = bls.Fp.create(
const y = Fp.create(
BigInt(
'0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'
)
@@ -604,12 +604,12 @@ describe('bls12-381/basic', () => {
deepStrictEqual(g1.x, G1Point.ZERO.x);
deepStrictEqual(g1.y, G1Point.ZERO.y);
// Test Non-Zero
const x = bls.Fp.create(
const x = Fp.create(
BigInt(
'0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
)
);
const y = bls.Fp.create(
const y = Fp.create(
BigInt(
'0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'
)
@@ -690,12 +690,12 @@ describe('bls12-381/basic', () => {
// Test Zero
deepStrictEqual(G1Point.ZERO.toHex(false), B_192_40);
// Test Non-Zero
const x = bls.Fp.create(
const x = Fp.create(
BigInt(
'0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
)
);
const y = bls.Fp.create(
const y = Fp.create(
BigInt(
'0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'
)
@@ -711,12 +711,12 @@ describe('bls12-381/basic', () => {
// Test Zero
deepStrictEqual(G1Point.ZERO.toHex(false), B_192_40);
// Test Non-Zero
const x = bls.Fp.create(
const x = Fp.create(
BigInt(
'0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
)
);
const y = bls.Fp.create(
const y = Fp.create(
BigInt(
'0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'
)
@@ -802,32 +802,32 @@ describe('bls12-381/basic', () => {
throws(() => G2Point.fromPrivateKey(0n));
});
const VALID_G1 = new G1Point(
bls.Fp.create(
Fp.create(
3609742242174788176010452839163620388872641749536604986743596621604118973777515189035770461528205168143692110933639n
),
bls.Fp.create(
Fp.create(
1619277690257184054444116778047375363103842303863153349133480657158810226683757397206929105479676799650932070320089n
),
bls.Fp.create(1n)
Fp.create(1n)
);
const VALID_G1_2 = new G1Point(
bls.Fp.create(
Fp.create(
1206972466279728255044019580914616126536509750250979180256809997983196363639429409634110400978470384566664128085207n
),
bls.Fp.create(
Fp.create(
2991142246317096160788653339959532007292638191110818490939476869616372888657136539642598243964263069435065725313423n
),
bls.Fp.create(1n)
Fp.create(1n)
);
const INVALID_G1 = new G1Point(
bls.Fp.create(
Fp.create(
499001545268060011619089734015590154568173930614466321429631711131511181286230338880376679848890024401335766847607n
),
bls.Fp.create(
Fp.create(
3934582309586258715640230772291917282844636728991757779640464479794033391537662970190753981664259511166946374555673n
),
bls.Fp.create(1n)
Fp.create(1n)
);
should('aggregate pubkeys', () => {
@@ -851,20 +851,20 @@ describe('bls12-381/basic', () => {
for (let vector of G2_VECTORS) {
const [priv, msg, expected] = vector;
const sig = bls.sign(msg, priv);
deepStrictEqual(bls.utils.bytesToHex(sig), expected);
deepStrictEqual(bytesToHex(sig), expected);
}
});
should(`produce correct scalars (${SCALAR_VECTORS.length} vectors)`, () => {
const options = {
p: bls.CURVE.r,
p: bls.params.r,
m: 1,
expand: false,
expand: '_internal_pass',
};
for (let vector of SCALAR_VECTORS) {
const [okmAscii, expectedHex] = vector;
const expected = BigInt('0x' + expectedHex);
const okm = new Uint8Array(okmAscii.split('').map((c) => c.charCodeAt(0)));
const scalars = bls.utils.hashToField(okm, 1, options);
const okm = utf8ToBytes(okmAscii);
const scalars = hash_to_field(okm, 1, Object.assign({}, bls.G2.CURVE.htfDefaults, options));
deepStrictEqual(scalars[0][0], expected);
}
});
@@ -872,7 +872,8 @@ describe('bls12-381/basic', () => {
// Pairing
describe('pairing', () => {
const { pairing, Fp12 } = bls;
const { pairing } = bls;
const { Fp12 } = bls.fields;
const G1 = G1Point.BASE;
const G2 = G2Point.BASE;
@@ -969,29 +970,29 @@ describe('pairing', () => {
});
});
// hashToCurve
describe('hash-to-curve', () => {
describe('hash-to-curve (against Killic)', () => {
// Point G1
const VECTORS_G1 = [
{
msg: bls.utils.stringToBytes(''),
msg: utf8ToBytes(''),
expected:
'0576730ab036cbac1d95b38dca905586f28d0a59048db4e8778782d89bff856ddef89277ead5a21e2975c4a6e3d8c79e' +
'1273e568bebf1864393c517f999b87c1eaa1b8432f95aea8160cd981b5b05d8cd4a7cf00103b6ef87f728e4b547dd7ae',
},
{
msg: bls.utils.stringToBytes('abc'),
msg: utf8ToBytes('abc'),
expected:
'061daf0cc00d8912dac1d4cf5a7c32fca97f8b3bf3f805121888e5eb89f77f9a9f406569027ac6d0e61b1229f42c43d6' +
'0de1601e5ba02cb637c1d35266f5700acee9850796dc88e860d022d7b9e7e3dce5950952e97861e5bb16d215c87f030d',
},
{
msg: bls.utils.stringToBytes('abcdef0123456789'),
msg: utf8ToBytes('abcdef0123456789'),
expected:
'0fb3455436843e76079c7cf3dfef75e5a104dfe257a29a850c145568d500ad31ccfe79be9ae0ea31a722548070cf98cd' +
'177989f7e2c751658df1b26943ee829d3ebcf131d8f805571712f3a7527ee5334ecff8a97fc2a50cea86f5e6212e9a57',
},
{
msg: bls.utils.stringToBytes(
msg: utf8ToBytes(
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
),
expected:
@@ -999,37 +1000,38 @@ describe('hash-to-curve', () => {
'047a85d6898416a0899e26219bca7c4f0fa682717199de196b02b95eaf9fb55456ac3b810e78571a1b7f5692b7c58ab6',
},
];
describe('hashToCurve G1', () => {
for (let i = 0; i < VECTORS_G1.length; i++) {
const t = VECTORS_G1[i];
should(`hashToCurve/G1 Killic (${i})`, () => {
const p = bls.hashToCurve.G1.hashToCurve(t.msg, {
should(`${i}`, () => {
const p = bls.G1.hashToCurve(t.msg, {
DST: 'BLS12381G1_XMD:SHA-256_SSWU_RO_TESTGEN',
});
deepStrictEqual(p.toHex(false), t.expected);
});
}
});
const VECTORS_ENCODE_G1 = [
{
msg: bls.utils.stringToBytes(''),
msg: utf8ToBytes(''),
expected:
'1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c' +
'0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5',
},
{
msg: bls.utils.stringToBytes('abc'),
msg: utf8ToBytes('abc'),
expected:
'179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6' +
'0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4',
},
{
msg: bls.utils.stringToBytes('abcdef0123456789'),
msg: utf8ToBytes('abcdef0123456789'),
expected:
'15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af' +
'0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788',
},
{
msg: bls.utils.stringToBytes(
msg: utf8ToBytes(
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
),
expected:
@@ -1037,19 +1039,21 @@ describe('hash-to-curve', () => {
'094bfdfe3e552447433b5a00967498a3f1314b86ce7a7164c8a8f4131f99333b30a574607e301d5f774172c627fd0bca',
},
];
describe('encodeToCurve G1', () => {
for (let i = 0; i < VECTORS_ENCODE_G1.length; i++) {
const t = VECTORS_ENCODE_G1[i];
should(`hashToCurve/G1 (Killic, encodeToCurve) (${i})`, () => {
const p = bls.hashToCurve.G1.encodeToCurve(t.msg, {
should(`(${i})`, () => {
const p = bls.G1.encodeToCurve(t.msg, {
DST: 'BLS12381G1_XMD:SHA-256_SSWU_NU_TESTGEN',
});
deepStrictEqual(p.toHex(false), t.expected);
});
}
});
// Point G2
const VECTORS_G2 = [
{
msg: bls.utils.stringToBytes(''),
msg: utf8ToBytes(''),
expected:
'0fbdae26f9f9586a46d4b0b70390d09064ef2afe5c99348438a3c7d9756471e015cb534204c1b6824617a85024c772dc' +
'0a650bd36ae7455cb3fe5d8bb1310594551456f5c6593aec9ee0c03d2f6cb693bd2c5e99d4e23cbaec767609314f51d3' +
@@ -1057,7 +1061,7 @@ describe('hash-to-curve', () => {
'0d8d49e7737d8f9fc5cef7c4b8817633103faf2613016cb86a1f3fc29968fe2413e232d9208d2d74a89bf7a48ac36f83',
},
{
msg: bls.utils.stringToBytes('abc'),
msg: utf8ToBytes('abc'),
expected:
'03578447618463deb106b60e609c6f7cc446dc6035f84a72801ba17c94cd800583b493b948eff0033f09086fdd7f6175' +
'1953ce6d4267939c7360756d9cca8eb34aac4633ef35369a7dc249445069888e7d1b3f9d2e75fbd468fbcbba7110ea02' +
@@ -1065,7 +1069,7 @@ describe('hash-to-curve', () => {
'0882ab045b8fe4d7d557ebb59a63a35ac9f3d312581b509af0f8eaa2960cbc5e1e36bb969b6e22980b5cbdd0787fcf4e',
},
{
msg: bls.utils.stringToBytes('abcdef0123456789'),
msg: utf8ToBytes('abcdef0123456789'),
expected:
'195fad48982e186ce3c5c82133aefc9b26d55979b6f530992a8849d4263ec5d57f7a181553c8799bcc83da44847bdc8d' +
'17b461fc3b96a30c2408958cbfa5f5927b6063a8ad199d5ebf2d7cdeffa9c20c85487204804fab53f950b2f87db365aa' +
@@ -1073,7 +1077,7 @@ describe('hash-to-curve', () => {
'174a3473a3af2d0302b9065e895ca4adba4ece6ce0b41148ba597001abb152f852dd9a96fb45c9de0a43d944746f833e',
},
{
msg: bls.utils.stringToBytes(
msg: utf8ToBytes(
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
),
expected:
@@ -1083,19 +1087,20 @@ describe('hash-to-curve', () => {
'15c1d4f1a685bb63ee67ca1fd96155e3d091e852a684b78d085fd34f6091e5249ddddbdcf2e7ec82ce6c04c63647eeb7',
},
];
describe('hashToCurve G2', () => {
for (let i = 0; i < VECTORS_G2.length; i++) {
const t = VECTORS_G2[i];
should(`hashToCurve/G2 Killic (${i})`, () => {
const p = bls.hashToCurve.G2.hashToCurve(t.msg, {
should(`${i}`, () => {
const p = bls.G2.hashToCurve(t.msg, {
DST: 'BLS12381G2_XMD:SHA-256_SSWU_RO_TESTGEN',
});
deepStrictEqual(p.toHex(false), t.expected);
});
}
});
const VECTORS_ENCODE_G2 = [
{
msg: bls.utils.stringToBytes(''),
msg: utf8ToBytes(''),
expected:
'0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8' +
'027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d' +
@@ -1103,7 +1108,7 @@ describe('hash-to-curve', () => {
'053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7',
},
{
msg: bls.utils.stringToBytes('abc'),
msg: utf8ToBytes('abc'),
expected:
'18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778' +
'09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b' +
@@ -1111,7 +1116,7 @@ describe('hash-to-curve', () => {
'02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811',
},
{
msg: bls.utils.stringToBytes('abcdef0123456789'),
msg: utf8ToBytes('abcdef0123456789'),
expected:
'19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163' +
'149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7' +
@@ -1119,7 +1124,7 @@ describe('hash-to-curve', () => {
'04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551',
},
{
msg: bls.utils.stringToBytes(
msg: utf8ToBytes(
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
),
expected:
@@ -1129,16 +1134,18 @@ describe('hash-to-curve', () => {
'09e5c8242dd7281ad32c03fe4af3f19167770016255fb25ad9b67ec51d62fade31a1af101e8f6172ec2ee8857662be3a',
},
];
describe('encodeToCurve G2', () => {
for (let i = 0; i < VECTORS_ENCODE_G2.length; i++) {
const t = VECTORS_ENCODE_G2[i];
should(`hashToCurve/G2 (Killic, encodeToCurve) (${i})`, () => {
const p = bls.hashToCurve.G2.encodeToCurve(t.msg, {
should(`${i}`, () => {
const p = bls.G2.encodeToCurve(t.msg, {
DST: 'BLS12381G2_XMD:SHA-256_SSWU_NU_TESTGEN',
});
deepStrictEqual(p.toHex(false), t.expected);
});
}
});
});
describe('verify()', () => {
should('verify signed message', () => {
@@ -1260,12 +1267,12 @@ describe('bls12-381 deterministic', () => {
.reverse()
.reduce((acc, i) => acc + i);
const Fp12 = bls.Fp12;
const { Fp12 } = bls.fields;
should('Killic based/Pairing', () => {
const t = bls.pairing(G1Point.BASE, G2Point.BASE);
deepStrictEqual(
bls.utils.bytesToHex(Fp12.toBytes(t)),
bytesToHex(Fp12.toBytes(t)),
killicHex([
'0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631',
'04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef',
@@ -1287,7 +1294,7 @@ describe('bls12-381 deterministic', () => {
let p2 = G2Point.BASE;
for (let v of pairingVectors) {
deepStrictEqual(
bls.utils.bytesToHex(Fp12.toBytes(bls.pairing(p1, p2))),
bytesToHex(Fp12.toBytes(bls.pairing(p1, p2))),
// Reverse order
v.match(/.{96}/g).reverse().join('')
);

362
test/ed25519-addons.test.js Normal file
View File

@@ -0,0 +1,362 @@
import { sha512 } from '@noble/hashes/sha512';
import { bytesToHex as hex, hexToBytes } from '@noble/hashes/utils';
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import { bytesToNumberLE, numberToBytesLE } from '../esm/abstract/utils.js';
import { default as x25519vectors } from './wycheproof/x25519_test.json' assert { type: 'json' };
import {
ed25519,
ed25519ctx,
ed25519ph,
edwardsToMontgomeryPub,
edwardsToMontgomeryPriv,
RistrettoPoint,
x25519,
} from '../esm/ed25519.js';
const VECTORS_RFC8032_CTX = [
{
secretKey: '0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6',
publicKey: 'dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292',
message: 'f726936d19c800494e3fdaff20b276a8',
context: '666f6f',
signature:
'55a4cc2f70a54e04288c5f4cd1e45a7b' +
'b520b36292911876cada7323198dd87a' +
'8b36950b95130022907a7fb7c4e9b2d5' +
'f6cca685a587b4b21f4b888e4e7edb0d',
},
{
secretKey: '0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6',
publicKey: 'dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292',
message: 'f726936d19c800494e3fdaff20b276a8',
context: '626172',
signature:
'fc60d5872fc46b3aa69f8b5b4351d580' +
'8f92bcc044606db097abab6dbcb1aee3' +
'216c48e8b3b66431b5b186d1d28f8ee1' +
'5a5ca2df6668346291c2043d4eb3e90d',
},
{
secretKey: '0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6',
publicKey: 'dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292',
message: '508e9e6882b979fea900f62adceaca35',
context: '666f6f',
signature:
'8b70c1cc8310e1de20ac53ce28ae6e72' +
'07f33c3295e03bb5c0732a1d20dc6490' +
'8922a8b052cf99b7c4fe107a5abb5b2c' +
'4085ae75890d02df26269d8945f84b0b',
},
{
secretKey: 'ab9c2853ce297ddab85c993b3ae14bcad39b2c682beabc27d6d4eb20711d6560',
publicKey: '0f1d1274943b91415889152e893d80e93275a1fc0b65fd71b4b0dda10ad7d772',
message: 'f726936d19c800494e3fdaff20b276a8',
context: '666f6f',
signature:
'21655b5f1aa965996b3f97b3c849eafb' +
'a922a0a62992f73b3d1b73106a84ad85' +
'e9b86a7b6005ea868337ff2d20a7f5fb' +
'd4cd10b0be49a68da2b2e0dc0ad8960f',
},
];
describe('RFC8032ctx', () => {
for (let i = 0; i < VECTORS_RFC8032_CTX.length; i++) {
const v = VECTORS_RFC8032_CTX[i];
should(`${i}`, () => {
deepStrictEqual(hex(ed25519ctx.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(
hex(ed25519ctx.sign(v.message, v.secretKey, { context: v.context })),
v.signature
);
deepStrictEqual(
ed25519ctx.verify(v.signature, v.message, v.publicKey, { context: v.context }),
true
);
});
}
});
const VECTORS_RFC8032_PH = [
{
secretKey: '833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42',
publicKey: 'ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf',
message: '616263',
signature:
'98a70222f0b8121aa9d30f813d683f80' +
'9e462b469c7ff87639499bb94e6dae41' +
'31f85042463c2a355a2003d062adf5aa' +
'a10b8c61e636062aaad11c2a26083406',
},
];
describe('RFC8032ph', () => {
for (let i = 0; i < VECTORS_RFC8032_PH.length; i++) {
const v = VECTORS_RFC8032_PH[i];
should(`${i}`, () => {
deepStrictEqual(hex(ed25519ph.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(hex(ed25519ph.sign(v.message, v.secretKey)), v.signature);
deepStrictEqual(ed25519ph.verify(v.signature, v.message, v.publicKey), true);
});
}
});
// x25519
describe('RFC7748 X25519 ECDH', () => {
const rfc7748Mul = [
{
scalar: 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4',
u: 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c',
outputU: 'c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552',
},
{
scalar: '4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d',
u: 'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493',
outputU: '95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957',
},
];
for (let i = 0; i < rfc7748Mul.length; i++) {
const v = rfc7748Mul[i];
should(`scalarMult (${i})`, () => {
deepStrictEqual(hex(x25519.scalarMult(v.scalar, v.u)), v.outputU);
});
}
const rfc7748Iter = [
{ scalar: '422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079', iters: 1 },
{ scalar: '684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51', iters: 1000 },
// { scalar: '7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424', iters: 1000000 },
];
for (let i = 0; i < rfc7748Iter.length; i++) {
const { scalar, iters } = rfc7748Iter[i];
should(`scalarMult iteration x${iters}`, () => {
let k = x25519.GuBytes;
for (let i = 0, u = k; i < iters; i++) [k, u] = [x25519.scalarMult(k, u), k];
deepStrictEqual(hex(k), scalar);
});
}
should('getSharedKey', () => {
const alicePrivate = '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a';
const alicePublic = '8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a';
const bobPrivate = '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb';
const bobPublic = 'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f';
const shared = '4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742';
deepStrictEqual(alicePublic, hex(x25519.getPublicKey(alicePrivate)));
deepStrictEqual(bobPublic, hex(x25519.getPublicKey(bobPrivate)));
deepStrictEqual(hex(x25519.scalarMult(alicePrivate, bobPublic)), shared);
deepStrictEqual(hex(x25519.scalarMult(bobPrivate, alicePublic)), shared);
});
should('X25519/getSharedSecret() should be commutative', () => {
for (let i = 0; i < 512; i++) {
const asec = x25519.utils.randomPrivateKey();
const apub = x25519.getPublicKey(asec);
const bsec = x25519.utils.randomPrivateKey();
const bpub = x25519.getPublicKey(bsec);
try {
deepStrictEqual(x25519.getSharedSecret(asec, bpub), x25519.getSharedSecret(bsec, apub));
} catch (error) {
console.error('not commutative', { asec, apub, bsec, bpub });
throw error;
}
}
});
should('edwardsToMontgomery should produce correct output', () => {
const edSecret = hexToBytes('77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a');
const edPublic = ed25519.getPublicKey(edSecret);
const xPrivate = edwardsToMontgomeryPriv(edSecret);
deepStrictEqual(
hex(xPrivate),
'a8cd44eb8e93319c0570bc11005c0e0189d34ff02f6c17773411ad191293c94f'
);
const xPublic = edwardsToMontgomeryPub(edPublic);
deepStrictEqual(
hex(xPublic),
'ed7749b4d989f6957f3bfde6c56767e988e21c9f8784d91d610011cd553f9b06'
);
});
should('edwardsToMontgomery should produce correct keyPair', () => {
const edSecret = ed25519.utils.randomPrivateKey();
const edPublic = ed25519.getPublicKey(edSecret);
const xSecret = edwardsToMontgomeryPriv(edSecret);
const expectedXPublic = x25519.getPublicKey(xSecret);
const xPublic = edwardsToMontgomeryPub(edPublic);
deepStrictEqual(xPublic, expectedXPublic);
});
should('ECDH through edwardsToMontgomery should be commutative', () => {
const edSecret1 = ed25519.utils.randomPrivateKey();
const edPublic1 = ed25519.getPublicKey(edSecret1);
const edSecret2 = ed25519.utils.randomPrivateKey();
const edPublic2 = ed25519.getPublicKey(edSecret2);
deepStrictEqual(
x25519.getSharedSecret(edwardsToMontgomeryPriv(edSecret1), edwardsToMontgomeryPub(edPublic2)),
x25519.getSharedSecret(edwardsToMontgomeryPriv(edSecret2), edwardsToMontgomeryPub(edPublic1))
);
});
should('base point', () => {
const { y } = ed25519ph.ExtendedPoint.BASE;
const { Fp } = ed25519ph.CURVE;
const u = Fp.create((y + 1n) * Fp.inv(1n - y));
deepStrictEqual(numberToBytesLE(u, 32), x25519.GuBytes);
});
const group = x25519vectors.testGroups[0];
should('wycheproof', () => {
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
const comment = `(${i}, ${v.result}) ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') {
try {
const shared = hex(x25519.scalarMult(v.private, v.public));
deepStrictEqual(shared, v.shared, comment);
} catch (e) {
// We are more strict
if (e.message.includes('Expected valid scalar')) return;
if (e.message.includes('Invalid private or public key received')) return;
throw e;
}
} else if (v.result === 'invalid') {
let failed = false;
try {
x25519.scalarMult(v.private, v.public);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, comment);
} else throw new Error('unknown test result');
}
});
});
function utf8ToBytes(str) {
if (typeof str !== 'string') {
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
}
return new TextEncoder().encode(str);
}
describe('ristretto255', () => {
should('follow the byte encodings of small multiples', () => {
const encodingsOfSmallMultiples = [
// This is the identity point
'0000000000000000000000000000000000000000000000000000000000000000',
// This is the basepoint
'e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76',
// These are small multiples of the basepoint
'6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919',
'94741f5d5d52755ece4f23f044ee27d5d1ea1e2bd196b462166b16152a9d0259',
'da80862773358b466ffadfe0b3293ab3d9fd53c5ea6c955358f568322daf6a57',
'e882b131016b52c1d3337080187cf768423efccbb517bb495ab812c4160ff44e',
'f64746d3c92b13050ed8d80236a7f0007c3b3f962f5ba793d19a601ebb1df403',
'44f53520926ec81fbd5a387845beb7df85a96a24ece18738bdcfa6a7822a176d',
'903293d8f2287ebe10e2374dc1a53e0bc887e592699f02d077d5263cdd55601c',
'02622ace8f7303a31cafc63f8fc48fdc16e1c8c8d234b2f0d6685282a9076031',
'20706fd788b2720a1ed2a5dad4952b01f413bcf0e7564de8cdc816689e2db95f',
'bce83f8ba5dd2fa572864c24ba1810f9522bc6004afe95877ac73241cafdab42',
'e4549ee16b9aa03099ca208c67adafcafa4c3f3e4e5303de6026e3ca8ff84460',
'aa52e000df2e16f55fb1032fc33bc42742dad6bd5a8fc0be0167436c5948501f',
'46376b80f409b29dc2b5f6f0c52591990896e5716f41477cd30085ab7f10301e',
'e0c418f7c8d9c4cdd7395b93ea124f3ad99021bb681dfc3302a9d99a2e53e64e',
];
let B = RistrettoPoint.BASE;
let P = RistrettoPoint.ZERO;
for (const encoded of encodingsOfSmallMultiples) {
deepStrictEqual(P.toHex(), encoded);
deepStrictEqual(RistrettoPoint.fromHex(encoded).toHex(), encoded);
P = P.add(B);
}
});
should('not convert bad bytes encoding', () => {
const badEncodings = [
// These are all bad because they're non-canonical field encodings.
'00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
'f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
'edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// These are all bad because they're negative field elements.
'0100000000000000000000000000000000000000000000000000000000000000',
'01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
'ed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20',
'c34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562',
'c940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78',
'47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24',
'f1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72',
'87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309',
// These are all bad because they give a nonsquare x².
'26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371',
'4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f',
'de6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b',
'bcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042',
'2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08',
'f4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22',
'8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731',
'2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b',
// These are all bad because they give a negative xy value.
'3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e',
'a45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220',
'd483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e',
'8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32',
'32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b',
'227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165',
'5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e',
'445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b',
// This is s = -1, which causes y = 0.
'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
];
for (const badBytes of badEncodings) {
const b = hexToBytes(badBytes);
throws(() => RistrettoPoint.fromHex(b), badBytes);
}
});
should('create right points from uniform hash', () => {
const labels = [
'Ristretto is traditionally a short shot of espresso coffee',
'made with the normal amount of ground coffee but extracted with',
'about half the amount of water in the same amount of time',
'by using a finer grind.',
'This produces a concentrated shot of coffee per volume.',
'Just pulling a normal shot short will produce a weaker shot',
'and is not a Ristretto as some believe.',
];
const encodedHashToPoints = [
'3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46',
'f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b',
'006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826',
'f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a',
'ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179',
'e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628',
'80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065',
];
for (let i = 0; i < labels.length; i++) {
const hash = sha512(utf8ToBytes(labels[i]));
const point = RistrettoPoint.hashToCurve(hash);
deepStrictEqual(point.toHex(), encodedHashToPoints[i]);
}
});
should('have proper equality testing', () => {
const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
const bytes255ToNumberLE = (bytes) =>
ed25519ctx.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
const priv = new Uint8Array([
198, 101, 65, 165, 93, 120, 37, 238, 16, 133, 10, 35, 253, 243, 161, 246, 229, 135, 12, 137,
202, 114, 222, 139, 146, 123, 4, 125, 152, 173, 1, 7,
]);
const pub = RistrettoPoint.BASE.multiply(bytes255ToNumberLE(priv));
deepStrictEqual(pub.equals(RistrettoPoint.ZERO), false);
});
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

2
test/ed25519.helpers.js Normal file
View File

@@ -0,0 +1,2 @@
export { numberToBytesLE } from '../esm/abstract/utils.js';
export { ed25519, ED25519_TORSION_SUBGROUP } from '../esm/ed25519.js';

View File

@@ -1,24 +1,19 @@
import { deepEqual, deepStrictEqual, strictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import * as fc from 'fast-check';
import {
ed25519,
ed25519ctx,
ed25519ph,
x25519,
RistrettoPoint,
ED25519_TORSION_SUBGROUP,
} from '../lib/esm/ed25519.js';
import { deepStrictEqual, strictEqual, throws } from 'assert';
import { readFileSync } from 'fs';
import { bytesToHex, concatBytes, hexToBytes, utf8ToBytes, randomBytes } from '@noble/hashes/utils';
import * as fc from 'fast-check';
import { describe, should } from 'micro-should';
import { ed25519 as ed, ED25519_TORSION_SUBGROUP, numberToBytesLE } from './ed25519.helpers.js';
// Old vectors allow to test sign() because they include private key
import { default as ed25519vectors_OLD } from './ed25519/ed25519_test_OLD.json' assert { type: 'json' };
import { default as ed25519vectors } from './wycheproof/ed25519_test.json' assert { type: 'json' };
import { default as zip215 } from './ed25519/zip215.json' assert { type: 'json' };
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
import { numberToBytesLE } from '../lib/esm/abstract/utils.js';
import { sha512 } from '@noble/hashes/sha512';
import { default as ed25519vectors } from './wycheproof/eddsa_test.json' assert { type: 'json' };
import { default as x25519vectors } from './wycheproof/x25519_test.json' assert { type: 'json' };
import { default as edgeCases } from './ed25519/edge-cases.json' assert { type: 'json' };
// Any changes to the file will need to be aware of the fact
// the file is shared between noble-curves and noble-ed25519.
describe('ed25519', () => {
const ed = ed25519;
const hex = bytesToHex;
const Point = ed.ExtendedPoint;
@@ -27,13 +22,6 @@ describe('ed25519', () => {
return hexToBytes(hex.padStart(64, '0'));
}
function utf8ToBytes(str) {
if (typeof str !== 'string') {
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
}
return new TextEncoder().encode(str);
}
ed.utils.precompute(8);
should('not accept >32byte private keys', () => {
@@ -292,104 +280,6 @@ describe('ed25519', () => {
// // const signature = await ristretto25519.sign(MESSAGE, PRIVATE_KEY);
// // expect(await ristretto25519.verify(signature, WRONG_MESSAGE, publicKey)).toBe(false);
// // });
should('ristretto255/should follow the byte encodings of small multiples', () => {
const encodingsOfSmallMultiples = [
// This is the identity point
'0000000000000000000000000000000000000000000000000000000000000000',
// This is the basepoint
'e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76',
// These are small multiples of the basepoint
'6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919',
'94741f5d5d52755ece4f23f044ee27d5d1ea1e2bd196b462166b16152a9d0259',
'da80862773358b466ffadfe0b3293ab3d9fd53c5ea6c955358f568322daf6a57',
'e882b131016b52c1d3337080187cf768423efccbb517bb495ab812c4160ff44e',
'f64746d3c92b13050ed8d80236a7f0007c3b3f962f5ba793d19a601ebb1df403',
'44f53520926ec81fbd5a387845beb7df85a96a24ece18738bdcfa6a7822a176d',
'903293d8f2287ebe10e2374dc1a53e0bc887e592699f02d077d5263cdd55601c',
'02622ace8f7303a31cafc63f8fc48fdc16e1c8c8d234b2f0d6685282a9076031',
'20706fd788b2720a1ed2a5dad4952b01f413bcf0e7564de8cdc816689e2db95f',
'bce83f8ba5dd2fa572864c24ba1810f9522bc6004afe95877ac73241cafdab42',
'e4549ee16b9aa03099ca208c67adafcafa4c3f3e4e5303de6026e3ca8ff84460',
'aa52e000df2e16f55fb1032fc33bc42742dad6bd5a8fc0be0167436c5948501f',
'46376b80f409b29dc2b5f6f0c52591990896e5716f41477cd30085ab7f10301e',
'e0c418f7c8d9c4cdd7395b93ea124f3ad99021bb681dfc3302a9d99a2e53e64e',
];
let B = RistrettoPoint.BASE;
let P = RistrettoPoint.ZERO;
for (const encoded of encodingsOfSmallMultiples) {
deepStrictEqual(P.toHex(), encoded);
deepStrictEqual(RistrettoPoint.fromHex(encoded).toHex(), encoded);
P = P.add(B);
}
});
should('ristretto255/should not convert bad bytes encoding', () => {
const badEncodings = [
// These are all bad because they're non-canonical field encodings.
'00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
'f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
'edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
// These are all bad because they're negative field elements.
'0100000000000000000000000000000000000000000000000000000000000000',
'01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
'ed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20',
'c34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562',
'c940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78',
'47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24',
'f1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72',
'87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309',
// These are all bad because they give a nonsquare x².
'26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371',
'4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f',
'de6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b',
'bcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042',
'2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08',
'f4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22',
'8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731',
'2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b',
// These are all bad because they give a negative xy value.
'3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e',
'a45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220',
'd483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e',
'8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32',
'32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b',
'227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165',
'5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e',
'445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b',
// This is s = -1, which causes y = 0.
'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
];
for (const badBytes of badEncodings) {
const b = hexToBytes(badBytes);
throws(() => RistrettoPoint.fromHex(b), badBytes);
}
});
should('ristretto255/should create right points from uniform hash', () => {
const labels = [
'Ristretto is traditionally a short shot of espresso coffee',
'made with the normal amount of ground coffee but extracted with',
'about half the amount of water in the same amount of time',
'by using a finer grind.',
'This produces a concentrated shot of coffee per volume.',
'Just pulling a normal shot short will produce a weaker shot',
'and is not a Ristretto as some believe.',
];
const encodedHashToPoints = [
'3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46',
'f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b',
'006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826',
'f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a',
'ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179',
'e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628',
'80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065',
];
for (let i = 0; i < labels.length; i++) {
const hash = sha512(utf8ToBytes(labels[i]));
const point = RistrettoPoint.hashToCurve(hash);
deepStrictEqual(point.toHex(), encodedHashToPoints[i]);
}
});
should('input immutability: sign/verify are immutable', () => {
const privateKey = ed.utils.randomPrivateKey();
@@ -413,7 +303,8 @@ describe('ed25519', () => {
// https://zips.z.cash/zip-0215
// Vectors from https://gist.github.com/hdevalence/93ed42d17ecab8e42138b213812c8cc7
should('ZIP-215 compliance tests/should pass all of them', () => {
describe('ZIP215', () => {
should('pass all compliance tests', () => {
const str = utf8ToBytes('Zcash');
for (let v of zip215) {
let noble = false;
@@ -425,56 +316,12 @@ describe('ed25519', () => {
deepStrictEqual(noble, v.valid_zip215, JSON.stringify(v));
}
});
should('ZIP-215 compliance tests/disallows sig.s >= CURVE.n', () => {
should('disallow sig.s >= CURVE.n', () => {
// sig.R = BASE, sig.s = N+1
const sig =
'5866666666666666666666666666666666666666666666666666666666666666eed3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010';
throws(() => ed.verify(sig, 'deadbeef', Point.BASE));
deepStrictEqual(ed.verify(sig, 'deadbeef', Point.BASE), false);
});
const rfc7748Mul = [
{
scalar: 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4',
u: 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c',
outputU: 'c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552',
},
{
scalar: '4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d',
u: 'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493',
outputU: '95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957',
},
];
for (let i = 0; i < rfc7748Mul.length; i++) {
const v = rfc7748Mul[i];
should(`RFC7748: scalarMult (${i})`, () => {
deepStrictEqual(hex(x25519.scalarMult(v.scalar, v.u)), v.outputU);
});
}
const rfc7748Iter = [
{ scalar: '422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079', iters: 1 },
{ scalar: '684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51', iters: 1000 },
// { scalar: '7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424', iters: 1000000 },
];
for (let i = 0; i < rfc7748Iter.length; i++) {
const { scalar, iters } = rfc7748Iter[i];
should(`RFC7748: scalarMult iteration (${i})`, () => {
let k = x25519.Gu;
for (let i = 0, u = k; i < iters; i++) [k, u] = [x25519.scalarMult(k, u), k];
deepStrictEqual(hex(k), scalar);
});
}
should('RFC7748 getSharedKey', () => {
const alicePrivate = '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a';
const alicePublic = '8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a';
const bobPrivate = '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb';
const bobPublic = 'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f';
const shared = '4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742';
deepStrictEqual(alicePublic, hex(x25519.getPublicKey(alicePrivate)));
deepStrictEqual(bobPublic, hex(x25519.getPublicKey(bobPrivate)));
deepStrictEqual(hex(x25519.scalarMult(alicePrivate, bobPublic)), shared);
deepStrictEqual(hex(x25519.scalarMult(bobPrivate, alicePublic)), shared);
});
// should('X25519/getSharedSecret() should be commutative', () => {
@@ -499,38 +346,9 @@ describe('ed25519', () => {
// );
// });
{
const group = x25519vectors.testGroups[0];
should(`Wycheproof/X25519`, () => {
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
const comment = `(${i}, ${v.result}) ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') {
try {
const shared = hex(x25519.scalarMult(v.private, v.public));
deepStrictEqual(shared, v.shared, comment);
} catch (e) {
// We are more strict
if (e.message.includes('Expected valid scalar')) return;
if (e.message.includes('Invalid private or public key received')) return;
throw e;
}
} else if (v.result === 'invalid') {
let failed = false;
try {
x25519.scalarMult(v.private, v.public);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, comment);
} else throw new Error('unknown test result');
}
});
}
should(`Wycheproof/ED25519`, () => {
for (let g = 0; g < ed25519vectors.testGroups.length; g++) {
const group = ed25519vectors.testGroups[g];
should(`wycheproof/ED25519 (OLD)`, () => {
for (let g = 0; g < ed25519vectors_OLD.testGroups.length; g++) {
const group = ed25519vectors_OLD.testGroups[g];
const key = group.key;
deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk, `(${g}, public)`);
for (let i = 0; i < group.tests.length; i++) {
@@ -552,98 +370,35 @@ describe('ed25519', () => {
}
});
should('Property test issue #1', () => {
should(`wycheproof/ED25519`, () => {
for (let g = 0; g < ed25519vectors.testGroups.length; g++) {
const group = ed25519vectors.testGroups[g];
const key = group.publicKey;
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
const comment = `(${g}/${i}, ${v.result}): ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') {
deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true, comment);
} else if (v.result === 'invalid') {
let failed = false;
try {
failed = !ed.verify(v.sig, v.msg, key.pk);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, comment);
} else throw new Error('unknown test result');
}
}
});
should('not mutate inputs', () => {
const message = new Uint8Array([12, 12, 12]);
const signature = ed.sign(message, to32Bytes(1n));
const publicKey = ed.getPublicKey(to32Bytes(1n)); // <- was 1n
deepStrictEqual(ed.verify(signature, message, publicKey), true);
});
const VECTORS_RFC8032_CTX = [
{
secretKey: '0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6',
publicKey: 'dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292',
message: 'f726936d19c800494e3fdaff20b276a8',
context: '666f6f',
signature:
'55a4cc2f70a54e04288c5f4cd1e45a7b' +
'b520b36292911876cada7323198dd87a' +
'8b36950b95130022907a7fb7c4e9b2d5' +
'f6cca685a587b4b21f4b888e4e7edb0d',
},
{
secretKey: '0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6',
publicKey: 'dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292',
message: 'f726936d19c800494e3fdaff20b276a8',
context: '626172',
signature:
'fc60d5872fc46b3aa69f8b5b4351d580' +
'8f92bcc044606db097abab6dbcb1aee3' +
'216c48e8b3b66431b5b186d1d28f8ee1' +
'5a5ca2df6668346291c2043d4eb3e90d',
},
{
secretKey: '0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6',
publicKey: 'dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292',
message: '508e9e6882b979fea900f62adceaca35',
context: '666f6f',
signature:
'8b70c1cc8310e1de20ac53ce28ae6e72' +
'07f33c3295e03bb5c0732a1d20dc6490' +
'8922a8b052cf99b7c4fe107a5abb5b2c' +
'4085ae75890d02df26269d8945f84b0b',
},
{
secretKey: 'ab9c2853ce297ddab85c993b3ae14bcad39b2c682beabc27d6d4eb20711d6560',
publicKey: '0f1d1274943b91415889152e893d80e93275a1fc0b65fd71b4b0dda10ad7d772',
message: 'f726936d19c800494e3fdaff20b276a8',
context: '666f6f',
signature:
'21655b5f1aa965996b3f97b3c849eafb' +
'a922a0a62992f73b3d1b73106a84ad85' +
'e9b86a7b6005ea868337ff2d20a7f5fb' +
'd4cd10b0be49a68da2b2e0dc0ad8960f',
},
];
for (let i = 0; i < VECTORS_RFC8032_CTX.length; i++) {
const v = VECTORS_RFC8032_CTX[i];
should(`RFC8032ctx/${i}`, () => {
deepStrictEqual(hex(ed25519ctx.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(hex(ed25519ctx.sign(v.message, v.secretKey, v.context)), v.signature);
deepStrictEqual(ed25519ctx.verify(v.signature, v.message, v.publicKey, v.context), true);
});
}
const VECTORS_RFC8032_PH = [
{
secretKey: '833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42',
publicKey: 'ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf',
message: '616263',
signature:
'98a70222f0b8121aa9d30f813d683f80' +
'9e462b469c7ff87639499bb94e6dae41' +
'31f85042463c2a355a2003d062adf5aa' +
'a10b8c61e636062aaad11c2a26083406',
},
];
for (let i = 0; i < VECTORS_RFC8032_PH.length; i++) {
const v = VECTORS_RFC8032_PH[i];
should(`RFC8032ph/${i}`, () => {
deepStrictEqual(hex(ed25519ph.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(hex(ed25519ph.sign(v.message, v.secretKey)), v.signature);
deepStrictEqual(ed25519ph.verify(v.signature, v.message, v.publicKey), true);
});
}
should('X25519 base point', () => {
const { y } = ed25519.ExtendedPoint.BASE;
const { Fp } = ed25519.CURVE;
const u = Fp.create((y + 1n) * Fp.inv(1n - y));
deepStrictEqual(hex(numberToBytesLE(u, 32)), x25519.Gu);
});
should('isTorsionFree()', () => {
const orig = ed.utils.getExtendedPublicKey(ed.utils.randomPrivateKey()).point;
for (const hex of ED25519_TORSION_SUBGROUP.slice(1)) {
@@ -654,16 +409,43 @@ describe('ed25519', () => {
strictEqual(cleared.isTorsionFree(), true, `cleared must be torsionFree: ${hex}`);
}
});
should('have strict SUF-CMA and SBS properties', () => {
// https://eprint.iacr.org/2020/1244
const list = [0, 1, 6, 7, 8, 9, 10, 11].map((i) => edgeCases[i]);
for (let v of list) {
const result = ed.verify(v.signature, v.message, v.pub_key, { zip215: false });
strictEqual(result, false, `zip215: false must not validate: ${v.signature}`);
}
});
should('ed25519 bug', () => {
should('not verify when sig.s >= CURVE.n', () => {
const privateKey = ed.utils.randomPrivateKey();
const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);
const publicKey = ed.getPublicKey(privateKey);
const signature = ed.sign(message, privateKey);
const R = signature.slice(0, 32);
let s = signature.slice(32, 64);
s = bytesToHex(s.slice().reverse());
s = BigInt('0x' + s);
s = s + ed.CURVE.n;
s = numberToBytesLE(s, 32);
const sig_invalid = concatBytes(R, s);
deepStrictEqual(ed.verify(sig_invalid, message, publicKey), false);
});
should('not accept point without z, t', () => {
const t = 81718630521762619991978402609047527194981150691135404693881672112315521837062n;
const point = ed25519.ExtendedPoint.fromAffine({ x: t, y: t });
const point = Point.fromAffine({ x: t, y: t });
throws(() => point.assertValidity());
// Otherwise (without assertValidity):
// const point2 = point.double();
// point2.toAffine(); // crash!
});
});
// ESM is broken.
import url from 'url';

View File

@@ -0,0 +1 @@
[{"message":"8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6","pub_key":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa","signature":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000"},{"message":"9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79","pub_key":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa","signature":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"},{"message":"aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e"},{"message":"9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009"},{"message":"e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09"},{"message":"e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405"},{"message":"85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40","pub_key":"442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623","signature":"e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514"},{"message":"85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40","pub_key":"442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623","signature":"8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22"},{"message":"9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f"},{"message":"9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908"},{"message":"e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b","pub_key":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","signature":"a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"},{"message":"39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f","pub_key":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","signature":"a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"}]

View File

@@ -1,9 +1,11 @@
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import * as fc from 'fast-check';
import { ed448, ed448ph, x448 } from '../lib/esm/ed448.js';
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
import { numberToBytesLE } from '../lib/esm/abstract/utils.js';
import { ed448, ed448ph, x448 } from '../esm/ed448.js';
import { bytesToHex, concatBytes, hexToBytes, randomBytes } from '@noble/hashes/utils';
import { numberToBytesLE } from '../esm/abstract/utils.js';
// Old vectors allow to test sign() because they include private key
import { default as ed448vectorsOld } from './ed448/ed448_test_OLD.json' assert { type: 'json' };
import { default as ed448vectors } from './wycheproof/ed448_test.json' assert { type: 'json' };
import { default as x448vectors } from './wycheproof/x448_test.json' assert { type: 'json' };
@@ -439,9 +441,9 @@ describe('ed448', () => {
}
});
describe('wycheproof', () => {
for (let g = 0; g < ed448vectors.testGroups.length; g++) {
const group = ed448vectors.testGroups[g];
describe('wycheproof (OLD)', () => {
for (let g = 0; g < ed448vectorsOld.testGroups.length; g++) {
const group = ed448vectorsOld.testGroups[g];
const key = group.key;
should(`ED448(${g}, public)`, () => {
deepStrictEqual(hex(ed.getPublicKey(key.sk)), key.pk);
@@ -467,92 +469,20 @@ describe('ed448', () => {
}
});
// ECDH
const rfc7748Mul = [
{
scalar:
'3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3',
u: '06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086',
outputU:
'ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f',
},
{
scalar:
'203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f',
u: '0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db',
outputU:
'884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d',
},
];
describe('RFC7748', () => {
for (let i = 0; i < rfc7748Mul.length; i++) {
const v = rfc7748Mul[i];
should(`scalarMult (${i})`, () => {
deepStrictEqual(hex(x448.scalarMult(v.scalar, v.u)), v.outputU);
});
}
});
const rfc7748Iter = [
{
scalar:
'3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113',
iters: 1,
},
{
scalar:
'aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38',
iters: 1000,
},
// { scalar: '077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37', iters: 1000000 },
];
for (let i = 0; i < rfc7748Iter.length; i++) {
const { scalar, iters } = rfc7748Iter[i];
should(`RFC7748: scalarMult iteration (${i})`, () => {
let k = x448.Gu;
for (let i = 0, u = k; i < iters; i++) [k, u] = [x448.scalarMult(k, u), k];
deepStrictEqual(hex(k), scalar);
});
}
should('RFC7748 getSharedKey', () => {
const alicePrivate =
'9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b';
const alicePublic =
'9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0';
const bobPrivate =
'1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d';
const bobPublic =
'3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609';
const shared =
'07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d';
deepStrictEqual(alicePublic, hex(x448.getPublicKey(alicePrivate)));
deepStrictEqual(bobPublic, hex(x448.getPublicKey(bobPrivate)));
deepStrictEqual(hex(x448.scalarMult(alicePrivate, bobPublic)), shared);
deepStrictEqual(hex(x448.scalarMult(bobPrivate, alicePublic)), shared);
});
describe('wycheproof', () => {
const group = x448vectors.testGroups[0];
should(`X448`, () => {
for (let g = 0; g < ed448vectors.testGroups.length; g++) {
const group = ed448vectors.testGroups[g];
const key = group.publicKey;
should(`ED448`, () => {
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
const index = `(${i}, ${v.result}) ${v.comment}`;
const index = `${g}/${i} ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') {
try {
const shared = hex(x448.scalarMult(v.private, v.public));
deepStrictEqual(shared, v.shared, index);
} catch (e) {
// We are more strict
if (e.message.includes('Expected valid scalar')) return;
if (e.message.includes('Invalid private or public key received')) return;
if (e.message.includes('Expected 56 bytes')) return;
throw e;
}
deepStrictEqual(ed.verify(v.sig, v.msg, key.pk), true, index);
} else if (v.result === 'invalid') {
let failed = false;
try {
x448.scalarMult(v.private, v.public);
failed = !ed.verify(v.sig, v.msg, key.pk);
} catch (error) {
failed = true;
}
@@ -560,8 +490,8 @@ describe('ed448', () => {
} else throw new Error('unknown test result');
}
});
}
});
// should('X448: should convert base point to montgomery using fromPoint', () => {
// deepStrictEqual(
// hex(ed.montgomeryCurve.UfromPoint(Point.BASE)),
@@ -584,6 +514,7 @@ describe('ed448', () => {
// }
// });
describe('ed448ctx', () => {
const VECTORS_RFC8032_CTX = [
{
secretKey:
@@ -603,16 +534,20 @@ describe('ed448', () => {
'3c00',
},
];
for (let i = 0; i < VECTORS_RFC8032_CTX.length; i++) {
const v = VECTORS_RFC8032_CTX[i];
should(`RFC8032ctx/${i}`, () => {
should(`${i}`, () => {
deepStrictEqual(hex(ed.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(hex(ed.sign(v.message, v.secretKey, v.context)), v.signature);
deepStrictEqual(ed.verify(v.signature, v.message, v.publicKey, v.context), true);
deepStrictEqual(hex(ed.sign(v.message, v.secretKey, { context: v.context })), v.signature);
deepStrictEqual(
ed.verify(v.signature, v.message, v.publicKey, { context: v.context }),
true
);
});
}
});
describe('ed448ph', () => {
const VECTORS_RFC8032_PH = [
{
secretKey:
@@ -648,23 +583,154 @@ describe('ed448', () => {
'2100',
},
];
for (let i = 0; i < VECTORS_RFC8032_PH.length; i++) {
const v = VECTORS_RFC8032_PH[i];
should(`RFC8032ph/${i}`, () => {
should(`${i}`, () => {
deepStrictEqual(hex(ed448ph.getPublicKey(v.secretKey)), v.publicKey);
deepStrictEqual(hex(ed448ph.sign(v.message, v.secretKey, v.context)), v.signature);
deepStrictEqual(ed448ph.verify(v.signature, v.message, v.publicKey, v.context), true);
deepStrictEqual(
hex(ed448ph.sign(v.message, v.secretKey, { context: v.context })),
v.signature
);
deepStrictEqual(
ed448ph.verify(v.signature, v.message, v.publicKey, { context: v.context }),
true
);
});
}
});
should('not verify when sig.s >= CURVE.n', () => {
function get56bSig() {
const privateKey = ed448.utils.randomPrivateKey();
const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);
const publicKey = ed448.getPublicKey(privateKey);
const signature = ed448.sign(message, privateKey);
const R = signature.slice(0, 56);
let s = signature.slice(56, 112);
s = bytesToHex(s.slice().reverse());
s = BigInt('0x' + s);
s = s + ed448.CURVE.n;
s = numberToBytesLE(s, 56);
const sig_invalid = concatBytes(R, s);
return { sig_invalid, message, publicKey };
}
let sig;
while (true) {
try {
sig = get56bSig();
break;
} catch (error) {
// non-56b sig was generated, try again
}
}
throws(() => {
ed448.verify(sig.sig_invalid, sig.message, sig.publicKey);
});
});
describe('RFC7748 X448 ECDH', () => {
// ECDH
const rfc7748Mul = [
{
scalar:
'3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3',
u: '06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086',
outputU:
'ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f',
},
{
scalar:
'203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f',
u: '0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db',
outputU:
'884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d',
},
];
for (let i = 0; i < rfc7748Mul.length; i++) {
const v = rfc7748Mul[i];
should(`scalarMult (${i})`, () => {
deepStrictEqual(hex(x448.scalarMult(v.scalar, v.u)), v.outputU);
});
}
should('X448 base point', () => {
const rfc7748Iter = [
{
scalar:
'3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113',
iters: 1,
},
{
scalar:
'aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38',
iters: 1000,
},
// { scalar: '077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37', iters: 1000000 },
];
for (let i = 0; i < rfc7748Iter.length; i++) {
const { scalar, iters } = rfc7748Iter[i];
should(`scalarMult iterated ${iters}x`, () => {
let k = x448.GuBytes;
for (let i = 0, u = k; i < iters; i++) [k, u] = [x448.scalarMult(k, u), k];
deepStrictEqual(hex(k), scalar);
});
}
should('getSharedKey', () => {
const alicePrivate =
'9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b';
const alicePublic =
'9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0';
const bobPrivate =
'1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d';
const bobPublic =
'3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609';
const shared =
'07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d';
deepStrictEqual(alicePublic, hex(x448.getPublicKey(alicePrivate)));
deepStrictEqual(bobPublic, hex(x448.getPublicKey(bobPrivate)));
deepStrictEqual(hex(x448.scalarMult(alicePrivate, bobPublic)), shared);
deepStrictEqual(hex(x448.scalarMult(bobPrivate, alicePublic)), shared);
});
should('wycheproof', () => {
const group = x448vectors.testGroups[0];
for (let i = 0; i < group.tests.length; i++) {
const v = group.tests[i];
const index = `(${i}, ${v.result}) ${v.comment}`;
if (v.result === 'valid' || v.result === 'acceptable') {
try {
const shared = hex(x448.scalarMult(v.private, v.public));
deepStrictEqual(shared, v.shared, index);
} catch (e) {
// We are more strict
if (e.message.includes('Expected valid scalar')) return;
if (e.message.includes('Invalid private or public key received')) return;
if (e.message.includes('Expected 56 bytes')) return;
throw e;
}
} else if (v.result === 'invalid') {
let failed = false;
try {
x448.scalarMult(v.private, v.public);
} catch (error) {
failed = true;
}
deepStrictEqual(failed, true, index);
} else throw new Error('unknown test result');
}
});
should('have proper base point', () => {
const { x, y } = Point.BASE;
const { Fp } = ed448.CURVE;
// const invX = Fp.invert(x * x); // x²
const u = Fp.div(Fp.create(y * y), Fp.create(x * x)); // (y²/x²)
// const u = Fp.create(y * y * invX);
deepStrictEqual(hex(numberToBytesLE(u, 56)), x448.Gu);
deepStrictEqual(numberToBytesLE(u, 56), x448.GuBytes);
});
});
});

View File

@@ -0,0 +1,908 @@
{
"algorithm" : "EDDSA",
"generatorVersion" : "0.8r12",
"numberOfTests" : 86,
"header" : [
"Test vectors of type EddsaVerify are intended for testing",
"the verification of Eddsa signatures."
],
"notes" : {
"SignatureMalleability" : "EdDSA signatures are non-malleable, if implemented accordingly. Failing to check the range of S allows to modify signatures. See RFC 8032, Section 5.2.7 and Section 8.4."
},
"schema" : "eddsa_verify_schema.json",
"testGroups" : [
{
"jwk" : {
"crv" : "Ed448",
"d" : "iDAeB2UY01N_kwLuD1Ij5LY-HwFgB9PC69_sX3CZfoEZxrrQrnuAP0h5HKjsVJqiobhi96UVkLnV",
"kid" : "none",
"kty" : "OKP",
"x" : "QZYQpTSvEn9YOwSBjNt_D_MAsCXy4BaCvK4z_Wkc7gOVEd8M3caQ7peEJuizjlDOWvfc-6UPcEwA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "419610a534af127f583b04818cdb7f0ff300b025f2e01682bcae33fd691cee039511df0cddc690ee978426e8b38e50ce5af7dcfba50f704c00",
"sk" : "88301e076518d3537f9302ee0f5223e4b63e1f016007d3c2ebdfec5f70997e8119c6bad0ae7b803f48791ca8ec549aa2a1b862f7a51590b9d5",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00419610a534af127f583b04818cdb7f0ff300b025f2e01682bcae33fd691cee039511df0cddc690ee978426e8b38e50ce5af7dcfba50f704c00",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAQZYQpTSvEn9YOwSBjNt/D/MAsCXy4BaCvK4z/Wkc7gOVEd8M3caQ7peEJuizjlDOWvfc+6UPcEwA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 1,
"comment" : "",
"msg" : "",
"sig" : "cf7953007666e12f73af9ec92e3e018da5ee5a8d5b17f5100a354c58f1d5f4bb37ab835c52f72374c72d612689149cf6d36a70db6dc5a6c400b597348e0e31e51e65bb144e63c892a367b4c055c036aa6cd7e728cdd2a098963bda863903e6dd025b5a5d891209f4e28537694804e50b0800",
"result" : "valid",
"flags" : []
},
{
"tcId" : 2,
"comment" : "",
"msg" : "78",
"sig" : "c56e94d5c9ca860c244f33db556bf6b3cec38b024b77604a35d6a07211b1316b9a027133c374b86f72665cc45ce01583a2e0f2775c6172da801acef168717cab1196cddfb149359dfef589756257cc2d6b02fc516d8d41b4adaa3f11428f41410ef0dc3c1b008d3d052173d4389508ed0100",
"result" : "valid",
"flags" : []
},
{
"tcId" : 3,
"comment" : "",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600",
"result" : "valid",
"flags" : []
},
{
"tcId" : 4,
"comment" : "",
"msg" : "48656c6c6f",
"sig" : "442e33780f199dd7bc71d1335f74df7f3a0ec789e21a175c1bffddb6e50091998d969ac8194b3acefb7702f6c222f84f7eeca3b80406f1fe80687915e7925bf52deb47b6b779e26d30eec7c5fef03580f280a089eefd0bacc9fbbb6a4d73a591d1671d192e6bbcfdb79ad3db5673a1263000",
"result" : "valid",
"flags" : []
},
{
"tcId" : 5,
"comment" : "",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff28060a05236fc9c1682b0e55b60a082c9a57bffe61ef4dda5ce65df539805122b3a09a05976d41ad68ab52df85428152c57da93531e5d16920e00",
"result" : "valid",
"flags" : []
},
{
"tcId" : 6,
"comment" : "",
"msg" : "000000000000000000000000",
"sig" : "a8ca64d1ab00eae77fd2854d8422db3ae12fca91c14f274f30a44df98590786ec4cbb96a9564fc1b9b16c22d2bd00aa65f0876323729f5ac809fb0b89a4d3f27afbabb596851d835173d60ea34e0875359f3d6adb13cef1395b7eaa5f9147583ff38b4deb183062874915bf194ae61072300",
"result" : "valid",
"flags" : []
},
{
"tcId" : 7,
"comment" : "",
"msg" : "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
"sig" : "b205d3e24ccef64c1e86f15f48ddfa682453503489475188b04a8f55860b3c8a9c01e6de820bb7d9b15daff8de25a4a870e987157a115ec1802da0d0606da12842ea7eab658b5eea6dd1f3a641a5174425578003cd318b8d6b8dcb4de954b5078d1912c578ad8281515d6df3672b94173f00",
"result" : "valid",
"flags" : []
},
{
"tcId" : 8,
"comment" : "",
"msg" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60",
"sig" : "3492ef66e5fdf1503e9e206c5c2f0d4b7891aad793575527d2251e0df1b97c2feac188bc382ce3c92c4bc36ba2695f32bedadd480eaa932300d0db1f9a9c60844d2ea5aea64933c7be46c4f9d21cb48b39eae23d08496de7ce9501197185cc5d4ff8aa4b018ce7ad321f6a7d778c4a070400",
"result" : "valid",
"flags" : []
},
{
"tcId" : 9,
"comment" : "",
"msg" : "ffffffffffffffffffffffffffffffff",
"sig" : "545e1905af1b5886552eaf78e17304c6f83fcfb3444df2d1ea056486db615e3bb29131bb0c1fd295364dc515dae581967148eb23c6c9012e806d3623baff00548c648e3cb3756aaaaf659f2fb7dd2e71c7611448593ca63f2a98913ab7f182e6820eaf1334e2745e0e7bc0dccab98de71600",
"result" : "valid",
"flags" : []
},
{
"tcId" : 10,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 11,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 12,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 13,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 14,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 15,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 16,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 17,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 18,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 19,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 20,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 21,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 22,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3ff24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 23,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3ff34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 24,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "f34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 25,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 26,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 27,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffff24458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 28,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffff34458ab92c27823558fc58d72c26c219036d6ae49db4ec4e923ca7cffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 29,
"comment" : "special values for r and s",
"msg" : "3f",
"sig" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 30,
"comment" : "empty signature",
"msg" : "54657374",
"sig" : "",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 31,
"comment" : "s missing",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 32,
"comment" : "signature too short",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 33,
"comment" : "signature too long",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826002020",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 34,
"comment" : "include pk in signature",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600419610a534af127f583b04818cdb7f0ff300b025f2e01682bcae33fd691cee039511df0cddc690ee978426e8b38e50ce5af7dcfba50f704c00",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 35,
"comment" : "prepending 0 byte to signature",
"msg" : "54657374",
"sig" : "005d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 36,
"comment" : "prepending 0 byte to s",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f2800031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd982600",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 37,
"comment" : "appending 0 byte to signature",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98260000",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 38,
"comment" : "removing 0 byte from signature",
"msg" : "5465737430",
"sig" : "dbd6384516ab6b0eb2d609414564ec217383b66040dfb0676128251ae24c1d7c179c21a9ee307dc13f8fe6550bc40187f093da85617bcf5d009d3ee8b798ad978b6e683bc4e911940ea82ea0b7e95dc24fe0b29e44663211892c2aaa3451379d22c289b94378f11fb700f1689d4a00d73e",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 39,
"comment" : "removing 0 byte from signature",
"msg" : "546573743535",
"sig" : "ce2b2fff0bf445a36813cf2a76e0cc5619a4f16ee53f0fe3cd46fc0414db7248b32fbda54bbb37e708d6238076ea12bf850b964b044520bb80fbaf0e1d1ed3bcab261462df5e7f2de73ac9cbae26dfa29015039acf90575961fc9b91b9ca276dae7d5fa805bd202c5579a0f4c66e801400",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 40,
"comment" : "dropping byte from signature",
"msg" : "546573743633",
"sig" : "c283ed36d78c275a5d02f7939aed2c4ef68320ae1bf6fc25e834b758046a6d52a480216a942dfe771f3bd307f4ce7d3f446e0824961bd5de80cda42b5cc38e6ec3d53f386978b9877d3c98a28ac8fc66630ffd178933a18de1aee23cab5011c9ff4c9277311b4c6c33acb8e82b8c693c00",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 41,
"comment" : "removing leading 0 byte from signature",
"msg" : "54657374333631",
"sig" : "62e629bd2b8f595df401c362c766216d45de89fceecd99c69d323b5c53ad5ac3ea7224963feba2f2895551d94f548248ef8597d2a959f880d59934a5e8f07847834d66ba1a6b09de5dba692172b13f768f0c29e8196144c130d2353445d63cbd0b690794fdad30a48e8bb7cc2504f80700",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 42,
"comment" : "modified bit 0 in R",
"msg" : "313233343030",
"sig" : "5cb94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280afc33a525116cc12e0d1c3a1fde6de518a6544f360d0fe18d5be7770b057a2bf792db4b7648fa84a6eaecae909e33fa59c5dfe4804ba2623",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 43,
"comment" : "modified bit 1 in R",
"msg" : "313233343030",
"sig" : "5fb94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280f91386c3e9dd9e7c9af7ca6bbef8b7a44ae3d68eeade449d7dfbb31de8419eb943e2ecbcdd06df5227e82b9ded519a56e70f0a1c0fc17b06",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 44,
"comment" : "modified bit 2 in R",
"msg" : "313233343030",
"sig" : "59b94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280f1aab07b4ad069dfafc01b4532e1e44cbf7177e1bdda197fc87434046db5b935afd9114ac5e1138eaead23c3b59dba9026d2da4a86fe800b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 45,
"comment" : "modified bit 7 in R",
"msg" : "313233343030",
"sig" : "ddb94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2807668402b7b093fc754019324077c1f842a7d2e35adf7b87094115cec459ad5419e162988ef42b1988d9b944d9d5a7ce09c6f342afa500839",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 46,
"comment" : "modified bit 8 in R",
"msg" : "313233343030",
"sig" : "5db84c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280279b70338586b9e13e669191cc0dfc2a937d50a6118758de04a4ca41f4877abdb971afa87fe4b83bc243b8dfd2cb368aa389a4cb11e83e31",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 47,
"comment" : "modified bit 16 in R",
"msg" : "313233343030",
"sig" : "5db94d53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280c7b847556b3a6f9447483899ab730a23004c695054dd57b1c3214fa87f632f39c8ff1471f0532b8eee4154930e1ca30d574b8f9e85b0432b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 48,
"comment" : "modified bit 31 in R",
"msg" : "313233343030",
"sig" : "5db94cd3101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2800b017917472b130a1cc1c8e995a252617d5ddaf1f3d48930b4876fa0d2cfedec90a8c85c8274892a1ca3b6cfce63ebfebc307210b844ae0c",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 49,
"comment" : "modified bit 32 in R",
"msg" : "313233343030",
"sig" : "5db94c53111f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2805f38f6371860fcc4f2ec515afd35cb05d8941e2448cc469a15b8537e758b16d46b123581613462c2bb20d8a07299ab795d0998e1e4277931",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 50,
"comment" : "modified bit 63 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f529f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff28017111ba6fefd45e2490f1d53a184007fa073470706d7f4a9606fcad2954e74c32116ba7701d225b76e55164e64df3245c1031f0df734bd31",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 51,
"comment" : "modified bit 64 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6d1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2808d7d0aa1fd81d0e31789921771c654338f96f0b557b615e3da55670271608a0e022e4e8cf393e309f8f6412281b6147e7fce42b089eb1e0c",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 52,
"comment" : "modified bit 97 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ca4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280b08d3be6ebf4e60bf6d74e105ea2fa9b965c62816bbd22ea3bb0c1acfd12300523ca76f94b6f789488a957fbeb212d713baccf95fd594f3d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 53,
"comment" : "modified bit 127 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7606fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280a23f54857e9b0f72b2ef90d2768834590464d75933ed08c454faa762b3702a2b631c33c339d05b2e24c20a8214f99af31f93f80f416a1129",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 54,
"comment" : "modified bit 240 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0881a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280734bdc399273d3403d934ceaae16e87a68c6bff6b77d8037ff41c97922498a58e704c29ab519d41bab70735f71fc26f589361e2b21754300",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 55,
"comment" : "modified bit 247 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0800a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280ba961cc8d0765c99d57470ee1c0c77f0a562a198fd0175eddb0c033e0fb8525328c5e2c516e2b00f73609c7f769195eb1a02ff54090d781f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 56,
"comment" : "modified bit 248 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a97b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280e72685907da9e5a64e4142ed02fc0c6bf95763201db5942aac055fa87e6fdd32e483fd21ed4110d5d7ef619b740fef2ad8a71fe821e42a2a",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 57,
"comment" : "modified bit 253 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880887b8e55858df4cf2291a7303ffda446b82a117b4dd408cff280500646d67c74f13471f0ad034da530f7238fe7897e532af8ec2977643a410b1d054934df567e170276389e66b3f3ccb3c15aed239d04f72b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 58,
"comment" : "modified bit 254 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880e87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2807bb153b8e350aa736a91c921217578539600c1299ab76522ef8f6902d79c93f274073ee6beafe6200ecaf59f7cd11bb1c833f24bf30ed52d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 59,
"comment" : "modified bit 255 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880287b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2804a67b22be599d6433b87ea961c82c457ab50f64ac6b7efb0b2f90988927f83742303c278f8248e02d5679b41ed505aba0fb51110d0def810",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 60,
"comment" : "modified bit 440 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff3807f452efb0cd97dab5506028b7b876830dee02a9c0cbd140dcde509638d4d546c30856b2151bdf79930df5bbb11f2beb66bcdc25ad75f2116",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 61,
"comment" : "modified bit 441 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff0808d78231bb3c9a87c5b8d168fe05f8197503a3d73a6d700f436b5a76ab866388baa6930191a077aca7970058932c88b7f9e6ecb13c89dcd1d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 62,
"comment" : "modified bit 447 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cf72809e5a8406063fb3545f0fb627f841b2e3a85ad5d378018e8b58fe58e14ee5520d57abc9140e9c5a75a8b09ac3334dd0cad69b48771284321d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 63,
"comment" : "modified bit 448 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2811adf92201088e051ee48b57aecf46edfc68e5baeed5ae4910ba5681d370f75ab593811e18293ef0808581c254196bcbf2b4c454136a6711b",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 64,
"comment" : "modified bit 449 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2825e06c3999e8308be439c40940b0075d3e4f65147c1608cbe6e9c432e33bed6686f9393ae2568f0ad60febcb4b6179c0d90d034e7c3c46810",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 65,
"comment" : "modified bit 454 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2c02456bbd141df048dbf1843be6d5fef402483314c2af547b361a09f3319489eaede43404df9faf634c1298d678b5261c808b0be3726013e39",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 66,
"comment" : "modified bit 455 in R",
"msg" : "313233343030",
"sig" : "5db94c53101f521f6c1f43b60ea4d7e06fbd49c2e8afaf4fcc289e645e0880a87b8e55858df4cf2291a7303ffda446b82a117b4dd408cff2007106d2a896a7fec6dee53eea272d9b6e738c340295416b50f39a9463a5635450b9f93c4c06737affd42ae06cee5879c96c0bd58a91345503",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 67,
"comment" : "R==0",
"msg" : "313233343030",
"sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027ab98ab862e4e7ec3361a45ac1993e9b47d9ac40db91faed752399cee0413122b47346594fd7d2c8949b43e4cabaf17d8339ea0e307023f",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 68,
"comment" : "invalid R",
"msg" : "313233343030",
"sig" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd11bae33a0999fd3fd2bed6fa5577685e8fd595e79c006e58fd35f69f91b1d853553fb4006019a07725aa37773883dbe12253812887ac828",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 69,
"comment" : "all bits flipped in R",
"msg" : "313233343030",
"sig" : "a246b3acefe0ade093e0bc49f15b281f9042b63d175050b033d7619ba1f77f578471aa7a720b30dd6e58cfc0025bb947d5ee84b22bf7300d7f334e48141af0fade1469f5dedb851c9e725d27bd65012bada05e70cde641aad9ce0bea4983164f73816b6f13095e6b93eb03e850cad0cf0d",
"result" : "invalid",
"flags" : []
},
{
"tcId" : 70,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280241bd6142ddb02c0f9fa133955d3e610b4b27cb814227de8b241ef4e86402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9866",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 71,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28017602ec0bf9d7be34e8ad9c6c795533244e952675efdcbac9c65b9cb85402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98a6",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 72,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280fde9de16e5226d2af9a864e2ac1a2d756456ffc4f1b3693570ad4dc584402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 73,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f280c9fd3fc42f2d50b84de67a197724e0faa43058801821a546173d76b882402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 74,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9866",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 75,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd98a6",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 76,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28031d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d286402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
},
{
"tcId" : 77,
"comment" : "checking malleability ",
"msg" : "54657374",
"sig" : "5d053ff5b71f6ec3284525d35d77933178c8e19879886d08eccc6c7d27e9e5b5e02537dbc4d4723506e8d171fc1733857573dd02d18f48f28030d67d699a188a9ca46b4eabe2107aef237ca609cb462e24c91d25d285402b6ef7862b78a386950246ff38d6d2f458136d12e3c97fdd9826",
"result" : "invalid",
"flags" : [
"SignatureMalleability"
]
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "bIKlYsuAjRDWMr6JyFE-v2ySnzTd-oyfY8mWDvbjSKNSjIo_zC8ETjmj_FuUSS-PAy51SaIAmPlb",
"kid" : "none",
"kty" : "OKP",
"x" : "X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq_oJWGA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180",
"sk" : "6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a005fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq/oJWGA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 78,
"comment" : "RFC 8032",
"msg" : "",
"sig" : "533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "xOqwXTVwB8Yy89u0hImSTVUrCP4MNToNSh8ArNosRjr76mfF6NKHfF47w5emWZSe-AIelU4KEidO",
"kid" : "none",
"kty" : "OKP",
"x" : "Q7oo9DDN_0Vq5TFUX37NCsg0pV2TWMA3K_oMbGeYwIZq6gHrAHQoArhDjqTLghacI1FgYntMOpSA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480",
"sk" : "c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a0043ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAQ7oo9DDN/0Vq5TFUX37NCsg0pV2TWMA3K/oMbGeYwIZq6gHrAHQoArhDjqTLghacI1FgYntMOpSA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 79,
"comment" : "RFC 8032: 1 octet",
"msg" : "03",
"sig" : "26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f4352541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cbcee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0ff3348ab21aa4adafd1d234441cf807c03a00",
"result" : "valid",
"flags" : []
},
{
"tcId" : 80,
"comment" : "RFC 8032: 1 octet with context",
"msg" : "03",
"sig" : "d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00",
"result" : "invalid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "zSPST3FCdOdENDI3uTKQ9RH2Ql-Y5kRZ_yA-iYUIP_32BQBVOrwOBc0CGEvbicTM1n4YeVEmfrMo",
"kid" : "none",
"kty" : "OKP",
"x" : "3OqeePNaG_NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl_OFh1xznExpUPqTLX36fHYsAaWRHABQA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400",
"sk" : "cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffdf60500553abc0e05cd02184bdb89c4ccd67e187951267eb328",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoA3OqeePNaG/NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl/OFh1xznExpUPqTLX36fHYsAaWRHABQA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 81,
"comment" : "RFC 8032: 11 bytes",
"msg" : "0c3e544074ec63b0265e0c",
"sig" : "1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d389dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b051068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5028961c9bf8ffd973fe5d5c206492b140e00",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "JYzdStoy7Zyf9U5jdWrlgvuPqyrHIfLI5nanJ2hRPZOfY93bVWCRM_Ka34bsmSncy1LBxf0v9-Ib",
"kid" : "none",
"kty" : "OKP",
"x" : "O6FtoMbyzB8wGHdAdW9eeY1rxfwBXXxjzJUQ7j_UStwk2OlotuRub5TRm5RTYXJr114UnvCYF_WA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580",
"sk" : "258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d939f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a003ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAO6FtoMbyzB8wGHdAdW9eeY1rxfwBXXxjzJUQ7j/UStwk2OlotuRub5TRm5RTYXJr114UnvCYF/WA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 82,
"comment" : "RFC 8032: 12 bytes",
"msg" : "64a65f3cdedcdd66811e2915",
"sig" : "7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4ae90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457eb1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861e72003cbae6d6b8b827e4e6c143064ff3c00",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "fvToRUQjZ1L7tWuPMaI6EOQoFPX1XKA3zcwRxkyaOylJwbtgcAMUYRcypsL-qY7rwCZqEak5cBAO",
"kid" : "none",
"kty" : "OKP",
"x" : "s9oHmwqkk6V3ICnwRnuuvuWoES2dOiJTI2HaKU97s4FcXcWeF2tNnzgcoJOOE8bAexdL5l36V46A"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb3815c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80",
"sk" : "7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b2949c1bb60700314611732a6c2fea98eebc0266a11a93970100e",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb3815c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAs9oHmwqkk6V3ICnwRnuuvuWoES2dOiJTI2HaKU97s4FcXcWeF2tNnzgcoJOOE8bAexdL5l36V46A\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 83,
"comment" : "RFC 8032: 13 bytes",
"msg" : "64a65f3cdedcdd66811e2915e7",
"sig" : "6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf56b4e7e0ba5519234d047155ac727a1053100",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "1l3zQa0T4AhWdoi67dqOnc3BfcAkl06ltCJ7ZTDjOb_yH5nmjKaWjzzKbf4PufT6tPoTXVVC6j8B",
"kid" : "none",
"kty" : "OKP",
"x" : "35cF9Y7bq4Asf4Njz-VWCrHGEywgqfHdFjSDom-KxTo51oCL9KHfvSYbCZuwOz-1CQbLKL2KCB8A"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00",
"sk" : "d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoA35cF9Y7bq4Asf4Njz+VWCrHGEywgqfHdFjSDom+KxTo51oCL9KHfvSYbCZuwOz+1CQbLKL2KCB8A\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 84,
"comment" : "RFC 8032: 64 bytes",
"msg" : "bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944",
"sig" : "554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b18dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722ef552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba5f30e88e36ec2703b349ca229c2670833900",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "LsX-PBcEWr2xNqXmqRPjKrda5otT0vwUm3flBBMtN1abfnZrp0oZvWFiNDohyFkKqc68qQFMY231",
"kid" : "none",
"kty" : "OKP",
"x" : "eXVvAU3P4gefXdnnGL5BceLvJIagjyUYb2v_Q6mTa5v-EkArCK5leYo9geIunsgOdpCGLvPU7ToA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00",
"sk" : "2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d37569b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a0079756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAeXVvAU3P4gefXdnnGL5BceLvJIagjyUYb2v/Q6mTa5v+EkArCK5leYo9geIunsgOdpCGLvPU7ToA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 85,
"comment" : "RFC 8032: 256 bytes",
"msg" : "15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567cfa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072fc1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a6039c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b590316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce012d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11",
"sig" : "c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc60987fd08527c1a8e80d5823e65cafe2a3d00",
"result" : "valid",
"flags" : []
}
]
},
{
"jwk" : {
"crv" : "Ed448",
"d" : "hy0JN4D103MN98ISZks3uKDyT1aBDaqDgs1Po_d2NOxE3FTxwu2b6ob6-3Yy2L4ZnqFl9a1V3Zzo",
"kid" : "none",
"kty" : "OKP",
"x" : "qBsuinClrJT_28ybrfw_6wgB8lhXi7EUrUTs4ewOeZ2gjv-4HF1oXAxW9k7srvjN8RzDhzeDjPQA"
},
"key" : {
"curve" : "edwards448",
"keySize" : 448,
"pk" : "a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400",
"sk" : "872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8",
"type" : "EDDSAKeyPair"
},
"keyDer" : "3043300506032b6571033a00a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400",
"keyPem" : "-----BEGIN PUBLIC KEY-----\nMEMwBQYDK2VxAzoAqBsuinClrJT/28ybrfw/6wgB8lhXi7EUrUTs4ewOeZ2gjv+4HF1oXAxW9k7srvjN8RzDhzeDjPQA\n-----END PUBLIC KEY-----\n",
"type" : "EddsaVerify",
"tests" : [
{
"tcId" : 86,
"comment" : "RFC 8032: 1023 bytes",
"msg" : "6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e972660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd323219b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab797172b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f52096cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db977025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f0410a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf9696149e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a6059d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87",
"sig" : "e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bddf7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed573603ce30d8bb761785dc30dbc320869e1a00",
"result" : "valid",
"flags" : []
}
]
}
]
}

View File

@@ -1,107 +0,0 @@
[
{
"curve": "P192",
"q": "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
"private": "6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4",
"Ux": "AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56",
"Uy": "3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43",
"cases": [
{
"k": "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496",
"message": "sample",
"r": "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55",
"s": "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85"
},
{
"k": "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C",
"message": "test",
"r": "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE",
"s": "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F"
}
]
},
{
"curve": "P224",
"q": "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
"private": "F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1",
"Ux": "00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C",
"Uy": "EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A",
"cases": [
{
"k": "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D",
"message": "sample",
"r": "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E",
"s": "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC"
},
{
"k": "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524",
"message": "test",
"r": "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019",
"s": "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4"
}
]
},
{
"curve": "P256",
"q": "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
"private": "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721",
"Ux": "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6",
"Uy": "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299",
"cases": [
{
"k": "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60",
"message": "sample",
"r": "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716",
"s": "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
},
{
"k": "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0",
"message": "test",
"r": "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367",
"s": "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083"
}
]
},
{
"curve": "P384",
"q": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
"private": "6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5",
"Ux": "EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13",
"Uy": "8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720",
"cases": [
{
"k": "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9",
"message": "sample",
"r": "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46",
"s": "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8"
},
{
"k": "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA",
"message": "test",
"r": "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB",
"s": "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5"
}
]
},
{
"curve": "P521",
"q": "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
"private": "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
"Ux": "1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4",
"Uy": "0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5",
"cases": [
{
"k": "1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3",
"message": "sample",
"r": "0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA",
"s": "0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A"
},
{
"k": "16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D",
"message": "test",
"r": "13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D",
"s": "1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3"
}
]
}
]

View File

@@ -5,18 +5,15 @@ import { bytesToHex } from '@noble/hashes/utils';
import { sha256 } from '@noble/hashes/sha256';
import { sha512 } from '@noble/hashes/sha512';
import { shake128, shake256 } from '@noble/hashes/sha3';
import * as secp256r1 from '../lib/esm/p256.js';
import * as secp384r1 from '../lib/esm/p384.js';
import * as secp521r1 from '../lib/esm/p521.js';
import * as ed25519 from '../lib/esm/ed25519.js';
import * as ed448 from '../lib/esm/ed448.js';
import * as secp256k1 from '../lib/esm/secp256k1.js';
import { bls12_381 } from '../lib/esm/bls12-381.js';
import {
stringToBytes,
expand_message_xmd,
expand_message_xof,
} from '../lib/esm/abstract/hash-to-curve.js';
import * as secp256r1 from '../esm/p256.js';
import * as secp384r1 from '../esm/p384.js';
import * as secp521r1 from '../esm/p521.js';
import * as ed25519 from '../esm/ed25519.js';
import * as ed448 from '../esm/ed448.js';
import * as secp256k1 from '../esm/secp256k1.js';
import { bls12_381 } from '../esm/bls12-381.js';
import { expand_message_xmd, expand_message_xof } from '../esm/abstract/hash-to-curve.js';
import { utf8ToBytes } from '../esm/abstract/utils.js';
// XMD
import { default as xmd_sha256_38 } from './hash-to-curve/expand_message_xmd_SHA256_38.json' assert { type: 'json' };
import { default as xmd_sha256_256 } from './hash-to-curve/expand_message_xmd_SHA256_256.json' assert { type: 'json' };
@@ -56,9 +53,9 @@ function testExpandXMD(hash, vectors) {
const t = vectors.tests[i];
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
const p = expand_message_xmd(
stringToBytes(t.msg),
stringToBytes(vectors.DST),
t.len_in_bytes,
utf8ToBytes(t.msg),
utf8ToBytes(vectors.DST),
Number.parseInt(t.len_in_bytes),
hash
);
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
@@ -79,9 +76,9 @@ function testExpandXOF(hash, vectors) {
const t = vectors.tests[i];
should(`${i}`, () => {
const p = expand_message_xof(
stringToBytes(t.msg),
stringToBytes(vectors.DST),
+t.len_in_bytes,
utf8ToBytes(t.msg),
utf8ToBytes(vectors.DST),
Number.parseInt(t.len_in_bytes),
vectors.k,
hash
);
@@ -112,7 +109,7 @@ function testCurve(curve, ro, nu) {
const t = ro.vectors[i];
should(`(${i})`, () => {
const p = curve
.hashToCurve(stringToBytes(t.msg), {
.hashToCurve(utf8ToBytes(t.msg), {
DST: ro.dst,
})
.toAffine();
@@ -126,7 +123,7 @@ function testCurve(curve, ro, nu) {
const t = nu.vectors[i];
should(`(${i})`, () => {
const p = curve
.encodeToCurve(stringToBytes(t.msg), {
.encodeToCurve(utf8ToBytes(t.msg), {
DST: nu.dst,
})
.toAffine();
@@ -140,8 +137,8 @@ function testCurve(curve, ro, nu) {
testCurve(secp256r1, p256_ro, p256_nu);
testCurve(secp384r1, p384_ro, p384_nu);
testCurve(secp521r1, p521_ro, p521_nu);
testCurve(bls12_381.hashToCurve.G1, g1_ro, g1_nu);
testCurve(bls12_381.hashToCurve.G2, g2_ro, g2_nu);
testCurve(bls12_381.G1, g1_ro, g1_nu);
testCurve(bls12_381.G2, g2_ro, g2_nu);
testCurve(secp256k1, secp256k1_ro, secp256k1_nu);
testCurve(ed25519, ed25519_ro, ed25519_nu);
testCurve(ed448, ed448_ro, ed448_nu);

View File

@@ -5,10 +5,12 @@ import './basic.test.js';
import './nist.test.js';
import './ed448.test.js';
import './ed25519.test.js';
import './ed25519-addons.test.js';
import './secp256k1.test.js';
import './stark/index.test.js';
import './secp256k1-schnorr.test.js';
import './jubjub.test.js';
import './bls12-381.test.js';
import './hash-to-curve.test.js';
import './poseidon.test.js';
import './bls12-381.test.js';
should.run();

View File

@@ -1,4 +1,4 @@
import { jubjub, findGroupHash } from '../lib/esm/jubjub.js';
import { jubjub, findGroupHash } from '../esm/jubjub.js';
import { describe, should } from 'micro-should';
import { deepStrictEqual, throws } from 'assert';
const Point = jubjub.ExtendedPoint;

View File

@@ -1,15 +1,16 @@
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import { secp192r1, P192 } from '../lib/esm/p192.js';
import { secp224r1, P224 } from '../lib/esm/p224.js';
import { secp256r1, P256 } from '../lib/esm/p256.js';
import { secp384r1, P384 } from '../lib/esm/p384.js';
import { secp521r1, P521 } from '../lib/esm/p521.js';
import { secp256k1 } from '../lib/esm/secp256k1.js';
import { hexToBytes, bytesToHex } from '../lib/esm/abstract/utils.js';
import { secp192r1, secp224r1, p192, p224 } from './_more-curves.helpers.js';
import { DER } from '../esm/abstract/weierstrass.js';
import { secp256r1, p256 } from '../esm/p256.js';
import { secp384r1, p384 } from '../esm/p384.js';
import { secp521r1, p521 } from '../esm/p521.js';
import { secp256k1 } from '../esm/secp256k1.js';
import { hexToBytes, bytesToHex } from '../esm/abstract/utils.js';
import { default as ecdsa } from './wycheproof/ecdsa_test.json' assert { type: 'json' };
import { default as ecdh } from './wycheproof/ecdh_test.json' assert { type: 'json' };
import { default as rfc6979 } from './fixtures/rfc6979.json' assert { type: 'json' };
import { default as rfc6979 } from './vectors/rfc6979.json' assert { type: 'json' };
import { default as endoVectors } from './vectors/secp256k1/endomorphism.json' assert { type: 'json' };
import { default as ecdh_secp224r1_test } from './wycheproof/ecdh_secp224r1_test.json' assert { type: 'json' };
import { default as ecdh_secp256r1_test } from './wycheproof/ecdh_secp256r1_test.json' assert { type: 'json' };
@@ -23,38 +24,59 @@ import { default as secp224r1_sha3_224_test } from './wycheproof/ecdsa_secp224r1
import { default as secp224r1_sha3_256_test } from './wycheproof/ecdsa_secp224r1_sha3_256_test.json' assert { type: 'json' };
import { default as secp224r1_sha3_512_test } from './wycheproof/ecdsa_secp224r1_sha3_512_test.json' assert { type: 'json' };
import { default as secp224r1_sha512_test } from './wycheproof/ecdsa_secp224r1_sha512_test.json' assert { type: 'json' };
import { default as secp224r1_shake128_test } from './wycheproof/ecdsa_secp224r1_shake128_test.json' assert { type: 'json' };
import { default as secp256k1_sha256_bitcoin_test } from './wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json' assert { type: 'json' };
import { default as secp256k1_sha256_test } from './wycheproof/ecdsa_secp256k1_sha256_test.json' assert { type: 'json' };
import { default as secp256k1_sha3_256_test } from './wycheproof/ecdsa_secp256k1_sha3_256_test.json' assert { type: 'json' };
import { default as secp256k1_sha3_512_test } from './wycheproof/ecdsa_secp256k1_sha3_512_test.json' assert { type: 'json' };
import { default as secp256k1_sha512_test } from './wycheproof/ecdsa_secp256k1_sha512_test.json' assert { type: 'json' };
import { default as secp256k1_shake128_test } from './wycheproof/ecdsa_secp256k1_shake128_test.json' assert { type: 'json' };
import { default as secp256k1_shake256_test } from './wycheproof/ecdsa_secp256k1_shake256_test.json' assert { type: 'json' };
import { default as secp256r1_sha256_test } from './wycheproof/ecdsa_secp256r1_sha256_test.json' assert { type: 'json' };
import { default as secp256r1_sha3_256_test } from './wycheproof/ecdsa_secp256r1_sha3_256_test.json' assert { type: 'json' };
import { default as secp256r1_sha3_512_test } from './wycheproof/ecdsa_secp256r1_sha3_512_test.json' assert { type: 'json' };
import { default as secp256r1_sha512_test } from './wycheproof/ecdsa_secp256r1_sha512_test.json' assert { type: 'json' };
import { default as secp256r1_shake128_test } from './wycheproof/ecdsa_secp256r1_shake128_test.json' assert { type: 'json' };
import { default as secp384r1_sha384_test } from './wycheproof/ecdsa_secp384r1_sha384_test.json' assert { type: 'json' };
import { default as secp384r1_sha3_384_test } from './wycheproof/ecdsa_secp384r1_sha3_384_test.json' assert { type: 'json' };
import { default as secp384r1_sha3_512_test } from './wycheproof/ecdsa_secp384r1_sha3_512_test.json' assert { type: 'json' };
import { default as secp384r1_sha512_test } from './wycheproof/ecdsa_secp384r1_sha512_test.json' assert { type: 'json' };
import { default as secp384r1_shake256_test } from './wycheproof/ecdsa_secp384r1_shake256_test.json' assert { type: 'json' };
import { default as secp521r1_sha3_512_test } from './wycheproof/ecdsa_secp521r1_sha3_512_test.json' assert { type: 'json' };
import { default as secp521r1_sha512_test } from './wycheproof/ecdsa_secp521r1_sha512_test.json' assert { type: 'json' };
import { default as secp521r1_shake256_test } from './wycheproof/ecdsa_secp521r1_shake256_test.json' assert { type: 'json' };
import { sha3_224, sha3_256, sha3_384, sha3_512 } from '@noble/hashes/sha3';
import { sha3_224, sha3_256, sha3_384, sha3_512, shake128, shake256 } from '@noble/hashes/sha3';
import { sha512, sha384 } from '@noble/hashes/sha512';
import { sha224, sha256 } from '@noble/hashes/sha256';
// TODO: maybe add to noble-hashes?
const wrapShake = (shake, dkLen) => {
const hashC = (msg) => shake(msg, { dkLen });
hashC.outputLen = dkLen;
hashC.blockLen = shake.blockLen;
hashC.create = () => shake.create({ dkLen });
return hashC;
};
const shake128_224 = wrapShake(shake128, 224 / 8);
const shake128_256 = wrapShake(shake128, 256 / 8);
const shake256_256 = wrapShake(shake256, 256 / 8);
const shake256_384 = wrapShake(shake256, 384 / 8);
const shake256_512 = wrapShake(shake256, 512 / 8);
const hex = bytesToHex;
// prettier-ignore
const NIST = {
secp192r1, P192,
secp224r1, P224,
secp256r1, P256,
secp384r1, P384,
secp521r1, P521,
secp192r1, P192: p192,
secp224r1, P224: p224,
secp256r1, P256: p256,
secp384r1, P384: p384,
secp521r1, P521: p521,
secp256k1,
};
@@ -75,9 +97,6 @@ should('fields', () => {
describe('wycheproof ECDH', () => {
for (const group of ecdh.testGroups) {
// // Tested in secp256k1.test.js
// if (group.key.curve === 'secp256k1') continue;
// We don't have SHA-224
const CURVE = NIST[group.curve];
if (!CURVE) continue;
should(group.curve, () => {
@@ -107,24 +126,24 @@ describe('wycheproof ECDH', () => {
// More per curve tests
const WYCHEPROOF_ECDH = {
P224: {
curve: P224,
p224: {
curve: p224,
tests: [ecdh_secp224r1_test],
},
P256: {
curve: P256,
p256: {
curve: p256,
tests: [ecdh_secp256r1_test],
},
secp256k1: {
curve: secp256k1,
tests: [ecdh_secp256k1_test],
},
P384: {
curve: P384,
p384: {
curve: p384,
tests: [ecdh_secp384r1_test],
},
P521: {
curve: P521,
p521: {
curve: p521,
tests: [ecdh_secp521r1_test],
},
};
@@ -164,8 +183,8 @@ describe('wycheproof ECDH', () => {
});
const WYCHEPROOF_ECDSA = {
P224: {
curve: P224,
p224: {
curve: p224,
hashes: {
sha224: {
hash: sha224,
@@ -191,6 +210,10 @@ const WYCHEPROOF_ECDSA = {
hash: sha512,
tests: [secp224r1_sha512_test],
},
shake128: {
hash: shake128_224,
tests: [secp224r1_shake128_test],
},
},
},
secp256k1: {
@@ -198,7 +221,7 @@ const WYCHEPROOF_ECDSA = {
hashes: {
sha256: {
hash: sha256,
tests: [secp256k1_sha256_test],
tests: [secp256k1_sha256_test, secp256k1_sha256_bitcoin_test],
},
sha3_256: {
hash: sha3_256,
@@ -212,10 +235,18 @@ const WYCHEPROOF_ECDSA = {
hash: sha512,
tests: [secp256k1_sha512_test],
},
shake128: {
hash: shake128_256,
tests: [secp256k1_shake128_test],
},
shake256: {
hash: shake256_256,
tests: [secp256k1_shake256_test],
},
},
P256: {
curve: P256,
},
p256: {
curve: p256,
hashes: {
sha256: {
hash: sha256,
@@ -233,10 +264,14 @@ const WYCHEPROOF_ECDSA = {
hash: sha512,
tests: [secp256r1_sha512_test],
},
shake128: {
hash: shake128_256,
tests: [secp256r1_shake128_test],
},
},
P384: {
curve: P384,
},
p384: {
curve: p384,
hashes: {
sha384: {
hash: sha384,
@@ -254,10 +289,14 @@ const WYCHEPROOF_ECDSA = {
hash: sha512,
tests: [secp384r1_sha512_test],
},
shake256: {
hash: shake256_384,
tests: [secp384r1_shake256_test],
},
},
P521: {
curve: P521,
},
p521: {
curve: p521,
hashes: {
sha3_512: {
hash: sha3_512,
@@ -267,19 +306,23 @@ const WYCHEPROOF_ECDSA = {
hash: sha512,
tests: [secp521r1_sha512_test],
},
shake256: {
hash: shake256_512,
tests: [secp521r1_shake256_test],
},
},
},
};
function runWycheproof(name, CURVE, group, index) {
const pubKey = CURVE.ProjectivePoint.fromHex(group.key.uncompressed);
deepStrictEqual(pubKey.x, BigInt(`0x${group.key.wx}`));
deepStrictEqual(pubKey.y, BigInt(`0x${group.key.wy}`));
const key = group.publicKey;
const pubKey = CURVE.ProjectivePoint.fromHex(key.uncompressed);
deepStrictEqual(pubKey.x, BigInt(`0x${key.wx}`));
deepStrictEqual(pubKey.y, BigInt(`0x${key.wy}`));
const pubR = pubKey.toRawBytes();
for (const test of group.tests) {
const m = CURVE.CURVE.hash(hexToBytes(test.msg));
const { sig } = test;
if (test.result === 'valid' || test.result === 'acceptable') {
try {
CURVE.Signature.fromDER(sig);
@@ -311,7 +354,6 @@ describe('wycheproof ECDSA', () => {
should('generic', () => {
for (const group of ecdsa.testGroups) {
// Tested in secp256k1.test.js
if (group.key.curve === 'secp256k1') continue;
let CURVE = NIST[group.key.curve];
if (!CURVE) continue;
if (group.key.curve === 'secp224r1' && group.sha !== 'SHA-224') {
@@ -324,6 +366,9 @@ describe('wycheproof ECDSA', () => {
if (['Hash weaker than DL-group'].includes(test.comment)) {
continue;
}
// These old Wycheproof vectors which still accept missing zero, new one is not.
if (test.flags.includes('MissingZero') && test.result === 'acceptable')
test.result = 'invalid';
const m = CURVE.CURVE.hash(hexToBytes(test.msg));
if (test.result === 'valid' || test.result === 'acceptable') {
try {
@@ -334,7 +379,12 @@ describe('wycheproof ECDSA', () => {
throw e;
}
const verified = CURVE.verify(test.sig, m, pubKey.toHex());
deepStrictEqual(verified, true, 'valid');
if (group.key.curve === 'secp256k1') {
// lowS: true for secp256k1
deepStrictEqual(verified, !CURVE.Signature.fromDER(test.sig).hasHighS(), `valid`);
} else {
deepStrictEqual(verified, true, `valid`);
}
} else if (test.result === 'invalid') {
let failed = false;
try {
@@ -389,6 +439,43 @@ describe('RFC6979', () => {
}
});
should('properly add leading zero to DER', () => {
// Valid DER
deepStrictEqual(
DER.toSig(
'303c021c70049af31f8348673d56cece2b27e587a402f2a48f0b21a7911a480a021c2840bf24f6f66be287066b7cbf38788e1b7770b18fd1aa6a26d7c6dc'
),
{
r: 11796871166002955884468185727465595477481802908758874298363724580874n,
s: 4239126896857047637966364941684493209162496401998708914961872570076n,
}
);
// Invalid DER (missing trailing zero)
throws(() =>
DER.toSig(
'303c021c70049af31f8348673d56cece2b27e587a402f2a48f0b21a7911a480a021cd7bf40db0909941d78f9948340c69e14c5417f8c840b7edb35846361'
)
);
// Correctly adds trailing zero
deepStrictEqual(
DER.hexFromSig({
r: 11796871166002955884468185727465595477481802908758874298363724580874n,
s: 22720819770293592156700650145335132731295311312425682806720849797985n,
}),
'303d021c70049af31f8348673d56cece2b27e587a402f2a48f0b21a7911a480a021d00d7bf40db0909941d78f9948340c69e14c5417f8c840b7edb35846361'
);
});
should('have proper GLV endomorphism logic in secp256k1', () => {
const Point = secp256k1.ProjectivePoint;
for (let item of endoVectors) {
const point = Point.fromAffine({ x: BigInt(item.ax), y: BigInt(item.ay) });
const c = point.multiplyUnsafe(BigInt(item.scalar)).toAffine();
deepStrictEqual(c.x, BigInt(item.cx));
deepStrictEqual(c.y, BigInt(item.cy));
}
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {

View File

@@ -1,8 +1,8 @@
import { deepStrictEqual, throws } from 'assert';
import { should, describe } from 'micro-should';
import * as poseidon from '../lib/esm/abstract/poseidon.js';
import * as stark from '../lib/esm/stark.js';
import * as mod from '../lib/esm/abstract/modular.js';
import * as poseidon from '../esm/abstract/poseidon.js';
import * as stark from './_poseidon.helpers.js';
import * as mod from '../esm/abstract/modular.js';
import { default as pvectors } from './vectors/poseidon.json' assert { type: 'json' };
const { st1, st2, st3, st4 } = pvectors;
@@ -132,7 +132,9 @@ describe('Stark', () => {
// Official vectors: https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/test_vectors.txt
should('poseidonperm_x5_255_3', () => {
const Fp = mod.Fp(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
const Fp = mod.Field(
BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')
);
const mds = [
[
@@ -179,7 +181,7 @@ should('poseidonperm_x5_255_3', () => {
});
should('poseidonperm_x5_255_5', () => {
const Fp = mod.Fp(0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n);
const Fp = mod.Field(0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n);
const t = 5;
const mds = [
@@ -250,7 +252,7 @@ should('poseidonperm_x5_255_5', () => {
});
should('poseidonperm_x5_254_3', () => {
const Fp = mod.Fp(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n);
const Fp = mod.Field(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n);
const t = 3;
const mds = [
@@ -297,7 +299,7 @@ should('poseidonperm_x5_254_3', () => {
});
should('poseidonperm_x5_254_5', () => {
const Fp = mod.Fp(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n);
const Fp = mod.Field(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n);
const t = 5;
const mds = [

View File

@@ -0,0 +1,34 @@
import { deepStrictEqual, throws } from 'assert';
import { readFileSync } from 'fs';
import { should, describe } from 'micro-should';
import { bytesToHex as hex } from '@noble/hashes/utils';
import { schnorr } from '../esm/secp256k1.js';
const schCsv = readFileSync('./test/vectors/secp256k1/schnorr.csv', 'utf-8');
describe('schnorr.sign()', () => {
// index,secret key,public key,aux_rand,message,signature,verification result,comment
const vectors = schCsv
.split('\n')
.map((line) => line.split(','))
.slice(1, -1);
for (let vec of vectors) {
const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec;
should(`${comment || 'vector ' + index}`, () => {
if (sec) {
deepStrictEqual(hex(schnorr.getPublicKey(sec)), pub.toLowerCase());
const sig = schnorr.sign(msg, sec, rnd);
deepStrictEqual(hex(sig), expSig.toLowerCase());
deepStrictEqual(schnorr.verify(sig, msg, pub), true);
} else {
const passed = schnorr.verify(expSig, msg, pub);
deepStrictEqual(passed, passes === 'TRUE');
}
});
}
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

11
test/secp256k1.helpers.js Normal file
View File

@@ -0,0 +1,11 @@
// @ts-ignore
export { secp256k1 as secp } from '../esm/secp256k1.js';
import { secp256k1 as _secp } from '../esm/secp256k1.js';
export { bytesToNumberBE, numberToBytesBE } from '../esm/abstract/utils.js';
export { mod } from '../esm/abstract/modular.js';
export const sigFromDER = (der) => {
return _secp.Signature.fromDER(der);
};
export const sigToDER = (sig) => sig.toDERHex();
export const selectHash = (secp) => secp.CURVE.hash;
export const normVerifySig = (s) => _secp.Signature.fromDER(s);

View File

@@ -1,22 +1,24 @@
import * as fc from 'fast-check';
import { secp256k1, schnorr } from '../lib/esm/secp256k1.js';
import { Fp } from '../lib/esm/abstract/modular.js';
import { bytesToNumberBE, ensureBytes, numberToBytesBE } from '../lib/esm/abstract/utils.js';
import { readFileSync } from 'fs';
import { default as ecdsa } from './vectors/ecdsa.json' assert { type: 'json' };
import { default as ecdh } from './vectors/ecdh.json' assert { type: 'json' };
import { default as privates } from './vectors/privates.json' assert { type: 'json' };
import { default as points } from './vectors/points.json' assert { type: 'json' };
import { default as wp } from './vectors/wychenproof.json' assert { type: 'json' };
import { should, describe } from 'micro-should';
import { hexToBytes, bytesToHex as hex } from '@noble/hashes/utils';
import { deepStrictEqual, throws } from 'assert';
import { hexToBytes, bytesToHex } from '@noble/hashes/utils';
import * as fc from 'fast-check';
import { readFileSync } from 'fs';
import { should, describe } from 'micro-should';
// prettier-ignore
import {
secp, sigFromDER, sigToDER, selectHash, normVerifySig, mod, bytesToNumberBE, numberToBytesBE
} from './secp256k1.helpers.js';
import { default as ecdsa } from './vectors/secp256k1/ecdsa.json' assert { type: 'json' };
import { default as ecdh } from './wycheproof/ecdh_secp256k1_test.json' assert { type: 'json' };
import { default as privates } from './vectors/secp256k1/privates.json' assert { type: 'json' };
import { default as points } from './vectors/secp256k1/points.json' assert { type: 'json' };
import { default as wp } from './wycheproof/ecdsa_secp256k1_sha256_test.json' assert { type: 'json' };
// Any changes to the file will need to be aware of the fact
// the file is shared between noble-curves and noble-secp256k1.
const hex = bytesToHex;
const secp = secp256k1;
const Point = secp.ProjectivePoint;
const privatesTxt = readFileSync('./test/vectors/privates-2.txt', 'utf-8');
const schCsv = readFileSync('./test/vectors/schnorr.csv', 'utf-8');
const privatesTxt = readFileSync('./test/vectors/secp256k1/privates-2.txt', 'utf-8');
const FC_BIGINT = fc.bigInt(1n + 1n, secp.CURVE.n - 1n);
// prettier-ignore
@@ -193,7 +195,7 @@ describe('secp256k1', () => {
fc.assert(
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
const sig = new secp.Signature(r, s);
deepStrictEqual(secp.Signature.fromDER(sig.toDERHex()), sig);
deepStrictEqual(sigFromDER(sigToDER(sig)), sig);
})
);
});
@@ -241,9 +243,9 @@ describe('secp256k1', () => {
);
for (const [msg, exp] of CASES) {
const res = secp.sign(msg, privKey, { extraEntropy: undefined });
deepStrictEqual(res.toDERHex(), exp);
const rs = secp.Signature.fromDER(res.toDERHex()).toCompactHex();
deepStrictEqual(secp.Signature.fromCompact(rs).toDERHex(), exp);
deepStrictEqual(sigToDER(res), exp);
const rs = sigFromDER(sigToDER(res)).toCompactHex();
deepStrictEqual(sigToDER(secp.Signature.fromCompact(rs)), exp);
}
});
should('handle {extraData} option', () => {
@@ -342,7 +344,7 @@ describe('secp256k1', () => {
const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n;
const pub = new Point(x, y, 1n).toRawBytes();
const sig = new secp.Signature(r, s);
deepStrictEqual(secp.verify(sig, msg, pub, { strict: false }), true);
deepStrictEqual(secp.verify(sig, msg, pub, { lowS: false }), true);
});
should('not verify invalid deterministic signatures with RFC 6979', () => {
for (const vector of ecdsa.invalid.verify) {
@@ -351,29 +353,6 @@ describe('secp256k1', () => {
}
});
});
describe('schnorr.sign()', () => {
// index,secret key,public key,aux_rand,message,signature,verification result,comment
const vectors = schCsv
.split('\n')
.map((line) => line.split(','))
.slice(1, -1);
for (let vec of vectors) {
const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec;
should(`${comment || 'vector ' + index}`, () => {
if (sec) {
deepStrictEqual(hex(schnorr.getPublicKey(sec)), pub.toLowerCase());
const sig = schnorr.sign(msg, sec, rnd);
deepStrictEqual(hex(sig), expSig.toLowerCase());
deepStrictEqual(schnorr.verify(sig, msg, pub), true);
} else {
const passed = schnorr.verify(expSig, msg, pub);
deepStrictEqual(passed, passes === 'TRUE');
}
});
}
});
describe('recoverPublicKey()', () => {
should('recover public key from recovery bit', () => {
const message = '00000000000000000000000000000000000000000000000000000000deadbeef';
@@ -404,7 +383,7 @@ describe('secp256k1', () => {
should('handle RFC 6979 vectors', () => {
for (const vector of ecdsa.valid) {
let usig = secp.sign(vector.m, vector.d);
let sig = usig.toDERHex();
let sig = sigToDER(usig);
const vpub = secp.getPublicKey(vector.d);
const recovered = usig.recoverPublicKey(vector.m);
deepStrictEqual(recovered.toHex(), hex(vpub));
@@ -459,24 +438,25 @@ describe('secp256k1', () => {
});
describe('tweak utilities (legacy)', () => {
const Fn = Fp(secp.CURVE.n);
const normal = secp.utils._normalizePrivateKey;
const normal = secp.utils.normPrivateKeyToScalar;
const tweakUtils = {
privateAdd: (privateKey, tweak) => {
return numberToBytesBE(Fn.add(normal(privateKey), normal(tweak)), 32);
return numberToBytesBE(mod(normal(privateKey) + normal(tweak), secp.CURVE.n), 32);
},
privateNegate: (privateKey) => {
return numberToBytesBE(Fn.neg(normal(privateKey)), 32);
return numberToBytesBE(mod(-normal(privateKey), secp.CURVE.n), 32);
},
pointAddScalar: (p, tweak, isCompressed) => {
// Will throw if tweaked point is at infinity
return Point.fromHex(p).add(Point.fromPrivateKey(tweak)).toRawBytes(isCompressed);
const tweaked = Point.fromHex(p).add(Point.fromPrivateKey(tweak));
if (tweaked.equals(Point.ZERO)) throw new Error('Tweaked point at infinity');
return tweaked.toRawBytes(isCompressed);
},
pointMultiply: (p, tweak, isCompressed) => {
const t = bytesToNumberBE(ensureBytes(tweak));
if (typeof tweak === 'string') tweak = hexToBytes(tweak);
const t = bytesToNumberBE(tweak);
return Point.fromHex(p).multiply(t).toRawBytes(isCompressed);
},
};
@@ -484,20 +464,20 @@ describe('secp256k1', () => {
should('privateAdd()', () => {
for (const vector of privates.valid.add) {
const { a, b, expected } = vector;
deepStrictEqual(bytesToHex(tweakUtils.privateAdd(a, b)), expected);
deepStrictEqual(hex(tweakUtils.privateAdd(a, b)), expected);
}
});
should('privateNegate()', () => {
for (const vector of privates.valid.negate) {
const { a, expected } = vector;
deepStrictEqual(bytesToHex(tweakUtils.privateNegate(a)), expected);
deepStrictEqual(hex(tweakUtils.privateNegate(a)), expected);
}
});
should('pointAddScalar()', () => {
for (const vector of points.valid.pointAddScalar) {
const { description, P, d, expected } = vector;
const compressed = !!expected && expected.length === 66; // compressed === 33 bytes
deepStrictEqual(bytesToHex(tweakUtils.pointAddScalar(P, d, compressed)), expected);
deepStrictEqual(hex(tweakUtils.pointAddScalar(P, d, compressed)), expected);
}
});
should('pointAddScalar() invalid', () => {
@@ -509,7 +489,7 @@ describe('secp256k1', () => {
should('pointMultiply()', () => {
for (const vector of points.valid.pointMultiply) {
const { P, d, expected } = vector;
deepStrictEqual(bytesToHex(tweakUtils.pointMultiply(P, d, true)), expected);
deepStrictEqual(hex(tweakUtils.pointMultiply(P, d, true)), expected);
}
});
should('pointMultiply() invalid', () => {
@@ -523,12 +503,24 @@ describe('secp256k1', () => {
should('wycheproof vectors', () => {
for (let group of wp.testGroups) {
// const pubKey = Point.fromHex().toRawBytes();
const pubKey = group.key.uncompressed;
const key = group.publicKey;
const pubKey = key.uncompressed;
for (let test of group.tests) {
const m = secp.CURVE.hash(hexToBytes(test.msg));
const h = selectHash(secp);
const m = h(hexToBytes(test.msg));
if (test.result === 'valid' || test.result === 'acceptable') {
const verified = secp.verify(test.sig, m, pubKey);
if (secp.Signature.fromDER(test.sig).hasHighS()) {
let sig;
try {
sig = sigFromDER(test.sig);
} catch (e) {
// These old Wycheproof vectors which allows invalid behaviour of DER parser
if (e.message === 'Invalid signature integer: negative') continue;
throw e;
}
const verified = secp.verify(normVerifySig(test.sig), m, pubKey);
if (sig.hasHighS()) {
deepStrictEqual(verified, false);
} else {
deepStrictEqual(verified, true);

View File

@@ -1,201 +0,0 @@
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import * as starknet from '../../lib/esm/stark.js';
import { default as issue2 } from './fixtures/issue2.json' assert { type: 'json' };
import * as bip32 from '@scure/bip32';
import * as bip39 from '@scure/bip39';
describe('starknet basic', () => {
should('Basic elliptic sanity check', () => {
const g1 = starknet.ProjectivePoint.BASE;
deepStrictEqual(
g1.toAffine().x.toString(16),
'1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca'
);
deepStrictEqual(
g1.toAffine().y.toString(16),
'5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f'
);
const g2 = g1.double();
deepStrictEqual(
g2.toAffine().x.toString(16),
'759ca09377679ecd535a81e83039658bf40959283187c654c5416f439403cf5'
);
deepStrictEqual(
g2.toAffine().y.toString(16),
'6f524a3400e7708d5c01a28598ad272e7455aa88778b19f93b562d7a9646c41'
);
const g3 = g2.add(g1);
deepStrictEqual(
g3.toAffine().x.toString(16),
'411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20'
);
deepStrictEqual(
g3.toAffine().y.toString(16),
'7e1b3ebac08924d2c26f409549191fcf94f3bf6f301ed3553e22dfb802f0686'
);
const g32 = g1.multiply(3n);
deepStrictEqual(
g32.toAffine().x.toString(16),
'411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20'
);
deepStrictEqual(
g32.toAffine().y.toString(16),
'7e1b3ebac08924d2c26f409549191fcf94f3bf6f301ed3553e22dfb802f0686'
);
const minus1 = g1.multiply(starknet.CURVE.n - 1n);
deepStrictEqual(
minus1.toAffine().x.toString(16),
'1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca'
);
deepStrictEqual(
minus1.toAffine().y.toString(16),
'7a997f9f55b68e04841b7fe20b9139d21ac132ee541bc5cd78cfff3c91723e2'
);
});
should('Pedersen', () => {
deepStrictEqual(
starknet.pedersen(2, 3),
'0x5774fa77b3d843ae9167abd61cf80365a9b2b02218fc2f628494b5bdc9b33b8'
);
deepStrictEqual(
starknet.pedersen(1, 2),
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
);
deepStrictEqual(
starknet.pedersen(3, 4),
'0x262697b88544f733e5c6907c3e1763131e9f14c51ee7951258abbfb29415fbf'
);
});
should('Hash chain', () => {
deepStrictEqual(
starknet.hashChain([1, 2, 3]),
'0x5d9d62d4040b977c3f8d2389d494e4e89a96a8b45c44b1368f1cc6ec5418915'
);
});
should('Pedersen hash edgecases', () => {
// >>> pedersen_hash(0,0)
const zero = '0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804';
deepStrictEqual(starknet.pedersen(0, 0), zero);
deepStrictEqual(starknet.pedersen(0n, 0n), zero);
deepStrictEqual(starknet.pedersen('0', '0'), zero);
deepStrictEqual(starknet.pedersen('0x0', '0x0'), zero);
// >>> pedersen_hash(3618502788666131213697322783095070105623107215331596699973092056135872020475,3618502788666131213697322783095070105623107215331596699973092056135872020475)
// 3226051580231087455100099637526672350308978851161639703631919449959447036451
const big = 3618502788666131213697322783095070105623107215331596699973092056135872020475n;
const bigExp = '0x721e167a36655994e88efa865e2ed8a0488d36db4d988fec043cda755728223';
deepStrictEqual(starknet.pedersen(big, big), bigExp);
// >= FIELD
const big2 = 36185027886661312136973227830950701056231072153315966999730920561358720204751n;
throws(() => starknet.pedersen(big2, big2), 'big2');
// FIELD -1
const big3 = 3618502788666131213697322783095070105623107215331596699973092056135872020480n;
const big3exp = '0x7258fccaf3371fad51b117471d9d888a1786c5694c3e6099160477b593a576e';
deepStrictEqual(starknet.pedersen(big3, big3), big3exp, 'big3');
// FIELD
const big4 = 3618502788666131213697322783095070105623107215331596699973092056135872020481n;
throws(() => starknet.pedersen(big4, big4), 'big4');
throws(() => starknet.pedersen(-1, -1), 'neg');
throws(() => starknet.pedersen(false, false), 'false');
throws(() => starknet.pedersen(true, true), 'true');
throws(() => starknet.pedersen(10.1, 10.1), 'float');
});
should('hashChain edgecases', () => {
deepStrictEqual(starknet.hashChain([32312321312321312312312321n]), '0x1aba6672c014b4838cc201');
deepStrictEqual(
starknet.hashChain([1n, 2n]),
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
);
deepStrictEqual(
starknet.hashChain([1, 2]),
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
);
throws(() => starknet.hashChain([]));
throws(() => starknet.hashChain('123'));
deepStrictEqual(
starknet.hashChain([1, 2]),
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
);
});
should('Pedersen hash, issue #2', () => {
// Verified with starnet.js
deepStrictEqual(
starknet.computeHashOnElements(issue2),
'0x22064462ea33a6ce5272a295e0f551c5da3834f80d8444e7a4df68190b1bc42'
);
deepStrictEqual(
starknet.computeHashOnElements([]),
'0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804'
);
deepStrictEqual(
starknet.computeHashOnElements([1]),
'0x78d74f61aeaa8286418fd34b3a12a610445eba11d00ecc82ecac2542d55f7a4'
);
});
should('Seed derivation (example)', () => {
const layer = 'starkex';
const application = 'starkdeployement';
const mnemonic =
'range mountain blast problem vibrant void vivid doctor cluster enough melody ' +
'salt layer language laptop boat major space monkey unit glimpse pause change vibrant';
const ethAddress = '0xa4864d977b944315389d1765ffa7e66F74ee8cd7';
const hdKey = bip32.HDKey.fromMasterSeed(bip39.mnemonicToSeedSync(mnemonic)).derive(
starknet.getAccountPath(layer, application, ethAddress, 0)
);
deepStrictEqual(
starknet.grindKey(hdKey.privateKey),
'6cf0a8bf113352eb863157a45c5e5567abb34f8d32cddafd2c22aa803f4892c'
);
});
should('Compressed keys', () => {
const G = starknet.ProjectivePoint.BASE;
const half = starknet.CURVE.n / 2n;
const last = starknet.CURVE.n;
const vectors = [
1n,
2n,
3n,
4n,
5n,
half - 5n,
half - 4n,
half - 3n,
half - 2n,
half - 1n,
half,
half + 1n,
half + 2n,
half + 3n,
half + 4n,
half + 5n,
last - 5n,
last - 4n,
last - 3n,
last - 2n,
last - 1n,
].map((i) => G.multiply(i));
const fixPoint = (pt) => pt.toAffine();
for (const v of vectors) {
const uncompressed = v.toHex();
const compressed = v.toHex(true);
const exp = fixPoint(v);
deepStrictEqual(fixPoint(starknet.ProjectivePoint.fromHex(uncompressed)), exp);
deepStrictEqual(fixPoint(starknet.ProjectivePoint.fromHex(compressed)), exp);
deepStrictEqual(starknet.ProjectivePoint.fromHex(compressed).toHex(), uncompressed);
}
});
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

View File

@@ -1,57 +0,0 @@
import * as microStark from '../../../lib/esm/stark.js';
import * as starkwareCrypto from '@starkware-industries/starkware-crypto-utils';
import * as bench from 'micro-bmark';
const { run, mark } = bench; // or bench.mark
const privateKey = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
const msgHash = 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47';
const keyPair = starkwareCrypto.default.ec.keyFromPrivate(privateKey, 'hex');
const publicKeyStark = starkwareCrypto.default.ec.keyFromPublic(
keyPair.getPublic(true, 'hex'),
'hex'
);
const publicKeyMicro = microStark.getPublicKey(privateKey);
const FNS = {
pedersenHash: {
samples: 250,
starkware: () =>
starkwareCrypto.default.pedersen([
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a',
]),
'micro-starknet': () =>
microStark.pedersen(
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a'
),
},
signVerify: {
samples: 500,
starkware: () =>
starkwareCrypto.default.verify(
publicKeyStark,
msgHash,
starkwareCrypto.default.sign(keyPair, msgHash)
),
'micro-starknet': () =>
microStark.verify(microStark.sign(msgHash, privateKey), msgHash, publicKeyMicro),
},
};
const main = () =>
run(async () => {
for (let [k, libs] of Object.entries(FNS)) {
console.log(`==== ${k} ====`);
for (const [lib, fn] of Object.entries(libs)) {
if (lib === 'samples') continue;
let title = `${k} (${lib})`;
await mark(title, libs.samples, () => fn());
}
console.log();
}
// Log current RAM
bench.logMem();
});
main();

View File

@@ -1,19 +0,0 @@
{
"name": "benchmark",
"private": true,
"version": "0.1.0",
"description": "benchmarks",
"main": "index.js",
"type": "module",
"scripts": {
"bench": "node index.js"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"@starkware-industries/starkware-crypto-utils": "^0.0.2",
"micro-bmark": "0.2.0",
"micro-should": "0.2.0"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
{
"0x1": "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca",
"0x2": "0x759ca09377679ecd535a81e83039658bf40959283187c654c5416f439403cf5",
"0x3": "0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20",
"0x4": "0xa7da05a4d664859ccd6e567b935cdfbfe3018c7771cb980892ef38878ae9bc",
"0x5": "0x788435d61046d3eec54d77d25bd194525f4fa26ebe6575536bc6f656656b74c",
"0x6": "0x1efc3d7c9649900fcbd03f578a8248d095bc4b6a13b3c25f9886ef971ff96fa",
"0x7": "0x743829e0a179f8afe223fc8112dfc8d024ab6b235fd42283c4f5970259ce7b7",
"0x8": "0x6eeee2b0c71d681692559735e08a2c3ba04e7347c0c18d4d49b83bb89771591",
"0x9": "0x216b4f076ff47e03a05032d1c6ee17933d8de8b2b4c43eb5ad5a7e1b25d3849",
"0x800000000000000000000000000000000000000000000000000000000000000": "0x5c79074e7f7b834c12c81a9bb0d46691a5e7517767a849d9d98cb84e2176ed2",
"0x800000000000000000000000000000000000000000000000000000000000001": "0x1c4f24e3bd16db0e2457bc005a9d61965105a535554c6b338871e34cb8e2d3a",
"0x800000000000000000000000000000000000000000000000000000000000002": "0xdfbb89b39288a9ddacf3942b4481b04d4fa2f8ed3c424757981cc6357f27ac",
"0x800000000000000000000000000000000000000000000000000000000000003": "0x41bef28265fd750b102f4f2d1e0231de7f4a33900a214f191a63d4fec4e72f4",
"0x800000000000000000000000000000000000000000000000000000000000004": "0x24de66eb164797d4b414e81ded0cfa1a592ef0a9363ebbcb440d4d03cb18af1",
"0x800000000000000000000000000000000000000000000000000000000000005": "0x5efb18c3bc9b69003746acc85fb6ee0cfbdc6adfb982f089cc63e1e5495daad",
"0x800000000000000000000000000000000000000000000000000000000000006": "0x10dc71f00918a8ebfe4085c834d41dd22b251b9f81eef8b9a4fab77e7e1afe9",
"0x800000000000000000000000000000000000000000000000000000000000007": "0x4267ebfd379b1c8caae73febc5920b0c95bd6f9f3536f47c5ddad1259c332ff",
"0x800000000000000000000000000000000000000000000000000000000000008": "0x6da515118c8e01fd5b2e96b814ee95bad7d60be4d2ba6b47e0d283f579d9671",
"0x800000000000000000000000000000000000000000000000000000000000009": "0x7a5b4797f4e56ed1473876bc2693fbe3f2fef7e050717cbae924ff23d426052",
"0x2e9c99d8382fa004dcbbee720aef8a97002de0e991f6a8344e6dc636a71b59e": "0x1ff6803ae740e7e596504ac5c6afbea472e53679361e214f12be0155b13e25d",
"0x8620458785138df8722214e073a91b8f55076ea78197cf41007692dd27fd90": "0x5967da40b90d7ca1e36dc4024381d7d4b403c6ac1a0ab358b0743984934a805",
"0x1b920e7dfb49ba5ada673882af5342e7448d3e9335e0ac37feb6280cd7289ce": "0x78c7ab46333968fbde3201cf512c1eeb5529360259072c459a158dee4449b57",
"0x704170dbfd5dc63caef69d2ce6dfc2b2dbb2af6e75851242bbe79fb6e62a118": "0x534bd8d6ebe4bb2f6992e2d7c19ef3146247e10c2849f357e44eddd283b2af6",
"0x4b58bf4228f39550eca59b5c96a0cb606036cc9495eef9a546f24f01b1b7829": "0x1097a8c5a46d94596f1c8e70ca66941f2bb11e3c8d4fd58fdc4589f09965be8",
"0x2e93226c90fb7a2381a24e940a94b98433e3553dcbf745d3f54d62963c75604": "0x369f0e8c8e984f244290267393a004dba435a4df091767ad5063fece7b1884c",
"0x4615f94598cd756ad1a551d7e57fd725916adfd0054eb773ceb482eef87d0b2": "0x1ee5b8d612102a2408cde59ce52a6498d2e38fe8789bb26d400dea310684ec9",
"0x6ade54b7debd7ca1d4e8e932f9545f8fa4024d73be1efcc86df86367fc333f8": "0x37de3bf52412b2fb9b0030d232ca9dd921cd8f71fd67975cdc62546826e121",
"0x618e7467dd24c2a3449c4df640439c12cdd0f8ea779afcee6e252b2cf494354": "0x71c2b578c432f2d305d3808bb645ecc46dd670cb43d4f4a076f75ccbff74fbc",
"0x7eae185e1f41ec76d214d763f0592f194933622a9dd5f3d52d0209f71619c1a": "0x2b0160052e70176e5b0ff2a6eff90896ae07b732fc27219e36e077735abd57e",
"0x178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F": "0x1895a6a77ae14e7987b9cb51329a5adfb17bd8e7c638f92d6892d76e51cebcf"
}

View File

@@ -1,57 +0,0 @@
{
"private_key": "0x3c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc",
"messages": [
{
"hash": "0x1",
"r": "3162358736122783857144396205516927012128897537504463716197279730251407200037",
"s": "1447067116407676619871126378936374427636662490882969509559888874644844560850"
},
{
"hash": "0x11",
"r": "2282960348362869237018441985726545922711140064809058182483721438101695251648",
"s": "2905868291002627709651322791912000820756370440695830310841564989426104902684"
},
{
"hash": "0x223",
"r": "2851492577225522862152785068304516872062840835882746625971400995051610132955",
"s": "2227464623243182122770469099770977514100002325017609907274766387592987135410"
},
{
"hash": "0x9999",
"r": "3551214266795401081823453828727326248401688527835302880992409448142527576296",
"s": "2580950807716503852408066180369610390914312729170066679103651110985466032285"
},
{
"hash": "0x387e76d1667c4454bfb835144120583af836f8e32a516765497d23eabe16b3f",
"r": "3518448914047769356425227827389998721396724764083236823647519654917215164512",
"s": "3042321032945513635364267149196358883053166552342928199041742035443537684462"
},
{
"hash": "0x3a7e76d1697c4455bfb835144120283af236f8e32a516765497d23eabe16b2",
"r": "2261926635950780594216378185339927576862772034098248230433352748057295357217",
"s": "2708700003762962638306717009307430364534544393269844487939098184375356178572"
},
{
"hash": "0xfa5f0cd1ebff93c9e6474379a213ba111f9e42f2f1cb361b0327e0737203",
"r": "3016953906936760149710218073693613509330129567629289734816320774638425763370",
"s": "306146275372136078470081798635201810092238376869367156373203048583896337506"
},
{
"hash": "0x4c1e9550e66958296d11b60f8e8e7f7ae99dd0cfa6bd5fa652c1a6c87d4e2cc",
"r": "3562728603055564208884290243634917206833465920158600288670177317979301056463",
"s": "1958799632261808501999574190111106370256896588537275453140683641951899459876"
},
{
"hash": "0x6362b40c218fb4c8a8bd42ca482145e8513b78e00faa0de76a98ba14fc37ae8",
"r": "3485557127492692423490706790022678621438670833185864153640824729109010175518",
"s": "897592218067946175671768586886915961592526001156186496738437723857225288280"
}
]
}

View File

@@ -1,4 +0,0 @@
import './basic.test.js';
import './stark.test.js';
import './property.test.js';
import './poseidon.test.js';

View File

@@ -1,114 +0,0 @@
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import * as starknet from '../../lib/esm/stark.js';
import * as fs from 'fs';
function parseTest(path) {
let data = fs.readFileSync(path, 'ascii');
// Remove whitespaces
data = data.replace(/[ |\t]/g, '');
const pattern =
'Rate=(\\d+)\n' +
'Capacity=(\\d+)\n' +
'FullRounds=(\\d+)\n' +
'PartialRounds=(\\d+)\n' +
'MDS=\\[(.+)\\]\n' +
'RoundKeys=\\(?\n?\\[\n?(.+)\n?\\]\n?\\)?';
const r = data.match(new RegExp(pattern, 'ms'));
function parseArray(s) {
// Remove new lines
s = s.replace(/\n/gms, '');
return s.match(/(\[.+?\])/g).map((i) =>
i
.replace(/^\[(.+)\]$/, '$1')
.split(',')
.filter((i) => !!i)
);
}
const res = {
rate: +r[1],
capacity: +r[2],
roundsFull: +r[3],
roundsPartial: +r[4],
MDS: parseArray(r[5]).map((i) => i.map((j) => BigInt(j))),
roundConstants: parseArray(r[6]).map((i) => i.map((j) => BigInt(j))),
};
return res;
}
function mapPoseidon(parsed) {
return starknet.poseidonBasic(
{
Fp: starknet.Fp251,
rate: parsed.rate,
capacity: parsed.capacity,
roundsFull: parsed.roundsFull,
roundsPartial: parsed.roundsPartial,
},
parsed.MDS
);
}
const parsed = {
poseidon3: parseTest('./test/stark/poseidon/poseidon3.txt'),
poseidon4: parseTest('./test/stark/poseidon/poseidon4.txt'),
poseidon5: parseTest('./test/stark/poseidon/poseidon5.txt'),
poseidon9: parseTest('./test/stark/poseidon/poseidon9.txt'),
};
function poseidonTest(name, parsed) {
should(`${name}`, () => {
const fn = mapPoseidon(parsed);
deepStrictEqual(fn.roundConstants, parsed.roundConstants);
});
}
describe('poseidon txt vectors', () => {
poseidonTest('poseidon3', parsed.poseidon3);
poseidonTest('poseidon4', parsed.poseidon4);
poseidonTest('poseidon5', parsed.poseidon5);
poseidonTest('poseidon9', parsed.poseidon9);
});
should('Poseidon examples', () => {
const p3 = mapPoseidon(parsed.poseidon3);
deepStrictEqual(p3([0n, 0n, 0n]), [
3446325744004048536138401612021367625846492093718951375866996507163446763827n,
1590252087433376791875644726012779423683501236913937337746052470473806035332n,
867921192302518434283879514999422690776342565400001269945778456016268852423n,
]);
const p4 = mapPoseidon(parsed.poseidon4);
deepStrictEqual(p4([0n, 0n, 0n, 0n]), [
535071095200566880914603862188010633478042591441142518549720701573192347548n,
3567335813488551850156302853280844225974867890860330236555401145692518003968n,
229995103310401763929738317978722680640995513996113588430855556460153357543n,
3513983790849716360905369754287999509206472929684378838050290392634812839312n,
]);
const p5 = mapPoseidon(parsed.poseidon5);
deepStrictEqual(p5([0n, 0n, 0n, 0n, 0n]), [
2337689130971531876049206831496963607805116499042700598724344149414565980684n,
3230969295497815870174763682436655274044379544854667759151474216427142025631n,
3297330512217530111610698859408044542971696143761201570393504997742535648562n,
2585480844700786541432072704002477919020588246983274666988914431019064343941n,
3595308260654382824623573767385493361624474708214823462901432822513585995028n,
]);
const p9 = mapPoseidon(parsed.poseidon9);
deepStrictEqual(p9([0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n]), [
1534116856660032929112709488204491699743182428465681149262739677337223235050n,
1710856073207389764546990138116985223517553616229641666885337928044617114700n,
3165864635055638516987240200217592641540231237468651257819894959934472989427n,
1003007637710164252047715558598366312649052908276423203724288341354608811559n,
68117303579957054409211824649914588822081700129416361923518488718489651489n,
1123395637839379807713801282868237406546107732595903195840754789810160564711n,
478590974834311070537087181212389392308746075734019180430422247431982932503n,
835322726024358888065061514739954009068852229059154336727219387089732433787n,
3129703030204995742174502162918848446737407262178341733578946634564864233056n,
]);
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,35 +0,0 @@
# StarkWare's Poseidon Hash
[Poseidon](https://www.poseidon-hash.info/) is a family of hash functions designed for being very efficient as algebraic circuits.
As such, they may be very useful in ZK proving systems such as STARKs and others.
This repository provides the official parameters of StarkWare's Poseidon hash implementations.
All the instances are over the prime field:
p = 2^251 + 17 * 2^192 + 1 = 3618502788666131213697322783095070105623107215331596699973092056135872020481
A few examples hash results with the different parameters:
```
Poseidon3([0,0,0]) = [3446325744004048536138401612021367625846492093718951375866996507163446763827,
1590252087433376791875644726012779423683501236913937337746052470473806035332,
867921192302518434283879514999422690776342565400001269945778456016268852423]
Poseidon4([0,0,0,0]) = [535071095200566880914603862188010633478042591441142518549720701573192347548,
3567335813488551850156302853280844225974867890860330236555401145692518003968,
229995103310401763929738317978722680640995513996113588430855556460153357543,
3513983790849716360905369754287999509206472929684378838050290392634812839312]
Poseidon5([0,0,0,0,0]) = [2337689130971531876049206831496963607805116499042700598724344149414565980684,
3230969295497815870174763682436655274044379544854667759151474216427142025631,
3297330512217530111610698859408044542971696143761201570393504997742535648562,
2585480844700786541432072704002477919020588246983274666988914431019064343941,
3595308260654382824623573767385493361624474708214823462901432822513585995028]
Poseidon9([0,0,0,0,0,0,0,0,0]) = [1534116856660032929112709488204491699743182428465681149262739677337223235050,
1710856073207389764546990138116985223517553616229641666885337928044617114700,
3165864635055638516987240200217592641540231237468651257819894959934472989427,
1003007637710164252047715558598366312649052908276423203724288341354608811559,
68117303579957054409211824649914588822081700129416361923518488718489651489,
1123395637839379807713801282868237406546107732595903195840754789810160564711,
478590974834311070537087181212389392308746075734019180430422247431982932503,
835322726024358888065061514739954009068852229059154336727219387089732433787,
3129703030204995742174502162918848446737407262178341733578946634564864233056]
```

View File

@@ -1,462 +0,0 @@
Rate = 2
Capacity = 1
FullRounds = 8
PartialRounds = 83
MDS = [[3, 1, 1], [1, -1, 1], [1, 1, -2]]
RoundKeys = [
[
2950795762459345168613727575620414179244544320470208355568817838579231751791,
1587446564224215276866294500450702039420286416111469274423465069420553242820,
1645965921169490687904413452218868659025437693527479459426157555728339600137,
],
[
2782373324549879794752287702905278018819686065818504085638398966973694145741,
3409172630025222641379726933524480516420204828329395644967085131392375707302,
2379053116496905638239090788901387719228422033660130943198035907032739387135,
],
[
2570819397480941104144008784293466051718826502582588529995520356691856497111,
3546220846133880637977653625763703334841539452343273304410918449202580719746,
2720682389492889709700489490056111332164748138023159726590726667539759963454,
],
[
1899653471897224903834726250400246354200311275092866725547887381599836519005,
2369443697923857319844855392163763375394720104106200469525915896159690979559,
2354174693689535854311272135513626412848402744119855553970180659094265527996,
],
[
2404084503073127963385083467393598147276436640877011103379112521338973185443,
950320777137731763811524327595514151340412860090489448295239456547370725376,
2121140748740143694053732746913428481442990369183417228688865837805149503386,
],
[
2372065044800422557577242066480215868569521938346032514014152523102053709709,
2618497439310693947058545060953893433487994458443568169824149550389484489896,
3518297267402065742048564133910509847197496119850246255805075095266319996916,
],
[
340529752683340505065238931581518232901634742162506851191464448040657139775,
1954876811294863748406056845662382214841467408616109501720437541211031966538,
813813157354633930267029888722341725864333883175521358739311868164460385261,
],
[
71901595776070443337150458310956362034911936706490730914901986556638720031,
2789761472166115462625363403490399263810962093264318361008954888847594113421,
2628791615374802560074754031104384456692791616314774034906110098358135152410,
],
[
3617032588734559635167557152518265808024917503198278888820567553943986939719,
2624012360209966117322788103333497793082705816015202046036057821340914061980,
149101987103211771991327927827692640556911620408176100290586418839323044234,
],
[
1039927963829140138166373450440320262590862908847727961488297105916489431045,
2213946951050724449162431068646025833746639391992751674082854766704900195669,
2792724903541814965769131737117981991997031078369482697195201969174353468597,
],
[
3212031629728871219804596347439383805499808476303618848198208101593976279441,
3343514080098703935339621028041191631325798327656683100151836206557453199613,
614054702436541219556958850933730254992710988573177298270089989048553060199,
],
[
148148081026449726283933484730968827750202042869875329032965774667206931170,
1158283532103191908366672518396366136968613180867652172211392033571980848414,
1032400527342371389481069504520755916075559110755235773196747439146396688513,
],
[
806900704622005851310078578853499250941978435851598088619290797134710613736,
462498083559902778091095573017508352472262817904991134671058825705968404510,
1003580119810278869589347418043095667699674425582646347949349245557449452503,
],
[
619074932220101074089137133998298830285661916867732916607601635248249357793,
2635090520059500019661864086615522409798872905401305311748231832709078452746,
978252636251682252755279071140187792306115352460774007308726210405257135181,
],
[
1766912167973123409669091967764158892111310474906691336473559256218048677083,
1663265127259512472182980890707014969235283233442916350121860684522654120381,
3532407621206959585000336211742670185380751515636605428496206887841428074250,
],
[
2507023127157093845256722098502856938353143387711652912931112668310034975446,
3321152907858462102434883844787153373036767230808678981306827073335525034593,
3039253036806065280643845548147711477270022154459620569428286684179698125661,
],
[
103480338868480851881924519768416587261556021758163719199282794248762465380,
2394049781357087698434751577708655768465803975478348134669006211289636928495,
2660531560345476340796109810821127229446538730404600368347902087220064379579,
],
[
3603166934034556203649050570865466556260359798872408576857928196141785055563,
1553799760191949768532188139643704561532896296986025007089826672890485412324,
2744284717053657689091306578463476341218866418732695211367062598446038965164,
],
[
320745764922149897598257794663594419839885234101078803811049904310835548856,
979382242100682161589753881721708883681034024104145498709287731138044566302,
1860426855810549882740147175136418997351054138609396651615467358416651354991,
],
[
336173081054369235994909356892506146234495707857220254489443629387613956145,
1632470326779699229772327605759783482411227247311431865655466227711078175883,
921958250077481394074960433988881176409497663777043304881055317463712938502,
],
[
3034358982193370602048539901033542101022185309652879937418114324899281842797,
25626282149517463867572353922222474817434101087272320606729439087234878607,
3002662261401575565838149305485737102400501329139562227180277188790091853682,
],
[
2939684373453383817196521641512509179310654199629514917426341354023324109367,
1076484609897998179434851570277297233169621096172424141759873688902355505136,
2575095284833160494841112025725243274091830284746697961080467506739203605049,
],
[
3565075264617591783581665711620369529657840830498005563542124551465195621851,
2197016502533303822395077038351174326125210255869204501838837289716363437993,
331415322883530754594261416546036195982886300052707474899691116664327869405,
],
[
1935011233711290003793244296594669823169522055520303479680359990463281661839,
3495901467168087413996941216661589517270845976538454329511167073314577412322,
954195417117133246453562983448451025087661597543338750600301835944144520375,
],
[
1271840477709992894995746871435810599280944810893784031132923384456797925777,
2565310762274337662754531859505158700827688964841878141121196528015826671847,
3365022288251637014588279139038152521653896670895105540140002607272936852513,
],
[
1660592021628965529963974299647026602622092163312666588591285654477111176051,
970104372286014048279296575474974982288801187216974504035759997141059513421,
2617024574317953753849168721871770134225690844968986289121504184985993971227,
],
[
999899815343607746071464113462778273556695659506865124478430189024755832262,
2228536129413411161615629030408828764980855956560026807518714080003644769896,
2701953891198001564547196795777701119629537795442025393867364730330476403227,
],
[
837078355588159388741598313782044128527494922918203556465116291436461597853,
2121749601840466143704862369657561429793951309962582099604848281796392359214,
771812260179247428733132708063116523892339056677915387749121983038690154755,
],
[
3317336423132806446086732225036532603224267214833263122557471741829060578219,
481570067997721834712647566896657604857788523050900222145547508314620762046,
242195042559343964206291740270858862066153636168162642380846129622127460192,
],
[
2855462178889999218204481481614105202770810647859867354506557827319138379686,
3525521107148375040131784770413887305850308357895464453970651672160034885202,
1320839531502392535964065058804908871811967681250362364246430459003920305799,
],
[
2514191518588387125173345107242226637171897291221681115249521904869763202419,
2798335750958827619666318316247381695117827718387653874070218127140615157902,
2808467767967035643407948058486565877867906577474361783201337540214875566395,
],
[
3551834385992706206273955480294669176699286104229279436819137165202231595747,
1219439673853113792340300173186247996249367102884530407862469123523013083971,
761519904537984520554247997444508040636526566551719396202550009393012691157,
],
[
3355402549169351700500518865338783382387571349497391475317206324155237401353,
199541098009731541347317515995192175813554789571447733944970283654592727138,
192100490643078165121235261796864975568292640203635147901612231594408079071,
],
[
1187019357602953326192019968809486933768550466167033084944727938441427050581,
189525349641911362389041124808934468936759383310282010671081989585219065700,
2831653363992091308880573627558515686245403755586311978724025292003353336665,
],
[
2052859812632218952608271535089179639890275494426396974475479657192657094698,
1670756178709659908159049531058853320846231785448204274277900022176591811072,
3538757242013734574731807289786598937548399719866320954894004830207085723125,
],
[
710549042741321081781917034337800036872214466705318638023070812391485261299,
2345013122330545298606028187653996682275206910242635100920038943391319595180,
3528369671971445493932880023233332035122954362711876290904323783426765912206,
],
[
1167120829038120978297497195837406760848728897181138760506162680655977700764,
3073243357129146594530765548901087443775563058893907738967898816092270628884,
378514724418106317738164464176041649567501099164061863402473942795977719726,
],
[
333391138410406330127594722511180398159664250722328578952158227406762627796,
1727570175639917398410201375510924114487348765559913502662122372848626931905,
968312190621809249603425066974405725769739606059422769908547372904403793174,
],
[
360659316299446405855194688051178331671817370423873014757323462844775818348,
1386580151907705298970465943238806620109618995410132218037375811184684929291,
3604888328937389309031638299660239238400230206645344173700074923133890528967,
],
[
2496185632263372962152518155651824899299616724241852816983268163379540137546,
486538168871046887467737983064272608432052269868418721234810979756540672990,
1558415498960552213241704009433360128041672577274390114589014204605400783336,
],
[
3512058327686147326577190314835092911156317204978509183234511559551181053926,
2235429387083113882635494090887463486491842634403047716936833563914243946191,
1290896777143878193192832813769470418518651727840187056683408155503813799882,
],
[
1143310336918357319571079551779316654556781203013096026972411429993634080835,
3235435208525081966062419599803346573407862428113723170955762956243193422118,
1293239921425673430660897025143433077974838969258268884994339615096356996604,
],
[
236252269127612784685426260840574970698541177557674806964960352572864382971,
1733907592497266237374827232200506798207318263912423249709509725341212026275,
302004309771755665128395814807589350526779835595021835389022325987048089868,
],
[
3018926838139221755384801385583867283206879023218491758435446265703006270945,
39701437664873825906031098349904330565195980985885489447836580931425171297,
908381723021746969965674308809436059628307487140174335882627549095646509778,
],
[
219062858908229855064136253265968615354041842047384625689776811853821594358,
1283129863776453589317845316917890202859466483456216900835390291449830275503,
418512623547417594896140369190919231877873410935689672661226540908900544012,
],
[
1792181590047131972851015200157890246436013346535432437041535789841136268632,
370546432987510607338044736824316856592558876687225326692366316978098770516,
3323437805230586112013581113386626899534419826098235300155664022709435756946,
],
[
910076621742039763058481476739499965761942516177975130656340375573185415877,
1762188042455633427137702520675816545396284185254002959309669405982213803405,
2186362253913140345102191078329764107619534641234549431429008219905315900520,
],
[
2230647725927681765419218738218528849146504088716182944327179019215826045083,
1069243907556644434301190076451112491469636357133398376850435321160857761825,
2695241469149243992683268025359863087303400907336026926662328156934068747593,
],
[
1361519681544413849831669554199151294308350560528931040264950307931824877035,
1339116632207878730171031743761550901312154740800549632983325427035029084904,
790593524918851401449292693473498591068920069246127392274811084156907468875,
],
[
2723400368331924254840192318398326090089058735091724263333980290765736363637,
3457180265095920471443772463283225391927927225993685928066766687141729456030,
1483675376954327086153452545475557749815683871577400883707749788555424847954,
],
[
2926303836265506736227240325795090239680154099205721426928300056982414025239,
543969119775473768170832347411484329362572550684421616624136244239799475526,
237401230683847084256617415614300816373730178313253487575312839074042461932,
],
[
844568412840391587862072008674263874021460074878949862892685736454654414423,
151922054871708336050647150237534498235916969120198637893731715254687336644,
1299332034710622815055321547569101119597030148120309411086203580212105652312,
],
[
487046922649899823989594814663418784068895385009696501386459462815688122993,
1104883249092599185744249485896585912845784382683240114120846423960548576851,
1458388705536282069567179348797334876446380557083422364875248475157495514484,
],
[
850248109622750774031817200193861444623975329881731864752464222442574976566,
2885843173858536690032695698009109793537724845140477446409245651176355435722,
3027068551635372249579348422266406787688980506275086097330568993357835463816,
],
[
3231892723647447539926175383213338123506134054432701323145045438168976970994,
1719080830641935421242626784132692936776388194122314954558418655725251172826,
1172253756541066126131022537343350498482225068791630219494878195815226839450,
],
[
1619232269633026603732619978083169293258272967781186544174521481891163985093,
3495680684841853175973173610562400042003100419811771341346135531754869014567,
1576161515913099892951745452471618612307857113799539794680346855318958552758,
],
[
2618326122974253423403350731396350223238201817594761152626832144510903048529,
2696245132758436974032479782852265185094623165224532063951287925001108567649,
930116505665110070247395429730201844026054810856263733273443066419816003444,
],
[
2786389174502246248523918824488629229455088716707062764363111940462137404076,
1555260846425735320214671887347115247546042526197895180675436886484523605116,
2306241912153325247392671742757902161446877415586158295423293240351799505917,
],
[
411529621724849932999694270803131456243889635467661223241617477462914950626,
1542495485262286701469125140275904136434075186064076910329015697714211835205,
1853045663799041100600825096887578544265580718909350942241802897995488264551,
],
[
2963055259497271220202739837493041799968576111953080503132045092194513937286,
2303806870349915764285872605046527036748108533406243381676768310692344456050,
2622104986201990620910286730213140904984256464479840856728424375142929278875,
],
[
2369987021925266811581727383184031736927816625797282287927222602539037105864,
285070227712021899602056480426671736057274017903028992288878116056674401781,
3034087076179360957800568733595959058628497428787907887933697691951454610691,
],
[
469095854351700119980323115747590868855368701825706298740201488006320881056,
360001976264385426746283365024817520563236378289230404095383746911725100012,
3438709327109021347267562000879503009590697221730578667498351600602230296178,
],
[
63573904800572228121671659287593650438456772568903228287754075619928214969,
3470881855042989871434874691030920672110111605547839662680968354703074556970,
724559311507950497340993415408274803001166693839947519425501269424891465492,
],
[
880409284677518997550768549487344416321062350742831373397603704465823658986,
6876255662475867703077362872097208259197756317287339941435193538565586230,
2701916445133770775447884812906226786217969545216086200932273680400909154638,
],
[
425152119158711585559310064242720816611629181537672850898056934507216982586,
1475552998258917706756737045704649573088377604240716286977690565239187213744,
2413772448122400684309006716414417978370152271397082147158000439863002593561,
],
[
392160855822256520519339260245328807036619920858503984710539815951012864164,
1075036996503791536261050742318169965707018400307026402939804424927087093987,
2176439430328703902070742432016450246365760303014562857296722712989275658921,
],
[
1413865976587623331051814207977382826721471106513581745229680113383908569693,
4879283427490523253696177116563427032332223531862961281430108575019551814,
3392583297537374046875199552977614390492290683707960975137418536812266544902,
],
[
3600854486849487646325182927019642276644093512133907046667282144129939150983,
2779924664161372134024229593301361846129279572186444474616319283535189797834,
2722699960903170449291146429799738181514821447014433304730310678334403972040,
],
[
819109815049226540285781191874507704729062681836086010078910930707209464699,
3046121243742768013822760785918001632929744274211027071381357122228091333823,
1339019590803056172509793134119156250729668216522001157582155155947567682278,
],
[
1933279639657506214789316403763326578443023901555983256955812717638093967201,
2138221547112520744699126051903811860205771600821672121643894708182292213541,
2694713515543641924097704224170357995809887124438248292930846280951601597065,
],
[
2471734202930133750093618989223585244499567111661178960753938272334153710615,
504903761112092757611047718215309856203214372330635774577409639907729993533,
1943979703748281357156510253941035712048221353507135074336243405478613241290,
],
[
684525210957572142559049112233609445802004614280157992196913315652663518936,
1705585400798782397786453706717059483604368413512485532079242223503960814508,
192429517716023021556170942988476050278432319516032402725586427701913624665,
],
[
1586493702243128040549584165333371192888583026298039652930372758731750166765,
686072673323546915014972146032384917012218151266600268450347114036285993377,
3464340397998075738891129996710075228740496767934137465519455338004332839215,
],
[
2805249176617071054530589390406083958753103601524808155663551392362371834663,
667746464250968521164727418691487653339733392025160477655836902744186489526,
1131527712905109997177270289411406385352032457456054589588342450404257139778,
],
[
1908969485750011212309284349900149072003218505891252313183123635318886241171,
1025257076985551890132050019084873267454083056307650830147063480409707787695,
2153175291918371429502545470578981828372846236838301412119329786849737957977,
],
[
3410257749736714576487217882785226905621212230027780855361670645857085424384,
3442969106887588154491488961893254739289120695377621434680934888062399029952,
3029953900235731770255937704976720759948880815387104275525268727341390470237,
],
[
85453456084781138713939104192561924536933417707871501802199311333127894466,
2730629666577257820220329078741301754580009106438115341296453318350676425129,
178242450661072967256438102630920745430303027840919213764087927763335940415,
],
[
2844589222514708695700541363167856718216388819406388706818431442998498677557,
3547876269219141094308889387292091231377253967587961309624916269569559952944,
2525005406762984211707203144785482908331876505006839217175334833739957826850,
],
[
3096397013555211396701910432830904669391580557191845136003938801598654871345,
574424067119200181933992948252007230348512600107123873197603373898923821490,
1714030696055067278349157346067719307863507310709155690164546226450579547098,
],
[
2339895272202694698739231405357972261413383527237194045718815176814132612501,
3562501318971895161271663840954705079797767042115717360959659475564651685069,
69069358687197963617161747606993436483967992689488259107924379545671193749,
],
[
2614502738369008850475068874731531583863538486212691941619835266611116051561,
655247349763023251625727726218660142895322325659927266813592114640858573566,
2305235672527595714255517865498269719545193172975330668070873705108690670678,
],
[
926416070297755413261159098243058134401665060349723804040714357642180531931,
866523735635840246543516964237513287099659681479228450791071595433217821460,
2284334068466681424919271582037156124891004191915573957556691163266198707693,
],
[
1812588309302477291425732810913354633465435706480768615104211305579383928792,
2836899808619013605432050476764608707770404125005720004551836441247917488507,
2989087789022865112405242078196235025698647423649950459911546051695688370523,
],
[
68056284404189102136488263779598243992465747932368669388126367131855404486,
505425339250887519581119854377342241317528319745596963584548343662758204398,
2118963546856545068961709089296976921067035227488975882615462246481055679215,
],
[
2253872596319969096156004495313034590996995209785432485705134570745135149681,
1625090409149943603241183848936692198923183279116014478406452426158572703264,
179139838844452470348634657368199622305888473747024389514258107503778442495,
],
[
1567067018147735642071130442904093290030432522257811793540290101391210410341,
2737301854006865242314806979738760349397411136469975337509958305470398783585,
3002738216460904473515791428798860225499078134627026021350799206894618186256,
],
[
374029488099466837453096950537275565120689146401077127482884887409712315162,
973403256517481077805460710540468856199855789930951602150773500862180885363,
2691967457038172130555117632010860984519926022632800605713473799739632878867,
],
[
3515906794910381201365530594248181418811879320679684239326734893975752012109,
148057579455448384062325089530558091463206199724854022070244924642222283388,
1541588700238272710315890873051237741033408846596322948443180470429851502842,
],
[
147013865879011936545137344076637170977925826031496203944786839068852795297,
2630278389304735265620281704608245039972003761509102213752997636382302839857,
1359048670759642844930007747955701205155822111403150159614453244477853867621,
],
[
2438984569205812336319229336885480537793786558293523767186829418969842616677,
2137792255841525507649318539501906353254503076308308692873313199435029594138,
2262318076430740712267739371170174514379142884859595360065535117601097652755,
],
[
2792703718581084537295613508201818489836796608902614779596544185252826291584,
2294173715793292812015960640392421991604150133581218254866878921346561546149,
2770011224727997178743274791849308200493823127651418989170761007078565678171,
],
]

View File

@@ -1,559 +0,0 @@
Rate = 3
Capacity = 1
FullRounds = 8
PartialRounds = 84
MDS = [[2, 1, 1, 1], [1, 1, 1, 1], [1, 1, 0, 1], [1, 1, 1, -1]]
RoundKeys = [
[
2950795762459345168613727575620414179244544320470208355568817838579231751791,
1587446564224215276866294500450702039420286416111469274423465069420553242820,
1645965921169490687904413452218868659025437693527479459426157555728339600137,
2782373324549879794752287702905278018819686065818504085638398966973694145741,
],
[
3409172630025222641379726933524480516420204828329395644967085131392375707302,
2379053116496905638239090788901387719228422033660130943198035907032739387135,
2570819397480941104144008784293466051718826502582588529995520356691856497111,
3546220846133880637977653625763703334841539452343273304410918449202580719746,
],
[
2720682389492889709700489490056111332164748138023159726590726667539759963454,
1899653471897224903834726250400246354200311275092866725547887381599836519005,
2369443697923857319844855392163763375394720104106200469525915896159690979559,
2354174693689535854311272135513626412848402744119855553970180659094265527996,
],
[
2404084503073127963385083467393598147276436640877011103379112521338973185443,
950320777137731763811524327595514151340412860090489448295239456547370725376,
2121140748740143694053732746913428481442990369183417228688865837805149503386,
2372065044800422557577242066480215868569521938346032514014152523102053709709,
],
[
2618497439310693947058545060953893433487994458443568169824149550389484489896,
3518297267402065742048564133910509847197496119850246255805075095266319996916,
340529752683340505065238931581518232901634742162506851191464448040657139775,
1954876811294863748406056845662382214841467408616109501720437541211031966538,
],
[
813813157354633930267029888722341725864333883175521358739311868164460385261,
71901595776070443337150458310956362034911936706490730914901986556638720031,
2789761472166115462625363403490399263810962093264318361008954888847594113421,
2628791615374802560074754031104384456692791616314774034906110098358135152410,
],
[
3617032588734559635167557152518265808024917503198278888820567553943986939719,
2624012360209966117322788103333497793082705816015202046036057821340914061980,
149101987103211771991327927827692640556911620408176100290586418839323044234,
1039927963829140138166373450440320262590862908847727961488297105916489431045,
],
[
2213946951050724449162431068646025833746639391992751674082854766704900195669,
2792724903541814965769131737117981991997031078369482697195201969174353468597,
3212031629728871219804596347439383805499808476303618848198208101593976279441,
3343514080098703935339621028041191631325798327656683100151836206557453199613,
],
[
614054702436541219556958850933730254992710988573177298270089989048553060199,
148148081026449726283933484730968827750202042869875329032965774667206931170,
1158283532103191908366672518396366136968613180867652172211392033571980848414,
1032400527342371389481069504520755916075559110755235773196747439146396688513,
],
[
806900704622005851310078578853499250941978435851598088619290797134710613736,
462498083559902778091095573017508352472262817904991134671058825705968404510,
1003580119810278869589347418043095667699674425582646347949349245557449452503,
619074932220101074089137133998298830285661916867732916607601635248249357793,
],
[
2635090520059500019661864086615522409798872905401305311748231832709078452746,
978252636251682252755279071140187792306115352460774007308726210405257135181,
1766912167973123409669091967764158892111310474906691336473559256218048677083,
1663265127259512472182980890707014969235283233442916350121860684522654120381,
],
[
3532407621206959585000336211742670185380751515636605428496206887841428074250,
2507023127157093845256722098502856938353143387711652912931112668310034975446,
3321152907858462102434883844787153373036767230808678981306827073335525034593,
3039253036806065280643845548147711477270022154459620569428286684179698125661,
],
[
103480338868480851881924519768416587261556021758163719199282794248762465380,
2394049781357087698434751577708655768465803975478348134669006211289636928495,
2660531560345476340796109810821127229446538730404600368347902087220064379579,
3603166934034556203649050570865466556260359798872408576857928196141785055563,
],
[
1553799760191949768532188139643704561532896296986025007089826672890485412324,
2744284717053657689091306578463476341218866418732695211367062598446038965164,
320745764922149897598257794663594419839885234101078803811049904310835548856,
979382242100682161589753881721708883681034024104145498709287731138044566302,
],
[
1860426855810549882740147175136418997351054138609396651615467358416651354991,
336173081054369235994909356892506146234495707857220254489443629387613956145,
1632470326779699229772327605759783482411227247311431865655466227711078175883,
921958250077481394074960433988881176409497663777043304881055317463712938502,
],
[
3034358982193370602048539901033542101022185309652879937418114324899281842797,
25626282149517463867572353922222474817434101087272320606729439087234878607,
3002662261401575565838149305485737102400501329139562227180277188790091853682,
2939684373453383817196521641512509179310654199629514917426341354023324109367,
],
[
1076484609897998179434851570277297233169621096172424141759873688902355505136,
2575095284833160494841112025725243274091830284746697961080467506739203605049,
3565075264617591783581665711620369529657840830498005563542124551465195621851,
2197016502533303822395077038351174326125210255869204501838837289716363437993,
],
[
331415322883530754594261416546036195982886300052707474899691116664327869405,
1935011233711290003793244296594669823169522055520303479680359990463281661839,
3495901467168087413996941216661589517270845976538454329511167073314577412322,
954195417117133246453562983448451025087661597543338750600301835944144520375,
],
[
1271840477709992894995746871435810599280944810893784031132923384456797925777,
2565310762274337662754531859505158700827688964841878141121196528015826671847,
3365022288251637014588279139038152521653896670895105540140002607272936852513,
1660592021628965529963974299647026602622092163312666588591285654477111176051,
],
[
970104372286014048279296575474974982288801187216974504035759997141059513421,
2617024574317953753849168721871770134225690844968986289121504184985993971227,
999899815343607746071464113462778273556695659506865124478430189024755832262,
2228536129413411161615629030408828764980855956560026807518714080003644769896,
],
[
2701953891198001564547196795777701119629537795442025393867364730330476403227,
837078355588159388741598313782044128527494922918203556465116291436461597853,
2121749601840466143704862369657561429793951309962582099604848281796392359214,
771812260179247428733132708063116523892339056677915387749121983038690154755,
],
[
3317336423132806446086732225036532603224267214833263122557471741829060578219,
481570067997721834712647566896657604857788523050900222145547508314620762046,
242195042559343964206291740270858862066153636168162642380846129622127460192,
2855462178889999218204481481614105202770810647859867354506557827319138379686,
],
[
3525521107148375040131784770413887305850308357895464453970651672160034885202,
1320839531502392535964065058804908871811967681250362364246430459003920305799,
2514191518588387125173345107242226637171897291221681115249521904869763202419,
2798335750958827619666318316247381695117827718387653874070218127140615157902,
],
[
2808467767967035643407948058486565877867906577474361783201337540214875566395,
3551834385992706206273955480294669176699286104229279436819137165202231595747,
1219439673853113792340300173186247996249367102884530407862469123523013083971,
761519904537984520554247997444508040636526566551719396202550009393012691157,
],
[
3355402549169351700500518865338783382387571349497391475317206324155237401353,
199541098009731541347317515995192175813554789571447733944970283654592727138,
192100490643078165121235261796864975568292640203635147901612231594408079071,
1187019357602953326192019968809486933768550466167033084944727938441427050581,
],
[
189525349641911362389041124808934468936759383310282010671081989585219065700,
2831653363992091308880573627558515686245403755586311978724025292003353336665,
2052859812632218952608271535089179639890275494426396974475479657192657094698,
1670756178709659908159049531058853320846231785448204274277900022176591811072,
],
[
3538757242013734574731807289786598937548399719866320954894004830207085723125,
710549042741321081781917034337800036872214466705318638023070812391485261299,
2345013122330545298606028187653996682275206910242635100920038943391319595180,
3528369671971445493932880023233332035122954362711876290904323783426765912206,
],
[
1167120829038120978297497195837406760848728897181138760506162680655977700764,
3073243357129146594530765548901087443775563058893907738967898816092270628884,
378514724418106317738164464176041649567501099164061863402473942795977719726,
333391138410406330127594722511180398159664250722328578952158227406762627796,
],
[
1727570175639917398410201375510924114487348765559913502662122372848626931905,
968312190621809249603425066974405725769739606059422769908547372904403793174,
360659316299446405855194688051178331671817370423873014757323462844775818348,
1386580151907705298970465943238806620109618995410132218037375811184684929291,
],
[
3604888328937389309031638299660239238400230206645344173700074923133890528967,
2496185632263372962152518155651824899299616724241852816983268163379540137546,
486538168871046887467737983064272608432052269868418721234810979756540672990,
1558415498960552213241704009433360128041672577274390114589014204605400783336,
],
[
3512058327686147326577190314835092911156317204978509183234511559551181053926,
2235429387083113882635494090887463486491842634403047716936833563914243946191,
1290896777143878193192832813769470418518651727840187056683408155503813799882,
1143310336918357319571079551779316654556781203013096026972411429993634080835,
],
[
3235435208525081966062419599803346573407862428113723170955762956243193422118,
1293239921425673430660897025143433077974838969258268884994339615096356996604,
236252269127612784685426260840574970698541177557674806964960352572864382971,
1733907592497266237374827232200506798207318263912423249709509725341212026275,
],
[
302004309771755665128395814807589350526779835595021835389022325987048089868,
3018926838139221755384801385583867283206879023218491758435446265703006270945,
39701437664873825906031098349904330565195980985885489447836580931425171297,
908381723021746969965674308809436059628307487140174335882627549095646509778,
],
[
219062858908229855064136253265968615354041842047384625689776811853821594358,
1283129863776453589317845316917890202859466483456216900835390291449830275503,
418512623547417594896140369190919231877873410935689672661226540908900544012,
1792181590047131972851015200157890246436013346535432437041535789841136268632,
],
[
370546432987510607338044736824316856592558876687225326692366316978098770516,
3323437805230586112013581113386626899534419826098235300155664022709435756946,
910076621742039763058481476739499965761942516177975130656340375573185415877,
1762188042455633427137702520675816545396284185254002959309669405982213803405,
],
[
2186362253913140345102191078329764107619534641234549431429008219905315900520,
2230647725927681765419218738218528849146504088716182944327179019215826045083,
1069243907556644434301190076451112491469636357133398376850435321160857761825,
2695241469149243992683268025359863087303400907336026926662328156934068747593,
],
[
1361519681544413849831669554199151294308350560528931040264950307931824877035,
1339116632207878730171031743761550901312154740800549632983325427035029084904,
790593524918851401449292693473498591068920069246127392274811084156907468875,
2723400368331924254840192318398326090089058735091724263333980290765736363637,
],
[
3457180265095920471443772463283225391927927225993685928066766687141729456030,
1483675376954327086153452545475557749815683871577400883707749788555424847954,
2926303836265506736227240325795090239680154099205721426928300056982414025239,
543969119775473768170832347411484329362572550684421616624136244239799475526,
],
[
237401230683847084256617415614300816373730178313253487575312839074042461932,
844568412840391587862072008674263874021460074878949862892685736454654414423,
151922054871708336050647150237534498235916969120198637893731715254687336644,
1299332034710622815055321547569101119597030148120309411086203580212105652312,
],
[
487046922649899823989594814663418784068895385009696501386459462815688122993,
1104883249092599185744249485896585912845784382683240114120846423960548576851,
1458388705536282069567179348797334876446380557083422364875248475157495514484,
850248109622750774031817200193861444623975329881731864752464222442574976566,
],
[
2885843173858536690032695698009109793537724845140477446409245651176355435722,
3027068551635372249579348422266406787688980506275086097330568993357835463816,
3231892723647447539926175383213338123506134054432701323145045438168976970994,
1719080830641935421242626784132692936776388194122314954558418655725251172826,
],
[
1172253756541066126131022537343350498482225068791630219494878195815226839450,
1619232269633026603732619978083169293258272967781186544174521481891163985093,
3495680684841853175973173610562400042003100419811771341346135531754869014567,
1576161515913099892951745452471618612307857113799539794680346855318958552758,
],
[
2618326122974253423403350731396350223238201817594761152626832144510903048529,
2696245132758436974032479782852265185094623165224532063951287925001108567649,
930116505665110070247395429730201844026054810856263733273443066419816003444,
2786389174502246248523918824488629229455088716707062764363111940462137404076,
],
[
1555260846425735320214671887347115247546042526197895180675436886484523605116,
2306241912153325247392671742757902161446877415586158295423293240351799505917,
411529621724849932999694270803131456243889635467661223241617477462914950626,
1542495485262286701469125140275904136434075186064076910329015697714211835205,
],
[
1853045663799041100600825096887578544265580718909350942241802897995488264551,
2963055259497271220202739837493041799968576111953080503132045092194513937286,
2303806870349915764285872605046527036748108533406243381676768310692344456050,
2622104986201990620910286730213140904984256464479840856728424375142929278875,
],
[
2369987021925266811581727383184031736927816625797282287927222602539037105864,
285070227712021899602056480426671736057274017903028992288878116056674401781,
3034087076179360957800568733595959058628497428787907887933697691951454610691,
469095854351700119980323115747590868855368701825706298740201488006320881056,
],
[
360001976264385426746283365024817520563236378289230404095383746911725100012,
3438709327109021347267562000879503009590697221730578667498351600602230296178,
63573904800572228121671659287593650438456772568903228287754075619928214969,
3470881855042989871434874691030920672110111605547839662680968354703074556970,
],
[
724559311507950497340993415408274803001166693839947519425501269424891465492,
880409284677518997550768549487344416321062350742831373397603704465823658986,
6876255662475867703077362872097208259197756317287339941435193538565586230,
2701916445133770775447884812906226786217969545216086200932273680400909154638,
],
[
425152119158711585559310064242720816611629181537672850898056934507216982586,
1475552998258917706756737045704649573088377604240716286977690565239187213744,
2413772448122400684309006716414417978370152271397082147158000439863002593561,
392160855822256520519339260245328807036619920858503984710539815951012864164,
],
[
1075036996503791536261050742318169965707018400307026402939804424927087093987,
2176439430328703902070742432016450246365760303014562857296722712989275658921,
1413865976587623331051814207977382826721471106513581745229680113383908569693,
4879283427490523253696177116563427032332223531862961281430108575019551814,
],
[
3392583297537374046875199552977614390492290683707960975137418536812266544902,
3600854486849487646325182927019642276644093512133907046667282144129939150983,
2779924664161372134024229593301361846129279572186444474616319283535189797834,
2722699960903170449291146429799738181514821447014433304730310678334403972040,
],
[
819109815049226540285781191874507704729062681836086010078910930707209464699,
3046121243742768013822760785918001632929744274211027071381357122228091333823,
1339019590803056172509793134119156250729668216522001157582155155947567682278,
1933279639657506214789316403763326578443023901555983256955812717638093967201,
],
[
2138221547112520744699126051903811860205771600821672121643894708182292213541,
2694713515543641924097704224170357995809887124438248292930846280951601597065,
2471734202930133750093618989223585244499567111661178960753938272334153710615,
504903761112092757611047718215309856203214372330635774577409639907729993533,
],
[
1943979703748281357156510253941035712048221353507135074336243405478613241290,
684525210957572142559049112233609445802004614280157992196913315652663518936,
1705585400798782397786453706717059483604368413512485532079242223503960814508,
192429517716023021556170942988476050278432319516032402725586427701913624665,
],
[
1586493702243128040549584165333371192888583026298039652930372758731750166765,
686072673323546915014972146032384917012218151266600268450347114036285993377,
3464340397998075738891129996710075228740496767934137465519455338004332839215,
2805249176617071054530589390406083958753103601524808155663551392362371834663,
],
[
667746464250968521164727418691487653339733392025160477655836902744186489526,
1131527712905109997177270289411406385352032457456054589588342450404257139778,
1908969485750011212309284349900149072003218505891252313183123635318886241171,
1025257076985551890132050019084873267454083056307650830147063480409707787695,
],
[
2153175291918371429502545470578981828372846236838301412119329786849737957977,
3410257749736714576487217882785226905621212230027780855361670645857085424384,
3442969106887588154491488961893254739289120695377621434680934888062399029952,
3029953900235731770255937704976720759948880815387104275525268727341390470237,
],
[
85453456084781138713939104192561924536933417707871501802199311333127894466,
2730629666577257820220329078741301754580009106438115341296453318350676425129,
178242450661072967256438102630920745430303027840919213764087927763335940415,
2844589222514708695700541363167856718216388819406388706818431442998498677557,
],
[
3547876269219141094308889387292091231377253967587961309624916269569559952944,
2525005406762984211707203144785482908331876505006839217175334833739957826850,
3096397013555211396701910432830904669391580557191845136003938801598654871345,
574424067119200181933992948252007230348512600107123873197603373898923821490,
],
[
1714030696055067278349157346067719307863507310709155690164546226450579547098,
2339895272202694698739231405357972261413383527237194045718815176814132612501,
3562501318971895161271663840954705079797767042115717360959659475564651685069,
69069358687197963617161747606993436483967992689488259107924379545671193749,
],
[
2614502738369008850475068874731531583863538486212691941619835266611116051561,
655247349763023251625727726218660142895322325659927266813592114640858573566,
2305235672527595714255517865498269719545193172975330668070873705108690670678,
926416070297755413261159098243058134401665060349723804040714357642180531931,
],
[
866523735635840246543516964237513287099659681479228450791071595433217821460,
2284334068466681424919271582037156124891004191915573957556691163266198707693,
1812588309302477291425732810913354633465435706480768615104211305579383928792,
2836899808619013605432050476764608707770404125005720004551836441247917488507,
],
[
2989087789022865112405242078196235025698647423649950459911546051695688370523,
68056284404189102136488263779598243992465747932368669388126367131855404486,
505425339250887519581119854377342241317528319745596963584548343662758204398,
2118963546856545068961709089296976921067035227488975882615462246481055679215,
],
[
2253872596319969096156004495313034590996995209785432485705134570745135149681,
1625090409149943603241183848936692198923183279116014478406452426158572703264,
179139838844452470348634657368199622305888473747024389514258107503778442495,
1567067018147735642071130442904093290030432522257811793540290101391210410341,
],
[
2737301854006865242314806979738760349397411136469975337509958305470398783585,
3002738216460904473515791428798860225499078134627026021350799206894618186256,
374029488099466837453096950537275565120689146401077127482884887409712315162,
973403256517481077805460710540468856199855789930951602150773500862180885363,
],
[
2691967457038172130555117632010860984519926022632800605713473799739632878867,
3515906794910381201365530594248181418811879320679684239326734893975752012109,
148057579455448384062325089530558091463206199724854022070244924642222283388,
1541588700238272710315890873051237741033408846596322948443180470429851502842,
],
[
147013865879011936545137344076637170977925826031496203944786839068852795297,
2630278389304735265620281704608245039972003761509102213752997636382302839857,
1359048670759642844930007747955701205155822111403150159614453244477853867621,
2438984569205812336319229336885480537793786558293523767186829418969842616677,
],
[
2137792255841525507649318539501906353254503076308308692873313199435029594138,
2262318076430740712267739371170174514379142884859595360065535117601097652755,
2792703718581084537295613508201818489836796608902614779596544185252826291584,
2294173715793292812015960640392421991604150133581218254866878921346561546149,
],
[
2770011224727997178743274791849308200493823127651418989170761007078565678171,
3321642244537785916275181932172303118112488081726311374164578600576901819844,
3522708517589950573320671158134804505970724681591943826922697952040487655044,
3417974441436557992524691506735790206623600049454586729879955931972546347402,
],
[
175039333145381316571259690443853067809784261609912638686739799135919647022,
1930713062131033273316869231148248962041053029742760224583505092759642967464,
2971452932574554603554350185069538580257636405419430340233233400633251319042,
2774781903758215341037075610938953949868289195845367046186588750871862784919,
],
[
666516874137869653699423537799457099346460194092311952417454613224504932738,
1900462225013533249140457703727169176351786259991305560412832202759625668041,
2665631186082687279121709429531834469477679375137509769347092380798929714377,
837840745988147279235494664091280091563355097569199320366973125128366540061,
],
[
3391544118305848781823721719916289805455110924839794510205940718821197620955,
2888553035909938253628892138500390690221493345071933642853222968481016605919,
3386241569867597612447901482685846444743718781330869478721963580925825915450,
1205126220630896984850042596877918177217334376800874965105642874206963597698,
],
[
3590072615491710252422997155203204584659171612188004116415640739580250394190,
692469013329617220154003334549812915100479873898898958632988703738125356983,
1623178235190707102808841905143937367808788834203621005714003335195182126335,
1972826180775011489122426045504602288576507493792470102803637471568052321297,
],
[
3415141329098504418158191749675997877417539760075593313736376750580696083073,
587811537889727046473915684463981273175495137461951211739526104349163747811,
2523982964351069134084525951849317400231659428055762640605248929856135518199,
2686176526711834950207666047281383173339057216783586039351834948812568447629,
],
[
983144446441739425577690449774542566745526459152966545642451764143532586964,
171558252019175695567663688494555626159399786667979998273792882504784080805,
332337623010057542760158225837623039780806442976079546879646069338600179518,
1264669683963885571544813806669118319675288608634733888843804451222546848295,
],
[
2426165115815723668018318268486497504249785449504758403912155206515511627681,
11387399609384288947733630450855186629703576293221897150193655994854764608,
2541728569046079092074077754414781968906176513081761690404588216304985421091,
47685947554980329431290582269851186106577733250761848107645535357326439312,
],
[
472176388418187405374813530639596064799362505024895746833751173199773896628,
2764298116617383397920343358525617195195060562266243809245480210157942112738,
486863835068754002670800862273365477867695879270721744227071001883208334054,
2973492686137102577527656941792991264994301121122130295965761350095846874635,
],
[
178385615141132702906181473263873416748818415607305319148067639744074654009,
533624640096756667052211553746016402543259206286603356120804827761339634127,
819406716720171922688026098737835227857400444543748198788964759773510472096,
531851793767260921861217458033110066464894334064526987603936107947006031387,
],
[
3269709072483585277009748181134917746036523619604017812342933951952104134829,
838191718603413598040249006803464503100808192944407407147899973659013630611,
1574561296941310904780257598780779812250055948216417844567262310524022037406,
551394354289003977607664358739006072556227894953233419144430578080352094737,
],
[
445076790942318675726839050057337819004979443030540904213920669247413907302,
1963946696292687224902912968478695543164747600779913024040878700455222386521,
484284614181963381509745298932402076252103342403432879800905151752488144767,
2240507606126946994415203252302826782042951346966859379502140796364876543253,
],
[
3237135638753992982179886898758938279897590886053928839613434762582576319619,
2334333034701915027889533058426879447140084891006486138782876488162658230991,
14411091399844539897439754491034751977136685514851444574462584316609631592,
1264480371592407258420308876448697804787923638319277097663041109464608464284,
],
[
671929312763821646360589403212798993954209530574443543917757335777610372144,
2513909805455654095962542944994577107405216428214873444765576238504714067396,
870121102846043786263357605823753628974859886859187558617096145653709171231,
399132620893316356411986266679786708905730068946836982293484206366500277754,
],
[
2855046250836680633532995284655778407402587437073106249445470889390454667586,
2063679741125384345396981490971605710211281905716315529671473143278849561151,
1433753212258929925682201698758056443128516570551146995210728194816988328337,
3334984763425011856632257855270507440816274246647423607159847074739331865077,
],
[
337911293622078184850923533628334646725451591671907148383867096651211846605,
559587005295238702015018022040357402231957131094636365177008701077975941644,
885963059604819264377490633589388189646118257469490919900554134369512794660,
1957748763518471091057032383332840331641373304981058387824598000170709016333,
],
[
3175295982155056798972302481564899381103533409383494814704562889625572018450,
498987160612401618114584726510347771865331516606886613019084323862447372555,
947374835104260364630171441676101001841507588423166778786886198914150312958,
906933977754491302438795274167251538820934378773708095543613756654712689280,
],
[
2170116291766863179909957030577284618726490893598499117272497866180009722894,
1801335399574515889082584621772588704763181408217893911806726119813067220453,
1942500232535842474530840356353427989892065499159260166135596750084681859966,
62936080219825306823124060587235998278756755377419521154040408253893795176,
],
[
3091993939935137795359769774909373279950941171574748645375255810204590357753,
1283528386884634267663661033944552098742115012555712906773586466375284501324,
1581820717639229420476069802992937438655873471854930764425841549067913106065,
2301986095388751633126546121528329200085681648876910655269533407603441046514,
],
[
2850003828037698751961753862613545302539465803982364898225617297398939302949,
48024691078494936445046366770271288984930221238071705874025261821606393528,
1482336297033144958942154923925185950152551534403871620222916667536030875354,
3081177564717719643771186007689458633949181485535169123213511264603782950049,
],
[
3315701127039521853279746297714590495201061397709680410650043502532250578075,
3514407611000441301995070394422463400067690470546731164089622325748803106020,
368970178199930154322724953487299516224498421233447528815195701420122548537,
584353160413525267849669053228533951552602295860601556035386665117717227391,
],
[
752038702160385294706011538400822066722189014251268673051846350397729870418,
3594041683498798688197194521326299097635429790757880308152971477196489335154,
1367902435756906062215608264424138718742854099315395230911274560900857414183,
1828549068951502746189364466794037234789986878381694857475972053743463890779,
],
[
488172495141237210878388657234137733008417573114482400652274985829148564248,
962906242461930394022372340919543491337923491322497419797555620396501785566,
2275418085010046236619290386129138234541669589549771944697082317642065048898,
1966395064658902622886154686288219600816893261614483533899715888994623208964,
],
[
3496095878293416917311185659829821476802828534554531050412634978086916288609,
3368478822390537245916137403277928093536087427951052230723275731232142463388,
3397410259276620127103231993277518800970669191016277541098821699302368873803,
2662600899665871010006649609856695263727220473364611552472965243032255906029,
],
]

View File

@@ -1,651 +0,0 @@
Rate = 4
Capacity = 1
FullRounds = 8
PartialRounds = 84
MDS = [[3, 1, 1, 1, 1], [1, 2, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, -1, 1], [1, 1, 1, 1, -2]]
RoundKeys = [
[
2950795762459345168613727575620414179244544320470208355568817838579231751791,
1587446564224215276866294500450702039420286416111469274423465069420553242820,
1645965921169490687904413452218868659025437693527479459426157555728339600137,
2782373324549879794752287702905278018819686065818504085638398966973694145741,
3409172630025222641379726933524480516420204828329395644967085131392375707302,
],
[
2379053116496905638239090788901387719228422033660130943198035907032739387135,
2570819397480941104144008784293466051718826502582588529995520356691856497111,
3546220846133880637977653625763703334841539452343273304410918449202580719746,
2720682389492889709700489490056111332164748138023159726590726667539759963454,
1899653471897224903834726250400246354200311275092866725547887381599836519005,
],
[
2369443697923857319844855392163763375394720104106200469525915896159690979559,
2354174693689535854311272135513626412848402744119855553970180659094265527996,
2404084503073127963385083467393598147276436640877011103379112521338973185443,
950320777137731763811524327595514151340412860090489448295239456547370725376,
2121140748740143694053732746913428481442990369183417228688865837805149503386,
],
[
2372065044800422557577242066480215868569521938346032514014152523102053709709,
2618497439310693947058545060953893433487994458443568169824149550389484489896,
3518297267402065742048564133910509847197496119850246255805075095266319996916,
340529752683340505065238931581518232901634742162506851191464448040657139775,
1954876811294863748406056845662382214841467408616109501720437541211031966538,
],
[
813813157354633930267029888722341725864333883175521358739311868164460385261,
71901595776070443337150458310956362034911936706490730914901986556638720031,
2789761472166115462625363403490399263810962093264318361008954888847594113421,
2628791615374802560074754031104384456692791616314774034906110098358135152410,
3617032588734559635167557152518265808024917503198278888820567553943986939719,
],
[
2624012360209966117322788103333497793082705816015202046036057821340914061980,
149101987103211771991327927827692640556911620408176100290586418839323044234,
1039927963829140138166373450440320262590862908847727961488297105916489431045,
2213946951050724449162431068646025833746639391992751674082854766704900195669,
2792724903541814965769131737117981991997031078369482697195201969174353468597,
],
[
3212031629728871219804596347439383805499808476303618848198208101593976279441,
3343514080098703935339621028041191631325798327656683100151836206557453199613,
614054702436541219556958850933730254992710988573177298270089989048553060199,
148148081026449726283933484730968827750202042869875329032965774667206931170,
1158283532103191908366672518396366136968613180867652172211392033571980848414,
],
[
1032400527342371389481069504520755916075559110755235773196747439146396688513,
806900704622005851310078578853499250941978435851598088619290797134710613736,
462498083559902778091095573017508352472262817904991134671058825705968404510,
1003580119810278869589347418043095667699674425582646347949349245557449452503,
619074932220101074089137133998298830285661916867732916607601635248249357793,
],
[
2635090520059500019661864086615522409798872905401305311748231832709078452746,
978252636251682252755279071140187792306115352460774007308726210405257135181,
1766912167973123409669091967764158892111310474906691336473559256218048677083,
1663265127259512472182980890707014969235283233442916350121860684522654120381,
3532407621206959585000336211742670185380751515636605428496206887841428074250,
],
[
2507023127157093845256722098502856938353143387711652912931112668310034975446,
3321152907858462102434883844787153373036767230808678981306827073335525034593,
3039253036806065280643845548147711477270022154459620569428286684179698125661,
103480338868480851881924519768416587261556021758163719199282794248762465380,
2394049781357087698434751577708655768465803975478348134669006211289636928495,
],
[
2660531560345476340796109810821127229446538730404600368347902087220064379579,
3603166934034556203649050570865466556260359798872408576857928196141785055563,
1553799760191949768532188139643704561532896296986025007089826672890485412324,
2744284717053657689091306578463476341218866418732695211367062598446038965164,
320745764922149897598257794663594419839885234101078803811049904310835548856,
],
[
979382242100682161589753881721708883681034024104145498709287731138044566302,
1860426855810549882740147175136418997351054138609396651615467358416651354991,
336173081054369235994909356892506146234495707857220254489443629387613956145,
1632470326779699229772327605759783482411227247311431865655466227711078175883,
921958250077481394074960433988881176409497663777043304881055317463712938502,
],
[
3034358982193370602048539901033542101022185309652879937418114324899281842797,
25626282149517463867572353922222474817434101087272320606729439087234878607,
3002662261401575565838149305485737102400501329139562227180277188790091853682,
2939684373453383817196521641512509179310654199629514917426341354023324109367,
1076484609897998179434851570277297233169621096172424141759873688902355505136,
],
[
2575095284833160494841112025725243274091830284746697961080467506739203605049,
3565075264617591783581665711620369529657840830498005563542124551465195621851,
2197016502533303822395077038351174326125210255869204501838837289716363437993,
331415322883530754594261416546036195982886300052707474899691116664327869405,
1935011233711290003793244296594669823169522055520303479680359990463281661839,
],
[
3495901467168087413996941216661589517270845976538454329511167073314577412322,
954195417117133246453562983448451025087661597543338750600301835944144520375,
1271840477709992894995746871435810599280944810893784031132923384456797925777,
2565310762274337662754531859505158700827688964841878141121196528015826671847,
3365022288251637014588279139038152521653896670895105540140002607272936852513,
],
[
1660592021628965529963974299647026602622092163312666588591285654477111176051,
970104372286014048279296575474974982288801187216974504035759997141059513421,
2617024574317953753849168721871770134225690844968986289121504184985993971227,
999899815343607746071464113462778273556695659506865124478430189024755832262,
2228536129413411161615629030408828764980855956560026807518714080003644769896,
],
[
2701953891198001564547196795777701119629537795442025393867364730330476403227,
837078355588159388741598313782044128527494922918203556465116291436461597853,
2121749601840466143704862369657561429793951309962582099604848281796392359214,
771812260179247428733132708063116523892339056677915387749121983038690154755,
3317336423132806446086732225036532603224267214833263122557471741829060578219,
],
[
481570067997721834712647566896657604857788523050900222145547508314620762046,
242195042559343964206291740270858862066153636168162642380846129622127460192,
2855462178889999218204481481614105202770810647859867354506557827319138379686,
3525521107148375040131784770413887305850308357895464453970651672160034885202,
1320839531502392535964065058804908871811967681250362364246430459003920305799,
],
[
2514191518588387125173345107242226637171897291221681115249521904869763202419,
2798335750958827619666318316247381695117827718387653874070218127140615157902,
2808467767967035643407948058486565877867906577474361783201337540214875566395,
3551834385992706206273955480294669176699286104229279436819137165202231595747,
1219439673853113792340300173186247996249367102884530407862469123523013083971,
],
[
761519904537984520554247997444508040636526566551719396202550009393012691157,
3355402549169351700500518865338783382387571349497391475317206324155237401353,
199541098009731541347317515995192175813554789571447733944970283654592727138,
192100490643078165121235261796864975568292640203635147901612231594408079071,
1187019357602953326192019968809486933768550466167033084944727938441427050581,
],
[
189525349641911362389041124808934468936759383310282010671081989585219065700,
2831653363992091308880573627558515686245403755586311978724025292003353336665,
2052859812632218952608271535089179639890275494426396974475479657192657094698,
1670756178709659908159049531058853320846231785448204274277900022176591811072,
3538757242013734574731807289786598937548399719866320954894004830207085723125,
],
[
710549042741321081781917034337800036872214466705318638023070812391485261299,
2345013122330545298606028187653996682275206910242635100920038943391319595180,
3528369671971445493932880023233332035122954362711876290904323783426765912206,
1167120829038120978297497195837406760848728897181138760506162680655977700764,
3073243357129146594530765548901087443775563058893907738967898816092270628884,
],
[
378514724418106317738164464176041649567501099164061863402473942795977719726,
333391138410406330127594722511180398159664250722328578952158227406762627796,
1727570175639917398410201375510924114487348765559913502662122372848626931905,
968312190621809249603425066974405725769739606059422769908547372904403793174,
360659316299446405855194688051178331671817370423873014757323462844775818348,
],
[
1386580151907705298970465943238806620109618995410132218037375811184684929291,
3604888328937389309031638299660239238400230206645344173700074923133890528967,
2496185632263372962152518155651824899299616724241852816983268163379540137546,
486538168871046887467737983064272608432052269868418721234810979756540672990,
1558415498960552213241704009433360128041672577274390114589014204605400783336,
],
[
3512058327686147326577190314835092911156317204978509183234511559551181053926,
2235429387083113882635494090887463486491842634403047716936833563914243946191,
1290896777143878193192832813769470418518651727840187056683408155503813799882,
1143310336918357319571079551779316654556781203013096026972411429993634080835,
3235435208525081966062419599803346573407862428113723170955762956243193422118,
],
[
1293239921425673430660897025143433077974838969258268884994339615096356996604,
236252269127612784685426260840574970698541177557674806964960352572864382971,
1733907592497266237374827232200506798207318263912423249709509725341212026275,
302004309771755665128395814807589350526779835595021835389022325987048089868,
3018926838139221755384801385583867283206879023218491758435446265703006270945,
],
[
39701437664873825906031098349904330565195980985885489447836580931425171297,
908381723021746969965674308809436059628307487140174335882627549095646509778,
219062858908229855064136253265968615354041842047384625689776811853821594358,
1283129863776453589317845316917890202859466483456216900835390291449830275503,
418512623547417594896140369190919231877873410935689672661226540908900544012,
],
[
1792181590047131972851015200157890246436013346535432437041535789841136268632,
370546432987510607338044736824316856592558876687225326692366316978098770516,
3323437805230586112013581113386626899534419826098235300155664022709435756946,
910076621742039763058481476739499965761942516177975130656340375573185415877,
1762188042455633427137702520675816545396284185254002959309669405982213803405,
],
[
2186362253913140345102191078329764107619534641234549431429008219905315900520,
2230647725927681765419218738218528849146504088716182944327179019215826045083,
1069243907556644434301190076451112491469636357133398376850435321160857761825,
2695241469149243992683268025359863087303400907336026926662328156934068747593,
1361519681544413849831669554199151294308350560528931040264950307931824877035,
],
[
1339116632207878730171031743761550901312154740800549632983325427035029084904,
790593524918851401449292693473498591068920069246127392274811084156907468875,
2723400368331924254840192318398326090089058735091724263333980290765736363637,
3457180265095920471443772463283225391927927225993685928066766687141729456030,
1483675376954327086153452545475557749815683871577400883707749788555424847954,
],
[
2926303836265506736227240325795090239680154099205721426928300056982414025239,
543969119775473768170832347411484329362572550684421616624136244239799475526,
237401230683847084256617415614300816373730178313253487575312839074042461932,
844568412840391587862072008674263874021460074878949862892685736454654414423,
151922054871708336050647150237534498235916969120198637893731715254687336644,
],
[
1299332034710622815055321547569101119597030148120309411086203580212105652312,
487046922649899823989594814663418784068895385009696501386459462815688122993,
1104883249092599185744249485896585912845784382683240114120846423960548576851,
1458388705536282069567179348797334876446380557083422364875248475157495514484,
850248109622750774031817200193861444623975329881731864752464222442574976566,
],
[
2885843173858536690032695698009109793537724845140477446409245651176355435722,
3027068551635372249579348422266406787688980506275086097330568993357835463816,
3231892723647447539926175383213338123506134054432701323145045438168976970994,
1719080830641935421242626784132692936776388194122314954558418655725251172826,
1172253756541066126131022537343350498482225068791630219494878195815226839450,
],
[
1619232269633026603732619978083169293258272967781186544174521481891163985093,
3495680684841853175973173610562400042003100419811771341346135531754869014567,
1576161515913099892951745452471618612307857113799539794680346855318958552758,
2618326122974253423403350731396350223238201817594761152626832144510903048529,
2696245132758436974032479782852265185094623165224532063951287925001108567649,
],
[
930116505665110070247395429730201844026054810856263733273443066419816003444,
2786389174502246248523918824488629229455088716707062764363111940462137404076,
1555260846425735320214671887347115247546042526197895180675436886484523605116,
2306241912153325247392671742757902161446877415586158295423293240351799505917,
411529621724849932999694270803131456243889635467661223241617477462914950626,
],
[
1542495485262286701469125140275904136434075186064076910329015697714211835205,
1853045663799041100600825096887578544265580718909350942241802897995488264551,
2963055259497271220202739837493041799968576111953080503132045092194513937286,
2303806870349915764285872605046527036748108533406243381676768310692344456050,
2622104986201990620910286730213140904984256464479840856728424375142929278875,
],
[
2369987021925266811581727383184031736927816625797282287927222602539037105864,
285070227712021899602056480426671736057274017903028992288878116056674401781,
3034087076179360957800568733595959058628497428787907887933697691951454610691,
469095854351700119980323115747590868855368701825706298740201488006320881056,
360001976264385426746283365024817520563236378289230404095383746911725100012,
],
[
3438709327109021347267562000879503009590697221730578667498351600602230296178,
63573904800572228121671659287593650438456772568903228287754075619928214969,
3470881855042989871434874691030920672110111605547839662680968354703074556970,
724559311507950497340993415408274803001166693839947519425501269424891465492,
880409284677518997550768549487344416321062350742831373397603704465823658986,
],
[
6876255662475867703077362872097208259197756317287339941435193538565586230,
2701916445133770775447884812906226786217969545216086200932273680400909154638,
425152119158711585559310064242720816611629181537672850898056934507216982586,
1475552998258917706756737045704649573088377604240716286977690565239187213744,
2413772448122400684309006716414417978370152271397082147158000439863002593561,
],
[
392160855822256520519339260245328807036619920858503984710539815951012864164,
1075036996503791536261050742318169965707018400307026402939804424927087093987,
2176439430328703902070742432016450246365760303014562857296722712989275658921,
1413865976587623331051814207977382826721471106513581745229680113383908569693,
4879283427490523253696177116563427032332223531862961281430108575019551814,
],
[
3392583297537374046875199552977614390492290683707960975137418536812266544902,
3600854486849487646325182927019642276644093512133907046667282144129939150983,
2779924664161372134024229593301361846129279572186444474616319283535189797834,
2722699960903170449291146429799738181514821447014433304730310678334403972040,
819109815049226540285781191874507704729062681836086010078910930707209464699,
],
[
3046121243742768013822760785918001632929744274211027071381357122228091333823,
1339019590803056172509793134119156250729668216522001157582155155947567682278,
1933279639657506214789316403763326578443023901555983256955812717638093967201,
2138221547112520744699126051903811860205771600821672121643894708182292213541,
2694713515543641924097704224170357995809887124438248292930846280951601597065,
],
[
2471734202930133750093618989223585244499567111661178960753938272334153710615,
504903761112092757611047718215309856203214372330635774577409639907729993533,
1943979703748281357156510253941035712048221353507135074336243405478613241290,
684525210957572142559049112233609445802004614280157992196913315652663518936,
1705585400798782397786453706717059483604368413512485532079242223503960814508,
],
[
192429517716023021556170942988476050278432319516032402725586427701913624665,
1586493702243128040549584165333371192888583026298039652930372758731750166765,
686072673323546915014972146032384917012218151266600268450347114036285993377,
3464340397998075738891129996710075228740496767934137465519455338004332839215,
2805249176617071054530589390406083958753103601524808155663551392362371834663,
],
[
667746464250968521164727418691487653339733392025160477655836902744186489526,
1131527712905109997177270289411406385352032457456054589588342450404257139778,
1908969485750011212309284349900149072003218505891252313183123635318886241171,
1025257076985551890132050019084873267454083056307650830147063480409707787695,
2153175291918371429502545470578981828372846236838301412119329786849737957977,
],
[
3410257749736714576487217882785226905621212230027780855361670645857085424384,
3442969106887588154491488961893254739289120695377621434680934888062399029952,
3029953900235731770255937704976720759948880815387104275525268727341390470237,
85453456084781138713939104192561924536933417707871501802199311333127894466,
2730629666577257820220329078741301754580009106438115341296453318350676425129,
],
[
178242450661072967256438102630920745430303027840919213764087927763335940415,
2844589222514708695700541363167856718216388819406388706818431442998498677557,
3547876269219141094308889387292091231377253967587961309624916269569559952944,
2525005406762984211707203144785482908331876505006839217175334833739957826850,
3096397013555211396701910432830904669391580557191845136003938801598654871345,
],
[
574424067119200181933992948252007230348512600107123873197603373898923821490,
1714030696055067278349157346067719307863507310709155690164546226450579547098,
2339895272202694698739231405357972261413383527237194045718815176814132612501,
3562501318971895161271663840954705079797767042115717360959659475564651685069,
69069358687197963617161747606993436483967992689488259107924379545671193749,
],
[
2614502738369008850475068874731531583863538486212691941619835266611116051561,
655247349763023251625727726218660142895322325659927266813592114640858573566,
2305235672527595714255517865498269719545193172975330668070873705108690670678,
926416070297755413261159098243058134401665060349723804040714357642180531931,
866523735635840246543516964237513287099659681479228450791071595433217821460,
],
[
2284334068466681424919271582037156124891004191915573957556691163266198707693,
1812588309302477291425732810913354633465435706480768615104211305579383928792,
2836899808619013605432050476764608707770404125005720004551836441247917488507,
2989087789022865112405242078196235025698647423649950459911546051695688370523,
68056284404189102136488263779598243992465747932368669388126367131855404486,
],
[
505425339250887519581119854377342241317528319745596963584548343662758204398,
2118963546856545068961709089296976921067035227488975882615462246481055679215,
2253872596319969096156004495313034590996995209785432485705134570745135149681,
1625090409149943603241183848936692198923183279116014478406452426158572703264,
179139838844452470348634657368199622305888473747024389514258107503778442495,
],
[
1567067018147735642071130442904093290030432522257811793540290101391210410341,
2737301854006865242314806979738760349397411136469975337509958305470398783585,
3002738216460904473515791428798860225499078134627026021350799206894618186256,
374029488099466837453096950537275565120689146401077127482884887409712315162,
973403256517481077805460710540468856199855789930951602150773500862180885363,
],
[
2691967457038172130555117632010860984519926022632800605713473799739632878867,
3515906794910381201365530594248181418811879320679684239326734893975752012109,
148057579455448384062325089530558091463206199724854022070244924642222283388,
1541588700238272710315890873051237741033408846596322948443180470429851502842,
147013865879011936545137344076637170977925826031496203944786839068852795297,
],
[
2630278389304735265620281704608245039972003761509102213752997636382302839857,
1359048670759642844930007747955701205155822111403150159614453244477853867621,
2438984569205812336319229336885480537793786558293523767186829418969842616677,
2137792255841525507649318539501906353254503076308308692873313199435029594138,
2262318076430740712267739371170174514379142884859595360065535117601097652755,
],
[
2792703718581084537295613508201818489836796608902614779596544185252826291584,
2294173715793292812015960640392421991604150133581218254866878921346561546149,
2770011224727997178743274791849308200493823127651418989170761007078565678171,
3321642244537785916275181932172303118112488081726311374164578600576901819844,
3522708517589950573320671158134804505970724681591943826922697952040487655044,
],
[
3417974441436557992524691506735790206623600049454586729879955931972546347402,
175039333145381316571259690443853067809784261609912638686739799135919647022,
1930713062131033273316869231148248962041053029742760224583505092759642967464,
2971452932574554603554350185069538580257636405419430340233233400633251319042,
2774781903758215341037075610938953949868289195845367046186588750871862784919,
],
[
666516874137869653699423537799457099346460194092311952417454613224504932738,
1900462225013533249140457703727169176351786259991305560412832202759625668041,
2665631186082687279121709429531834469477679375137509769347092380798929714377,
837840745988147279235494664091280091563355097569199320366973125128366540061,
3391544118305848781823721719916289805455110924839794510205940718821197620955,
],
[
2888553035909938253628892138500390690221493345071933642853222968481016605919,
3386241569867597612447901482685846444743718781330869478721963580925825915450,
1205126220630896984850042596877918177217334376800874965105642874206963597698,
3590072615491710252422997155203204584659171612188004116415640739580250394190,
692469013329617220154003334549812915100479873898898958632988703738125356983,
],
[
1623178235190707102808841905143937367808788834203621005714003335195182126335,
1972826180775011489122426045504602288576507493792470102803637471568052321297,
3415141329098504418158191749675997877417539760075593313736376750580696083073,
587811537889727046473915684463981273175495137461951211739526104349163747811,
2523982964351069134084525951849317400231659428055762640605248929856135518199,
],
[
2686176526711834950207666047281383173339057216783586039351834948812568447629,
983144446441739425577690449774542566745526459152966545642451764143532586964,
171558252019175695567663688494555626159399786667979998273792882504784080805,
332337623010057542760158225837623039780806442976079546879646069338600179518,
1264669683963885571544813806669118319675288608634733888843804451222546848295,
],
[
2426165115815723668018318268486497504249785449504758403912155206515511627681,
11387399609384288947733630450855186629703576293221897150193655994854764608,
2541728569046079092074077754414781968906176513081761690404588216304985421091,
47685947554980329431290582269851186106577733250761848107645535357326439312,
472176388418187405374813530639596064799362505024895746833751173199773896628,
],
[
2764298116617383397920343358525617195195060562266243809245480210157942112738,
486863835068754002670800862273365477867695879270721744227071001883208334054,
2973492686137102577527656941792991264994301121122130295965761350095846874635,
178385615141132702906181473263873416748818415607305319148067639744074654009,
533624640096756667052211553746016402543259206286603356120804827761339634127,
],
[
819406716720171922688026098737835227857400444543748198788964759773510472096,
531851793767260921861217458033110066464894334064526987603936107947006031387,
3269709072483585277009748181134917746036523619604017812342933951952104134829,
838191718603413598040249006803464503100808192944407407147899973659013630611,
1574561296941310904780257598780779812250055948216417844567262310524022037406,
],
[
551394354289003977607664358739006072556227894953233419144430578080352094737,
445076790942318675726839050057337819004979443030540904213920669247413907302,
1963946696292687224902912968478695543164747600779913024040878700455222386521,
484284614181963381509745298932402076252103342403432879800905151752488144767,
2240507606126946994415203252302826782042951346966859379502140796364876543253,
],
[
3237135638753992982179886898758938279897590886053928839613434762582576319619,
2334333034701915027889533058426879447140084891006486138782876488162658230991,
14411091399844539897439754491034751977136685514851444574462584316609631592,
1264480371592407258420308876448697804787923638319277097663041109464608464284,
671929312763821646360589403212798993954209530574443543917757335777610372144,
],
[
2513909805455654095962542944994577107405216428214873444765576238504714067396,
870121102846043786263357605823753628974859886859187558617096145653709171231,
399132620893316356411986266679786708905730068946836982293484206366500277754,
2855046250836680633532995284655778407402587437073106249445470889390454667586,
2063679741125384345396981490971605710211281905716315529671473143278849561151,
],
[
1433753212258929925682201698758056443128516570551146995210728194816988328337,
3334984763425011856632257855270507440816274246647423607159847074739331865077,
337911293622078184850923533628334646725451591671907148383867096651211846605,
559587005295238702015018022040357402231957131094636365177008701077975941644,
885963059604819264377490633589388189646118257469490919900554134369512794660,
],
[
1957748763518471091057032383332840331641373304981058387824598000170709016333,
3175295982155056798972302481564899381103533409383494814704562889625572018450,
498987160612401618114584726510347771865331516606886613019084323862447372555,
947374835104260364630171441676101001841507588423166778786886198914150312958,
906933977754491302438795274167251538820934378773708095543613756654712689280,
],
[
2170116291766863179909957030577284618726490893598499117272497866180009722894,
1801335399574515889082584621772588704763181408217893911806726119813067220453,
1942500232535842474530840356353427989892065499159260166135596750084681859966,
62936080219825306823124060587235998278756755377419521154040408253893795176,
3091993939935137795359769774909373279950941171574748645375255810204590357753,
],
[
1283528386884634267663661033944552098742115012555712906773586466375284501324,
1581820717639229420476069802992937438655873471854930764425841549067913106065,
2301986095388751633126546121528329200085681648876910655269533407603441046514,
2850003828037698751961753862613545302539465803982364898225617297398939302949,
48024691078494936445046366770271288984930221238071705874025261821606393528,
],
[
1482336297033144958942154923925185950152551534403871620222916667536030875354,
3081177564717719643771186007689458633949181485535169123213511264603782950049,
3315701127039521853279746297714590495201061397709680410650043502532250578075,
3514407611000441301995070394422463400067690470546731164089622325748803106020,
368970178199930154322724953487299516224498421233447528815195701420122548537,
],
[
584353160413525267849669053228533951552602295860601556035386665117717227391,
752038702160385294706011538400822066722189014251268673051846350397729870418,
3594041683498798688197194521326299097635429790757880308152971477196489335154,
1367902435756906062215608264424138718742854099315395230911274560900857414183,
1828549068951502746189364466794037234789986878381694857475972053743463890779,
],
[
488172495141237210878388657234137733008417573114482400652274985829148564248,
962906242461930394022372340919543491337923491322497419797555620396501785566,
2275418085010046236619290386129138234541669589549771944697082317642065048898,
1966395064658902622886154686288219600816893261614483533899715888994623208964,
3496095878293416917311185659829821476802828534554531050412634978086916288609,
],
[
3368478822390537245916137403277928093536087427951052230723275731232142463388,
3397410259276620127103231993277518800970669191016277541098821699302368873803,
2662600899665871010006649609856695263727220473364611552472965243032255906029,
2854831720595596992200155718152374313555878203864206470581502555480894633975,
2417859092561967752135741161218626374900182454089059862468108240576782064037,
],
[
1064506915903089299531724594973601253341866933071158266140674053459433520889,
243845138053687262800349059300355289745206315347524675450796070948867090098,
1952653154963756062322124110012629666160000286707762177032475477295929736283,
2760979128531476595658428672038276216079708408852493051222686009638650156041,
3341178930260137001230946104398194306290005446746057811731360203227371301716,
],
[
1033242545866274439991875444609632860132556714736615395036273942261573810479,
3567973410830779135148598005871071456943945697865168835204985462698751038238,
23014034649293369426970379738102323014738017168969687350330825050016457105,
1146720508452451012445869043641390200263192255569203352823376998708972325392,
2553707028642376593497768606567528232999203496079990242456254686325586089356,
],
[
269729857648436699208023125596593246149228245518586029792966091405383426269,
276912682886955358118649215147238115764108757952690361549816619060658800027,
2367180947887796341722261610916728725977893583923967218630363334645641817362,
2398694802751362950028137620758033447242325333923222365760836442417755445092,
984868389243025029364428136317275892280780834039611841422502834917752411391,
],
[
861353329558771468244040268521983016756775808329676883407171471251365927595,
2498672969617384807617108262141800974986393948110233099680635130601163654234,
1336236634145657673540555267430353130305889434115514586892320600753700983325,
980337801407886250576371882962628290239239581416378379141354256717803603922,
2308558359523317875952657835109605515063994805873180719205156915762120497245,
],
[
2116737905426837141304542819940293184404010538896700217242374222514653607487,
2143995283326808680518644927890182524580312777400009071739277407358043120199,
3038758768133404431511594054950351369492648883179154555267474054094234927849,
981824005865625678985009911415023115269386212492064371040001594972137748141,
2427990511715778580869565219059895697855813782250850855111162965998948386792,
],
[
1987498156785173719076522405088076990979859292718600184358583152317049836167,
1633834915134208237423144264187482951766302060112099587851513525797020813799,
2895454976388515752029424688351979030650325184941524820409482023485820781526,
941019661238578826272324221721825852217063629464317974190162904813488515671,
2529926057929249454763690180607677568685011502604470585585763159431333258299,
],
[
2604831509257756199338105380847564711923112853239827243306562341166492672823,
2300475954087415591738767759767032267163723345312082546282694920273655145455,
1954000528502201000509342111010021527425422549437946241062907964768089317082,
1179936151696782249912570883839105595634344582873818018332922940963046083567,
3077707030301573630126144767923697288658782137457660869231140049571827937228,
],
[
1062324397142900251844488719868780667589966366756786302007970554437994421840,
353718609497993885193404630053532608155520921625518104461520254335222009911,
770557645309607171206012551080400276506165720184677119001983749356594531977,
3043628430985247363392058521341757139056029350680498644930013342982472853636,
1694968537785457252742656255724723357998402478572600479401200420305593921487,
],
[
539865665379093791531434211889371819368504193082947002067781562776138072582,
3473466148775696692731190426971123680342615414200262605154732883324298196699,
482783534456196983135936103604928650836406142744767857356485953118411089098,
2389101033971236780034779577432189630800997581132154923233144722790749715251,
845264223568475649981141803833883014312596504303895519674002924871878791033,
],
[
3027004059915270231142566724881373969831662022738947178800901294120992473905,
2169574859350740480088697859610203373582027214052754592019828328614087431593,
3515527080764222354309565181793838292349410992793070639041305826153436624160,
1817926918350512904327755405973355211358017834277255662858654992240629698587,
1999148133619270973098477176176178514394558202995832714883251820350860287223,
],
[
1203131300029280096510929599113528018338088236684405405384757591977164161039,
336815403657101171302040383579077521911288747438919304948637997306314852594,
986661060847815533035934253464295060766339947679669645818832311132001095573,
2291116974939980228917916563988261327966840303336559854772343651559589512651,
3421243089992476528970346847858594146122972226790673723411896208702859892637,
],
[
1015505198663386486420800821559060487156096175034250154764824837183581949724,
1165880582987807286271819576391581724550686829511475839624601920297855380101,
904232961143172831178860280790910264843503022179578981166030973682571903458,
261322216292849827900157598748641385787016033372999683866859675894253115357,
3060676319159217735181388708455879854358158161989877552543698103915296690395,
],
[
1175560144527845912984609340783959238735643215413930887771084560168082442967,
2813871258576082360085006002528268796351819524936446195552260262614692343332,
1841341101531851399935829271555098629075809587212843292354556374386667658235,
3076135575511709688509914361447080149794919016880133063891720256749999834767,
753111801049754117414662684453226478940731922961768343984187479992842213733,
],
[
1405657437118503342762241742745888533114216548278983907019917904938403345580,
3111186124713876864436867307979940633543281080828379725576742174555539054855,
3404463650394703220454952017098727360005393139199301323890695570346564876407,
2024087816190101179456573591359233695334184711688920998987373624570170649371,
2770035625774572095496575568588054654502991645588385802705097377675051032967,
],
[
437058215235292632621847481185406671372191763951486300610124033096831557414,
1345792773780982398809956395232061067669190682958320579442454533085407626029,
925357273912625669941681596445839316566672314870287993638671283923476231904,
3288133122086768300615066039539687885053110015077924175836976549020438910830,
666190075990703867784232802074474372379358766701681865975596503982238839889,
],
[
2664898601165892062970298960258838238925231697327906221693001926762280012052,
2075648691532387787722427044464731934171216054855867223374228487601569118337,
3173725544188532489243684991828985285646224157242834030308807120745121062293,
1517474443612606408422643323550409253700128234157734252330869178582583531320,
1593950878945144789965609248470060076911813704207225832606804796819386297511,
],
[
141195541167651298813588829225208004611326987855926870823948793274702167509,
2990187949585642302497822222637786229364740008175968941859105979392907839776,
2893807105405820282316438050347503569385510241526138409321358916388308586443,
1379719211597875648759619903854862028510320482486109668868067715175935658353,
2702780364788282233075255946852944970202849869091427738791947810055591218061,
],
[
1825815734419326277729273926504439575157952821379179501821641713286627304656,
1481344458867016048625916723816339719872443766684158199301690902395849166360,
2014084774259125722186109781197998076881266739680534358898592778318128968629,
2612744185006548312909661512508122065214170543806989291921289897662387203493,
2486291022451231582267428921150634472835925206862678364689227838329114330247,
],
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,53 +0,0 @@
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import * as starknet from '../../lib/esm/stark.js';
import * as fc from 'fast-check';
const FC_BIGINT = fc.bigInt(1n + 1n, starknet.CURVE.n - 1n);
describe('starknet property', () => {
should('Point#toHex() roundtrip', () => {
fc.assert(
fc.property(FC_BIGINT, (x) => {
const point1 = starknet.ProjectivePoint.fromPrivateKey(x);
const hex = point1.toHex(true);
deepStrictEqual(starknet.ProjectivePoint.fromHex(hex).toHex(true), hex);
})
);
});
should('Signature.fromCompactHex() roundtrip', () => {
fc.assert(
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
const sig = new starknet.Signature(r, s);
deepStrictEqual(starknet.Signature.fromCompact(sig.toCompactHex()), sig);
})
);
});
should('Signature.fromDERHex() roundtrip', () => {
fc.assert(
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
const sig = new starknet.Signature(r, s);
deepStrictEqual(starknet.Signature.fromDER(sig.toDERHex()), sig);
})
);
});
should('verify()/should verify random signatures', () =>
fc.assert(
fc.property(FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), (privNum, msg) => {
const privKey = privNum.toString(16).padStart(64, '0');
const pub = starknet.getPublicKey(privKey);
const sig = starknet.sign(msg, privKey);
deepStrictEqual(starknet.verify(sig, msg, pub), true);
})
)
);
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

View File

@@ -1,288 +0,0 @@
import { deepStrictEqual, throws } from 'assert';
import { describe, should } from 'micro-should';
import { hex, utf8 } from '@scure/base';
import * as bip32 from '@scure/bip32';
import * as bip39 from '@scure/bip39';
import * as starknet from '../../lib/esm/stark.js';
import { default as sigVec } from './fixtures/rfc6979_signature_test_vector.json' assert { type: 'json' };
import { default as precomputedKeys } from './fixtures/keys_precomputed.json' assert { type: 'json' };
describe('starknet', () => {
should('custom keccak', () => {
const value = starknet.keccak(utf8.decode('hello'));
deepStrictEqual(value, 0x8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8n);
deepStrictEqual(value < 2n ** 250n, true);
});
should('RFC6979', () => {
for (const msg of sigVec.messages) {
const { r, s } = starknet.sign(msg.hash, sigVec.private_key);
// const { r, s } = starknet.Signature.fromDER(sig);
deepStrictEqual(r.toString(10), msg.r);
deepStrictEqual(s.toString(10), msg.s);
}
});
should('Signatures', () => {
const vectors = [
{
// Message hash of length 61.
msg: 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47',
r: '5f496f6f210b5810b2711c74c15c05244dad43d18ecbbdbe6ed55584bc3b0a2',
s: '4e8657b153787f741a67c0666bad6426c3741b478c8eaa3155196fc571416f3',
},
{
// Message hash of length 61, with leading zeros.
msg: '00c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47',
r: '5f496f6f210b5810b2711c74c15c05244dad43d18ecbbdbe6ed55584bc3b0a2',
s: '4e8657b153787f741a67c0666bad6426c3741b478c8eaa3155196fc571416f3',
},
{
// Message hash of length 62.
msg: 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47a',
r: '233b88c4578f0807b4a7480c8076eca5cfefa29980dd8e2af3c46a253490e9c',
s: '28b055e825bc507349edfb944740a35c6f22d377443c34742c04e0d82278cf1',
},
{
// Message hash of length 63.
msg: '7465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47a1',
r: 'b6bee8010f96a723f6de06b5fa06e820418712439c93850dd4e9bde43ddf',
s: '1a3d2bc954ed77e22986f507d68d18115fa543d1901f5b4620db98e2f6efd80',
},
];
const privateKey = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
const publicKey = starknet.getPublicKey(privateKey);
for (const v of vectors) {
const sig = starknet.sign(v.msg, privateKey);
const { r, s } = sig;
// const { r, s } = starknet.Signature.fromDER(sig);
deepStrictEqual(r.toString(16), v.r, 'r equality');
deepStrictEqual(s.toString(16), v.s, 's equality');
deepStrictEqual(starknet.verify(sig, v.msg, publicKey), true, 'verify');
}
});
should('Invalid signatures', () => {
/*
it('should not verify invalid signature inputs lengths', () => {
const ecOrder = starkwareCrypto.ec.n;
const {maxEcdsaVal} = starkwareCrypto;
const maxMsgHash = maxEcdsaVal.sub(oneBn);
const maxR = maxEcdsaVal.sub(oneBn);
const maxS = ecOrder.sub(oneBn).sub(oneBn);
const maxStarkKey = maxEcdsaVal.sub(oneBn);
// Test invalid message length.
expect(() =>
starkwareCrypto.verify(maxStarkKey, maxMsgHash.add(oneBn).toString(16), {
r: maxR,
s: maxS
})
).to.throw('Message not signable, invalid msgHash length.');
// Test invalid r length.
expect(() =>
starkwareCrypto.verify(maxStarkKey, maxMsgHash.toString(16), {
r: maxR.add(oneBn),
s: maxS
})
).to.throw('Message not signable, invalid r length.');
// Test invalid w length.
expect(() =>
starkwareCrypto.verify(maxStarkKey, maxMsgHash.toString(16), {
r: maxR,
s: maxS.add(oneBn)
})
).to.throw('Message not signable, invalid w length.');
// Test invalid s length.
expect(() =>
starkwareCrypto.verify(maxStarkKey, maxMsgHash.toString(16), {
r: maxR,
s: maxS.add(oneBn).add(oneBn)
})
).to.throw('Message not signable, invalid s length.');
});
it('should not verify invalid signatures', () => {
const privKey = generateRandomStarkPrivateKey();
const keyPair = starkwareCrypto.ec.keyFromPrivate(privKey, 'hex');
const keyPairPub = starkwareCrypto.ec.keyFromPublic(
keyPair.getPublic(),
'BN'
);
const msgHash = new BN(randomHexString(61));
const msgSignature = starkwareCrypto.sign(keyPair, msgHash);
// Test invalid public key.
const invalidKeyPairPub = starkwareCrypto.ec.keyFromPublic(
{x: keyPairPub.pub.getX().add(oneBn), y: keyPairPub.pub.getY()},
'BN'
);
expect(
starkwareCrypto.verify(
invalidKeyPairPub,
msgHash.toString(16),
msgSignature
)
).to.be.false;
// Test invalid message.
expect(
starkwareCrypto.verify(
keyPair,
msgHash.add(oneBn).toString(16),
msgSignature
)
).to.be.false;
expect(
starkwareCrypto.verify(
keyPairPub,
msgHash.add(oneBn).toString(16),
msgSignature
)
).to.be.false;
// Test invalid r.
msgSignature.r.iadd(oneBn);
expect(starkwareCrypto.verify(keyPair, msgHash.toString(16), msgSignature))
.to.be.false;
expect(
starkwareCrypto.verify(keyPairPub, msgHash.toString(16), msgSignature)
).to.be.false;
// Test invalid s.
msgSignature.r.isub(oneBn);
msgSignature.s.iadd(oneBn);
expect(starkwareCrypto.verify(keyPair, msgHash.toString(16), msgSignature))
.to.be.false;
expect(
starkwareCrypto.verify(keyPairPub, msgHash.toString(16), msgSignature)
).to.be.false;
});
});
*/
});
should('Pedersen', () => {
deepStrictEqual(
starknet.pedersen(
'0x3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
'0x208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a'
),
'0x30e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662'
);
deepStrictEqual(
starknet.pedersen(
'0x58f580910a6ca59b28927c08fe6c43e2e303ca384badc365795fc645d479d45',
'0x78734f65a067be9bdb39de18434d71e79f7b6466a4b66bbd979ab9e7515fe0b'
),
'0x68cc0b76cddd1dd4ed2301ada9b7c872b23875d5ff837b3a87993e0d9996b87'
);
});
should('Hash chain', () => {
deepStrictEqual(starknet.hashChain([1, 2, 3]), starknet.pedersen(1, starknet.pedersen(2, 3)));
});
should('Key grinding', () => {
deepStrictEqual(
starknet.grindKey('86F3E7293141F20A8BAFF320E8EE4ACCB9D4A4BF2B4D295E8CEE784DB46E0519'),
'5c8c8683596c732541a59e03007b2d30dbbbb873556fe65b5fb63c16688f941'
);
// Loops more than once (verified manually)
deepStrictEqual(
starknet.grindKey('94F3E7293141F20A8BAFF320E8EE4ACCB9D4A4BF2B4D295E8CEE784DB46E0595'),
'33880b9aba464c1c01c9f8f5b4fc1134698f9b0a8d18505cab6cdd34d93dc02'
);
});
should('Private to stark key', () => {
deepStrictEqual(
starknet.getStarkKey('0x178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F'),
'0x1895a6a77ae14e7987b9cb51329a5adfb17bd8e7c638f92d6892d76e51cebcf'
);
for (const [privKey, expectedPubKey] of Object.entries(precomputedKeys)) {
deepStrictEqual(starknet.getStarkKey(privKey), expectedPubKey);
}
});
should('Private stark key from eth signature', () => {
const ethSignature =
'0x21fbf0696d5e0aa2ef41a2b4ffb623bcaf070461d61cf7251c74161f82fec3a43' +
'70854bc0a34b3ab487c1bc021cd318c734c51ae29374f2beb0e6f2dd49b4bf41c';
deepStrictEqual(
starknet.ethSigToPrivate(ethSignature),
'766f11e90cd7c7b43085b56da35c781f8c067ac0d578eabdceebc4886435bda'
);
});
should('Key derivation', () => {
const layer = 'starkex';
const application = 'starkdeployement';
const mnemonic =
'range mountain blast problem vibrant void vivid doctor cluster enough melody ' +
'salt layer language laptop boat major space monkey unit glimpse pause change vibrant';
const ethAddress = '0xa4864d977b944315389d1765ffa7e66F74ee8cd7';
const VECTORS = [
{
index: 0,
path: "m/2645'/579218131'/891216374'/1961790679'/2135936222'/0",
privateKey: '6cf0a8bf113352eb863157a45c5e5567abb34f8d32cddafd2c22aa803f4892c',
},
{
index: 7,
path: "m/2645'/579218131'/891216374'/1961790679'/2135936222'/7",
privateKey: '341751bdc42841da35ab74d13a1372c1f0250617e8a2ef96034d9f46e6847af',
},
{
index: 598,
path: "m/2645'/579218131'/891216374'/1961790679'/2135936222'/598",
privateKey: '41a4d591a868353d28b7947eb132aa4d00c4a022743689ffd20a3628d6ca28c',
},
];
const hd = bip32.HDKey.fromMasterSeed(bip39.mnemonicToSeedSync(mnemonic));
for (const { index, path, privateKey } of VECTORS) {
const realPath = starknet.getAccountPath(layer, application, ethAddress, index);
deepStrictEqual(realPath, path);
deepStrictEqual(starknet.grindKey(hd.derive(realPath).privateKey), privateKey);
}
});
// Verified against starknet.js
should('Starknet.js cross-tests', () => {
const privateKey = '0x019800ea6a9a73f94aee6a3d2edf018fc770443e90c7ba121e8303ec6b349279';
// NOTE: there is no compressed keys here, getPubKey returns stark-key (which is schnorr-like X coordinate)
// But it is not used in signing/verifying
deepStrictEqual(
starknet.getStarkKey(privateKey),
'0x33f45f07e1bd1a51b45fc24ec8c8c9908db9e42191be9e169bfcac0c0d99745'
);
const msgHash = '0x6d1706bd3d1ba7c517be2a2a335996f63d4738e2f182144d078a1dd9997062e';
const sig = starknet.sign(msgHash, privateKey);
const { r, s } = sig;
deepStrictEqual(
r.toString(),
'1427981024487605678086498726488552139932400435436186597196374630267616399345'
);
deepStrictEqual(
s.toString(),
'1853664302719670721837677288395394946745467311923401353018029119631574115563'
);
const hashMsg2 = starknet.pedersen(
'0x33f45f07e1bd1a51b45fc24ec8c8c9908db9e42191be9e169bfcac0c0d99745',
'1'
);
deepStrictEqual(hashMsg2, '0x2b0d4d43acce8ff68416f667f92ec7eab2b96f1d2224abd4d9d4d1e7fa4bb00');
const pubKey =
'04033f45f07e1bd1a51b45fc24ec8c8c9908db9e42191be9e169bfcac0c0d997450319d0f53f6ca077c4fa5207819144a2a4165daef6ee47a7c1d06c0dcaa3e456';
const sig2 = new starknet.Signature(
558858382392827003930138586379728730695763862039474863361948210004201119180n,
2440689354481625417078677634625227600823892606910345662891037256374285369343n
);
deepStrictEqual(starknet.verify(sig2.toDERHex(), hashMsg2, pubKey), true);
});
});
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,72 +1,107 @@
[
{
"message": "test data",
"d": "fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e",
"k0": "fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e",
"k1": "727fbcb59eb48b1d7d46f95a04991fc512eb9dbf9105628e3aec87428df28fd8",
"k15": "398f0e2c9f79728f7b3d84d447ac3a86d8b2083c8f234a0ffa9c4043d68bd258"
"curve": "P192",
"q": "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
"private": "6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4",
"Ux": "AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56",
"Uy": "3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43",
"cases": [
{
"k": "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496",
"message": "sample",
"r": "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55",
"s": "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85"
},
{
"message": "Everything should be made as simple as possible, but not simpler.",
"d": "0000000000000000000000000000000000000000000000000000000000000001",
"k0": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
"k1": "df55b6d1b5c48184622b0ead41a0e02bfa5ac3ebdb4c34701454e80aabf36f56",
"k15": "def007a9a3c2f7c769c75da9d47f2af84075af95cadd1407393dc1e26086ef87"
},
{
"message": "Satoshi Nakamoto",
"d": "0000000000000000000000000000000000000000000000000000000000000002",
"k0": "d3edc1b8224e953f6ee05c8bbf7ae228f461030e47caf97cde91430b4607405e",
"k1": "f86d8e43c09a6a83953f0ab6d0af59fb7446b4660119902e9967067596b58374",
"k15": "241d1f57d6cfd2f73b1ada7907b199951f95ef5ad362b13aed84009656e0254a"
},
{
"message": "Diffie Hellman",
"d": "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
"k0": "c378a41cb17dce12340788dd3503635f54f894c306d52f6e9bc4b8f18d27afcc",
"k1": "90756c96fef41152ac9abe08819c4e95f16da2af472880192c69a2b7bac29114",
"k15": "7b3f53300ab0ccd0f698f4d67db87c44cf3e9e513d9df61137256652b2e94e7c"
},
{
"message": "Japan",
"d": "8080808080808080808080808080808080808080808080808080808080808080",
"k0": "f471e61b51d2d8db78f3dae19d973616f57cdc54caaa81c269394b8c34edcf59",
"k1": "6819d85b9730acc876fdf59e162bf309e9f63dd35550edf20869d23c2f3e6d17",
"k15": "d8e8bae3ee330a198d1f5e00ad7c5f9ed7c24c357c0a004322abca5d9cd17847"
},
{
"message": "Bitcoin",
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k0": "36c848ffb2cbecc5422c33a994955b807665317c1ce2a0f59c689321aaa631cc",
"k1": "4ed8de1ec952a4f5b3bd79d1ff96446bcd45cabb00fc6ca127183e14671bcb85",
"k15": "56b6f47babc1662c011d3b1f93aa51a6e9b5f6512e9f2e16821a238d450a31f8"
},
{
"message": "i2FLPP8WEus5WPjpoHwheXOMSobUJVaZM1JPMQZq",
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k0": "6e9b434fcc6bbb081a0463c094356b47d62d7efae7da9c518ed7bac23f4e2ed6",
"k1": "ae5323ae338d6117ce8520a43b92eacd2ea1312ae514d53d8e34010154c593bb",
"k15": "3eaa1b61d1b8ab2f1ca71219c399f2b8b3defa624719f1e96fe3957628c2c4ea"
},
{
"message": "lEE55EJNP7aLrMtjkeJKKux4Yg0E8E1SAJnWTCEh",
"d": "3881e5286abc580bb6139fe8e83d7c8271c6fe5e5c2d640c1f0ed0e1ee37edc9",
"k0": "5b606665a16da29cc1c5411d744ab554640479dd8abd3c04ff23bd6b302e7034",
"k1": "f8b25263152c042807c992eacd2ac2cc5790d1e9957c394f77ea368e3d9923bd",
"k15": "ea624578f7e7964ac1d84adb5b5087dd14f0ee78b49072aa19051cc15dab6f33"
},
{
"message": "2SaVPvhxkAPrayIVKcsoQO5DKA8Uv5X/esZFlf+y",
"d": "7259dff07922de7f9c4c5720d68c9745e230b32508c497dd24cb95ef18856631",
"k0": "3ab6c19ab5d3aea6aa0c6da37516b1d6e28e3985019b3adb388714e8f536686b",
"k1": "19af21b05004b0ce9cdca82458a371a9d2cf0dc35a813108c557b551c08eb52e",
"k15": "117a32665fca1b7137a91c4739ac5719fec0cf2e146f40f8e7c21b45a07ebc6a"
},
{
"message": "00A0OwO2THi7j5Z/jp0FmN6nn7N/DQd6eBnCS+/b",
"d": "0d6ea45d62b334777d6995052965c795a4f8506044b4fd7dc59c15656a28f7aa",
"k0": "79487de0c8799158294d94c0eb92ee4b567e4dc7ca18addc86e49d31ce1d2db6",
"k1": "9561d2401164a48a8f600882753b3105ebdd35e2358f4f808c4f549c91490009",
"k15": "b0d273634129ff4dbdf0df317d4062a1dbc58818f88878ffdb4ec511c77976c0"
"k": "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C",
"message": "test",
"r": "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE",
"s": "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F"
}
]
},
{
"curve": "P224",
"q": "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
"private": "F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1",
"Ux": "00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C",
"Uy": "EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A",
"cases": [
{
"k": "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D",
"message": "sample",
"r": "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E",
"s": "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC"
},
{
"k": "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524",
"message": "test",
"r": "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019",
"s": "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4"
}
]
},
{
"curve": "P256",
"q": "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
"private": "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721",
"Ux": "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6",
"Uy": "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299",
"cases": [
{
"k": "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60",
"message": "sample",
"r": "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716",
"s": "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
},
{
"k": "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0",
"message": "test",
"r": "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367",
"s": "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083"
}
]
},
{
"curve": "P384",
"q": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
"private": "6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5",
"Ux": "EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13",
"Uy": "8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720",
"cases": [
{
"k": "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9",
"message": "sample",
"r": "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46",
"s": "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8"
},
{
"k": "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA",
"message": "test",
"r": "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB",
"s": "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5"
}
]
},
{
"curve": "P521",
"q": "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
"private": "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
"Ux": "1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4",
"Uy": "0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5",
"cases": [
{
"k": "1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3",
"message": "sample",
"r": "0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA",
"s": "0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A"
},
{
"k": "16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D",
"message": "test",
"r": "13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D",
"s": "1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3"
}
]
}
]

View File

@@ -0,0 +1,26 @@
[
{
"desc": "k1neg=true, k2neg=false",
"ax": "55066263022277343669578718895168534326250603453777594175500187360389116729240",
"ay": "32670510020758816978083085130507043184471273380659243275938904335757337482424",
"scalar": "2704427838213584814824020837927043695889",
"cx": "70912011419250646761259860556624974262679413898110209707622032756145750038852",
"cy": "46481114889376149700487001434152190585794282401306514438088690968308506923285"
},
{
"desc": "k1neg=false, k2neg=true",
"ax": "55066263022277343669578718895168534326250603453777594175500187360389116729240",
"ay": "32670510020758816978083085130507043184471273380659243275938904335757337482424",
"scalar": "367917413016453100223835821029139468248",
"cx": "10322688129782350538653828383726187034025074756440739323015371090593152139135",
"cy": "68793242610611269092604721689053086352541804982835045879816374698216278704126"
},
{
"desc": "k1neg=true, k2neg=true",
"ax": "55066263022277343669578718895168534326250603453777594175500187360389116729240",
"ay": "32670510020758816978083085130507043184471273380659243275938904335757337482424",
"scalar": "3808180077262944115495528301014462100633",
"cx": "14215418389480067884450074673878587420586762919133643262861030012154939932102",
"cy": "29847359538023735520768762420255189621104408153695873716448888266404867737302"
}
]

View File

@@ -0,0 +1,72 @@
[
{
"message": "test data",
"d": "fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e",
"k0": "fcce1de7a9bcd6b2d3defade6afa1913fb9229e3b7ddf4749b55c4848b2a196e",
"k1": "727fbcb59eb48b1d7d46f95a04991fc512eb9dbf9105628e3aec87428df28fd8",
"k15": "398f0e2c9f79728f7b3d84d447ac3a86d8b2083c8f234a0ffa9c4043d68bd258"
},
{
"message": "Everything should be made as simple as possible, but not simpler.",
"d": "0000000000000000000000000000000000000000000000000000000000000001",
"k0": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
"k1": "df55b6d1b5c48184622b0ead41a0e02bfa5ac3ebdb4c34701454e80aabf36f56",
"k15": "def007a9a3c2f7c769c75da9d47f2af84075af95cadd1407393dc1e26086ef87"
},
{
"message": "Satoshi Nakamoto",
"d": "0000000000000000000000000000000000000000000000000000000000000002",
"k0": "d3edc1b8224e953f6ee05c8bbf7ae228f461030e47caf97cde91430b4607405e",
"k1": "f86d8e43c09a6a83953f0ab6d0af59fb7446b4660119902e9967067596b58374",
"k15": "241d1f57d6cfd2f73b1ada7907b199951f95ef5ad362b13aed84009656e0254a"
},
{
"message": "Diffie Hellman",
"d": "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
"k0": "c378a41cb17dce12340788dd3503635f54f894c306d52f6e9bc4b8f18d27afcc",
"k1": "90756c96fef41152ac9abe08819c4e95f16da2af472880192c69a2b7bac29114",
"k15": "7b3f53300ab0ccd0f698f4d67db87c44cf3e9e513d9df61137256652b2e94e7c"
},
{
"message": "Japan",
"d": "8080808080808080808080808080808080808080808080808080808080808080",
"k0": "f471e61b51d2d8db78f3dae19d973616f57cdc54caaa81c269394b8c34edcf59",
"k1": "6819d85b9730acc876fdf59e162bf309e9f63dd35550edf20869d23c2f3e6d17",
"k15": "d8e8bae3ee330a198d1f5e00ad7c5f9ed7c24c357c0a004322abca5d9cd17847"
},
{
"message": "Bitcoin",
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k0": "36c848ffb2cbecc5422c33a994955b807665317c1ce2a0f59c689321aaa631cc",
"k1": "4ed8de1ec952a4f5b3bd79d1ff96446bcd45cabb00fc6ca127183e14671bcb85",
"k15": "56b6f47babc1662c011d3b1f93aa51a6e9b5f6512e9f2e16821a238d450a31f8"
},
{
"message": "i2FLPP8WEus5WPjpoHwheXOMSobUJVaZM1JPMQZq",
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k0": "6e9b434fcc6bbb081a0463c094356b47d62d7efae7da9c518ed7bac23f4e2ed6",
"k1": "ae5323ae338d6117ce8520a43b92eacd2ea1312ae514d53d8e34010154c593bb",
"k15": "3eaa1b61d1b8ab2f1ca71219c399f2b8b3defa624719f1e96fe3957628c2c4ea"
},
{
"message": "lEE55EJNP7aLrMtjkeJKKux4Yg0E8E1SAJnWTCEh",
"d": "3881e5286abc580bb6139fe8e83d7c8271c6fe5e5c2d640c1f0ed0e1ee37edc9",
"k0": "5b606665a16da29cc1c5411d744ab554640479dd8abd3c04ff23bd6b302e7034",
"k1": "f8b25263152c042807c992eacd2ac2cc5790d1e9957c394f77ea368e3d9923bd",
"k15": "ea624578f7e7964ac1d84adb5b5087dd14f0ee78b49072aa19051cc15dab6f33"
},
{
"message": "2SaVPvhxkAPrayIVKcsoQO5DKA8Uv5X/esZFlf+y",
"d": "7259dff07922de7f9c4c5720d68c9745e230b32508c497dd24cb95ef18856631",
"k0": "3ab6c19ab5d3aea6aa0c6da37516b1d6e28e3985019b3adb388714e8f536686b",
"k1": "19af21b05004b0ce9cdca82458a371a9d2cf0dc35a813108c557b551c08eb52e",
"k15": "117a32665fca1b7137a91c4739ac5719fec0cf2e146f40f8e7c21b45a07ebc6a"
},
{
"message": "00A0OwO2THi7j5Z/jp0FmN6nn7N/DQd6eBnCS+/b",
"d": "0d6ea45d62b334777d6995052965c795a4f8506044b4fd7dc59c15656a28f7aa",
"k0": "79487de0c8799158294d94c0eb92ee4b567e4dc7ca18addc86e49d31ce1d2db6",
"k1": "9561d2401164a48a8f600882753b3105ebdd35e2358f4f808c4f549c91490009",
"k15": "b0d273634129ff4dbdf0df317d4062a1dbc58818f88878ffdb4ec511c77976c0"
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,434 @@
{
"algorithm" : "EcCurveTest",
"schema" : "ec_curve_test_schema.json",
"generatorVersion" : "0.9rc5",
"numberOfTests" : 26,
"header" : [
"Test vectors of type EcCurveTest are for checking curve parameters."
],
"notes" : {
},
"testGroups" : [
{
"type" : "EcCurveTest",
"tests" : [
{
"tcId" : 1,
"comment" : "",
"flags" : [],
"name" : "secp224r1",
"oid" : "1.3.132.0.33",
"ref" : "ANSI X9.62",
"p" : "00ffffffffffffffffffffffffffffffff000000000000000000000001",
"n" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d",
"a" : "00fffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
"b" : "00b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
"gx" : "00b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
"gy" : "00bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 2,
"comment" : "",
"flags" : [],
"name" : "secp256r1",
"oid" : "1.2.840.10045.3.1.7",
"ref" : "ANSI X9.62",
"p" : "00ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
"n" : "00ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
"a" : "00ffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
"b" : "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
"gx" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"gy" : "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 3,
"comment" : "",
"flags" : [],
"name" : "secp384r1",
"oid" : "1.3.132.0.34",
"ref" : "ANSI X9.62",
"p" : "00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
"n" : "00ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
"a" : "00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc",
"b" : "00b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef",
"gx" : "00aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
"gy" : "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 4,
"comment" : "",
"flags" : [],
"name" : "secp521r1",
"oid" : "1.3.132.0.35",
"ref" : "ANSI X9.62",
"p" : "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"n" : "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
"a" : "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
"b" : "51953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
"gx" : "00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"gy" : "011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 5,
"comment" : "",
"flags" : [],
"name" : "secp256k1",
"oid" : "1.3.132.0.10",
"ref" : "https://www.secg.org/sec2-v2.pdf",
"p" : "00fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
"n" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"a" : "00",
"b" : "07",
"gx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"gy" : "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 6,
"comment" : "",
"flags" : [],
"name" : "secp224k1",
"oid" : "1.3.132.0.32",
"ref" : "ANSI X9.62",
"p" : "00fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d",
"n" : "010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7",
"a" : "00",
"b" : "05",
"gx" : "00a1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c",
"gy" : "7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 7,
"comment" : "",
"flags" : [],
"name" : "brainpoolP224r1",
"oid" : "1.3.36.3.3.2.8.1.1.5",
"ref" : "RFC 5639",
"p" : "00d7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
"n" : "00d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
"a" : "68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
"b" : "2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
"gx" : "0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
"gy" : "58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 8,
"comment" : "",
"flags" : [],
"name" : "brainpoolP256r1",
"oid" : "1.3.36.3.3.2.8.1.1.7",
"ref" : "RFC 5639",
"p" : "00a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
"n" : "00a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
"a" : "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
"b" : "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
"gx" : "008bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
"gy" : "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 9,
"comment" : "",
"flags" : [],
"name" : "brainpoolP320r1",
"oid" : "1.3.36.3.3.2.8.1.1.9",
"ref" : "RFC 5639",
"p" : "00d35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28fcd412b1f1b32e27",
"n" : "00d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59311",
"a" : "3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f492f375a97d860eb4",
"b" : "520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd884539816f5eb4ac8fb1f1a6",
"gx" : "43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c710af8d0d39e20611",
"gy" : "14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7d35245d1692e8ee1",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 10,
"comment" : "",
"flags" : [],
"name" : "brainpoolP384r1",
"oid" : "1.3.36.3.3.2.8.1.1.11",
"ref" : "RFC 5639",
"p" : "008cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53",
"n" : "008cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046565",
"a" : "7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd22ce2826",
"b" : "04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696fa504c11",
"gx" : "1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e247d4af1e",
"gy" : "008abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341263c5315",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 11,
"comment" : "",
"flags" : [],
"name" : "brainpoolP512r1",
"oid" : "1.3.36.3.3.2.8.1.1.13",
"ref" : "RFC 5639",
"p" : "00aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
"n" : "00aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
"a" : "7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
"b" : "3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
"gx" : "0081aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098eff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
"gy" : "7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 12,
"comment" : "",
"flags" : [],
"name" : "brainpoolP224t1",
"oid" : "1.3.36.3.3.2.8.1.1.6",
"ref" : "RFC 5639",
"p" : "00d7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
"n" : "00d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
"a" : "00d7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0fc",
"b" : "4b337d934104cd7bef271bf60ced1ed20da14c08b3bb64f18a60888d",
"gx" : "6ab1e344ce25ff3896424e7ffe14762ecb49f8928ac0c76029b4d580",
"gy" : "0374e9f5143e568cd23f3f4d7c0d4b1e41c8cc0d1c6abd5f1a46db4c",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 13,
"comment" : "",
"flags" : [],
"name" : "brainpoolP256t1",
"oid" : "1.3.36.3.3.2.8.1.1.8",
"ref" : "RFC 5639",
"p" : "00a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
"n" : "00a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
"a" : "00a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5374",
"b" : "662c61c430d84ea4fe66a7733d0b76b7bf93ebc4af2f49256ae58101fee92b04",
"gx" : "00a3e8eb3cc1cfe7b7732213b23a656149afa142c47aafbc2b79a191562e1305f4",
"gy" : "2d996c823439c56d7f7b22e14644417e69bcb6de39d027001dabe8f35b25c9be",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 14,
"comment" : "",
"flags" : [],
"name" : "brainpoolP320t1",
"oid" : "1.3.36.3.3.2.8.1.1.10",
"ref" : "RFC 5639",
"p" : "00d35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28fcd412b1f1b32e27",
"n" : "00d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59311",
"a" : "00d35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28fcd412b1f1b32e24",
"b" : "00a7f561e038eb1ed560b3d147db782013064c19f27ed27c6780aaf77fb8a547ceb5b4fef422340353",
"gx" : "00925be9fb01afc6fb4d3e7d4990010f813408ab106c4f09cb7ee07868cc136fff3357f624a21bed52",
"gy" : "63ba3a7a27483ebf6671dbef7abb30ebee084e58a0b077ad42a5a0989d1ee71b1b9bc0455fb0d2c3",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 15,
"comment" : "",
"flags" : [],
"name" : "brainpoolP384t1",
"oid" : "1.3.36.3.3.2.8.1.1.12",
"ref" : "RFC 5639",
"p" : "008cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53",
"n" : "008cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046565",
"a" : "008cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec50",
"b" : "7f519eada7bda81bd826dba647910f8c4b9346ed8ccdc64e4b1abd11756dce1d2074aa263b88805ced70355a33b471ee",
"gx" : "18de98b02db9a306f2afcd7235f72a819b80ab12ebd653172476fecd462aabffc4ff191b946a5f54d8d0aa2f418808cc",
"gy" : "25ab056962d30651a114afd2755ad336747f93475b7a1fca3b88f2b6a208ccfe469408584dc2b2912675bf5b9e582928",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 16,
"comment" : "",
"flags" : [],
"name" : "brainpoolP512t1",
"oid" : "1.3.36.3.3.2.8.1.1.14",
"ref" : "RFC 5639",
"p" : "00aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
"n" : "00aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
"a" : "00aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f0",
"b" : "7cbbbcf9441cfab76e1890e46884eae321f70c0bcb4981527897504bec3e36a62bcdfa2304976540f6450085f2dae145c22553b465763689180ea2571867423e",
"gx" : "640ece5c12788717b9c1ba06cbc2a6feba85842458c56dde9db1758d39c0313d82ba51735cdb3ea499aa77a7d6943a64f7a3f25fe26f06b51baa2696fa9035da",
"gy" : "5b534bd595f5af0fa2c892376c84ace1bb4e3019b71634c01131159cae03cee9d9932184beef216bd71df2dadf86a627306ecff96dbb8bace198b61e00f8b332",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 17,
"comment" : "",
"flags" : [],
"name" : "FRP256v1",
"oid" : "1.2.250.1.223.101.256.1",
"ref" : "https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000024668816",
"p" : "00f1fd178c0b3ad58f10126de8ce42435b3961adbcabc8ca6de8fcf353d86e9c03",
"n" : "00f1fd178c0b3ad58f10126de8ce42435b53dc67e140d2bf941ffdd459c6d655e1",
"a" : "00f1fd178c0b3ad58f10126de8ce42435b3961adbcabc8ca6de8fcf353d86e9c00",
"b" : "00ee353fca5428a9300d4aba754a44c00fdfec0c9ae4b1a1803075ed967b7bb73f",
"gx" : "00b6b3d4c356c139eb31183d4749d423958c27d2dcaf98b70164c97a2dd98f5cff",
"gy" : "6142e0f7c8b204911f9271f0f3ecef8c2701c307e8e4c9e183115a1554062cfb",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 18,
"comment" : "",
"flags" : [],
"name" : "secp192k1",
"oid" : "1.3.132.0.31",
"ref" : "ANSI X9.62",
"p" : "00fffffffffffffffffffffffffffffffffffffffeffffee37",
"n" : "00fffffffffffffffffffffffe26f2fc170f69466a74defd8d",
"a" : "00",
"b" : "03",
"gx" : "00db4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d",
"gy" : "009b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 19,
"comment" : "",
"flags" : [],
"name" : "secp192r1",
"oid" : "1.2.840.10045.3.1.1",
"ref" : "ANSI X9.62",
"p" : "00fffffffffffffffffffffffffffffffeffffffffffffffff",
"n" : "00ffffffffffffffffffffffff99def836146bc9b1b4d22831",
"a" : "00fffffffffffffffffffffffffffffffefffffffffffffffc",
"b" : "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
"gx" : "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
"gy" : "07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 20,
"comment" : "",
"flags" : [],
"name" : "secp160k1",
"oid" : "1.3.132.0.9",
"ref" : "https://www.secg.org/SEC2-Ver-1.0.pdf",
"p" : "00fffffffffffffffffffffffffffffffeffffac73",
"n" : "0100000000000000000001b8fa16dfab9aca16b6b3",
"a" : "00",
"b" : "07",
"gx" : "3b4c382ce37aa192a4019e763036f4f5dd4d7ebb",
"gy" : "00938cf935318fdced6bc28286531733c3f03c4fee",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 21,
"comment" : "",
"flags" : [],
"name" : "secp160r1",
"oid" : "1.3.132.0.8",
"ref" : "https://www.secg.org/SEC2-Ver-1.0.pdf",
"p" : "00ffffffffffffffffffffffffffffffff7fffffff",
"n" : "0100000000000000000001f4c8f927aed3ca752257",
"a" : "00ffffffffffffffffffffffffffffffff7ffffffc",
"b" : "1c97befc54bd7a8b65acf89f81d4d4adc565fa45",
"gx" : "4a96b5688ef573284664698968c38bb913cbfc82",
"gy" : "23a628553168947d59dcc912042351377ac5fb32",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 22,
"comment" : "",
"flags" : [],
"name" : "secp160r2",
"oid" : "1.3.132.0.30",
"ref" : "https://www.secg.org/SEC2-Ver-1.0.pdf",
"p" : "00fffffffffffffffffffffffffffffffeffffac73",
"n" : "0100000000000000000000351ee786a818f3a1a16b",
"a" : "00fffffffffffffffffffffffffffffffeffffac70",
"b" : "00b4e134d3fb59eb8bab57274904664d5af50388ba",
"gx" : "52dcb034293a117e1f4ff11b30f7199d3144ce6d",
"gy" : "00feaffef2e331f296e071fa0df9982cfea7d43f2e",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 23,
"comment" : "",
"flags" : [],
"name" : "brainpoolP160r1",
"oid" : "1.3.36.3.3.2.8.1.1.1",
"ref" : "RFC 5639",
"p" : "00e95e4a5f737059dc60dfc7ad95b3d8139515620f",
"n" : "00e95e4a5f737059dc60df5991d45029409e60fc09",
"a" : "340e7be2a280eb74e2be61bada745d97e8f7c300",
"b" : "1e589a8595423412134faa2dbdec95c8d8675e58",
"gx" : "00bed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
"gy" : "1667cb477a1a8ec338f94741669c976316da6321",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 24,
"comment" : "",
"flags" : [],
"name" : "brainpoolP160t1",
"oid" : "1.3.36.3.3.2.8.1.1.2",
"ref" : "RFC 5639",
"p" : "00e95e4a5f737059dc60dfc7ad95b3d8139515620f",
"n" : "00e95e4a5f737059dc60df5991d45029409e60fc09",
"a" : "00e95e4a5f737059dc60dfc7ad95b3d8139515620c",
"b" : "7a556b6dae535b7b51ed2c4d7daa7a0b5c55f380",
"gx" : "00b199b13b9b34efc1397e64baeb05acc265ff2378",
"gy" : "00add6718b7c7c1961f0991b842443772152c9e0ad",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 25,
"comment" : "",
"flags" : [],
"name" : "brainpoolP192r1",
"oid" : "1.3.36.3.3.2.8.1.1.3",
"ref" : "RFC 5639",
"p" : "00c302f41d932a36cda7a3463093d18db78fce476de1a86297",
"n" : "00c302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
"a" : "6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
"b" : "469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
"gx" : "00c0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
"gy" : "14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
"h" : 1,
"result" : "valid"
},
{
"tcId" : 26,
"comment" : "",
"flags" : [],
"name" : "brainpoolP192t1",
"oid" : "1.3.36.3.3.2.8.1.1.4",
"ref" : "RFC 5639",
"p" : "00c302f41d932a36cda7a3463093d18db78fce476de1a86297",
"n" : "00c302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
"a" : "00c302f41d932a36cda7a3463093d18db78fce476de1a86294",
"b" : "13d56ffaec78681e68f9deb43b35bec2fb68542e27897b79",
"gx" : "3ae9e58c82f63c30282e1fe7bbf43fa72c446af6f4618129",
"gy" : "097e2c5667c2223a902ab5ca449d0084b7e5b3de7ccc01c9",
"h" : 1,
"result" : "valid"
}
]
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More