forked from tornado-packages/noble-curves
Initial commit
This commit is contained in:
commit
a20a357225
2
.github/funding.yml
vendored
Normal file
2
.github/funding.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github: paulmillr
|
||||||
|
# custom: https://paulmillr.com/funding/
|
18
.github/workflows/nodejs.yml
vendored
Normal file
18
.github/workflows/nodejs.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: Node CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: v18 @ ubuntu-latest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Use Node.js ${{ matrix.node }}
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run build --if-present
|
||||||
|
- run: cd curve-definitions; npm install; npm run build --if-present
|
||||||
|
- run: npm test
|
||||||
|
- run: npm run lint --if-present
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
build/
|
||||||
|
node_modules/
|
||||||
|
coverage/
|
||||||
|
/lib/**/*.js
|
||||||
|
/lib/**/*.ts
|
||||||
|
/lib/**/*.d.ts.map
|
||||||
|
/curve-definitions/lib
|
4
.prettierrc.json
Normal file
4
.prettierrc.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the “Software”), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
71
README.md
Normal file
71
README.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# noble-curves
|
||||||
|
|
||||||
|
Minimal, zero-dependency JS implementation of elliptic curve cryptography.
|
||||||
|
|
||||||
|
Implements Short Weierstrass curves with ECDSA signature scheme.
|
||||||
|
|
||||||
|
To keep the package minimal, no curve definitions are provided out-of-box.
|
||||||
|
Main reason for that is the fact hashing library is usually required for full functionality. Use separate package that defines popular curves: `micro-curve-definitions` for P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) - it depends on `@noble/hashes`.
|
||||||
|
|
||||||
|
Future plans:
|
||||||
|
|
||||||
|
- Edwards, Twisted Edwards & Montgomery curves
|
||||||
|
- hash-to-curve standard
|
||||||
|
- pairings
|
||||||
|
|
||||||
|
### This library belongs to _noble_ crypto
|
||||||
|
|
||||||
|
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
||||||
|
|
||||||
|
- No dependencies, small files
|
||||||
|
- Easily auditable TypeScript/JS code
|
||||||
|
- Supported in all major browsers and stable node.js versions
|
||||||
|
- All releases are signed with PGP keys
|
||||||
|
- Check out [homepage](https://paulmillr.com/noble/) & all libraries:
|
||||||
|
[secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
||||||
|
[ed25519](https://github.com/paulmillr/noble-ed25519),
|
||||||
|
[bls12-381](https://github.com/paulmillr/noble-bls12-381),
|
||||||
|
[hashes](https://github.com/paulmillr/noble-hashes),
|
||||||
|
[curves](https://github.com/paulmillr/noble-curves)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Use NPM in node.js / browser, or include single file from
|
||||||
|
[GitHub's releases page](https://github.com/paulmillr/noble-curves/releases):
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install @noble/curves
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Short Weierstrass curve
|
||||||
|
import shortw from '@noble/curves/shortw';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
|
|
||||||
|
export const secp256k1 = shortw({
|
||||||
|
a: 0n,
|
||||||
|
b: 7n,
|
||||||
|
// Field over which we'll do calculations
|
||||||
|
P: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
|
||||||
|
// Curve order, total count of valid points in the field
|
||||||
|
n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
||||||
|
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
||||||
|
hash: sha256,
|
||||||
|
hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
|
||||||
|
randomBytes: randomBytes
|
||||||
|
});
|
||||||
|
|
||||||
|
// secp256k1.getPublicKey(priv)
|
||||||
|
// secp256k1.sign(msg, priv)
|
||||||
|
// secp256k1.verify(sig, msg, pub)
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.
|
21
curve-definitions/LICENSE
Normal file
21
curve-definitions/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the “Software”), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
28
curve-definitions/README.md
Normal file
28
curve-definitions/README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# micro-curve-definitions
|
||||||
|
|
||||||
|
Elliptic curves implementations. `@noble/curves` is zero-dependency library for internal arithmetics.
|
||||||
|
|
||||||
|
`micro-curve-definitions` is the actual implementations. Current functionality:
|
||||||
|
|
||||||
|
- NIST curves: P192, P224, P256, P384, P521 (ECDSA)
|
||||||
|
- secp256k1 (ECDSA, without Schnorr)
|
||||||
|
- stark curve
|
||||||
|
- bn254
|
||||||
|
|
||||||
|
Pairings are not implemented.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install micro-curve-definitions
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import * as nist from 'micro-curve-definitions';
|
||||||
|
|
||||||
|
// P192, P224, P256, P384, P521, bn254
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.
|
62
curve-definitions/package.json
Normal file
62
curve-definitions/package.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"name": "micro-curve-definitions",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Curve definitions for @noble/curves",
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"index.d.ts",
|
||||||
|
"index.d.ts.map",
|
||||||
|
"index.ts"
|
||||||
|
],
|
||||||
|
"type": "module",
|
||||||
|
"main": "index.js",
|
||||||
|
"module": "index.js",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/curves": "file:../",
|
||||||
|
"@noble/hashes": "1.1.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@scure/base": "~1.1.0",
|
||||||
|
"@scure/bip32": "^1.1.1",
|
||||||
|
"@scure/bip39": "^1.1.0",
|
||||||
|
"@types/node": "^18.11.3",
|
||||||
|
"fast-check": "3.0.0",
|
||||||
|
"micro-should": "0.2.0",
|
||||||
|
"prettier": "2.6.2",
|
||||||
|
"typescript": "4.7.3"
|
||||||
|
},
|
||||||
|
"author": "Paul Miller (https://paulmillr.com)",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/paulmillr/noble-curves",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/paulmillr/noble-curves.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"lint": "prettier --check index.ts",
|
||||||
|
"test": "node test/index.test.js"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"secp192r1",
|
||||||
|
"secp224r1",
|
||||||
|
"secp256r1",
|
||||||
|
"secp384r1",
|
||||||
|
"secp521r1",
|
||||||
|
"NIST P192",
|
||||||
|
"NIST P224",
|
||||||
|
"NIST P256",
|
||||||
|
"NIST P384",
|
||||||
|
"NIST P521",
|
||||||
|
"NIST curves",
|
||||||
|
"EC",
|
||||||
|
"elliptic curves"
|
||||||
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
25
curve-definitions/src/bn.ts
Normal file
25
curve-definitions/src/bn.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
import { weierstrass, CHash } from '@noble/curves/shortw';
|
||||||
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
|
||||||
|
function getHash(hash: CHash) {
|
||||||
|
return {
|
||||||
|
hash,
|
||||||
|
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)),
|
||||||
|
randomBytes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was known as alt_bn128 when it had 128-bit security. Now that it's much lower, the naming
|
||||||
|
// has been changed to its prime bit count.
|
||||||
|
export const bn254 = weierstrass({
|
||||||
|
a: 0n,
|
||||||
|
b: 3n,
|
||||||
|
P: 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47n,
|
||||||
|
n: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n,
|
||||||
|
Gx: 1n,
|
||||||
|
Gy: 2n,
|
||||||
|
...getHash(sha256),
|
||||||
|
});
|
190
curve-definitions/src/nist.ts
Normal file
190
curve-definitions/src/nist.ts
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { sha384, sha512 } from '@noble/hashes/sha512';
|
||||||
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
|
import { weierstrass, CHash } from '@noble/curves/shortw';
|
||||||
|
import { mod, pow2 } from '@noble/curves/modular';
|
||||||
|
|
||||||
|
function getHash(hash: CHash) {
|
||||||
|
return {
|
||||||
|
hash,
|
||||||
|
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)),
|
||||||
|
randomBytes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.secg.org/sec2-v2.pdf
|
||||||
|
// https://neuromancer.sk/std/secg/secp192r1
|
||||||
|
export const P192 = weierstrass({
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
|
||||||
|
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
|
||||||
|
// Field over which we'll do calculations. Verify with: 2n ** 192n - 2n ** 64n - 1n
|
||||||
|
P: BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff'),
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
|
||||||
|
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
|
||||||
|
lowS: false,
|
||||||
|
// Default options
|
||||||
|
...getHash(sha256),
|
||||||
|
} as const);
|
||||||
|
export const secp192r1 = P192;
|
||||||
|
// https://neuromancer.sk/std/nist/P-224
|
||||||
|
export const P224 = weierstrass({
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
|
||||||
|
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
|
||||||
|
// Field over which we'll do calculations. Verify with:
|
||||||
|
P: 2n ** 224n - 2n ** 96n + 1n,
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
|
||||||
|
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
|
||||||
|
lowS: false,
|
||||||
|
// Default options
|
||||||
|
...getHash(sha256),
|
||||||
|
} as const);
|
||||||
|
export const secp224r1 = P224;
|
||||||
|
// https://neuromancer.sk/std/nist/P-256
|
||||||
|
export const P256 = weierstrass({
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
|
||||||
|
b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
|
||||||
|
// Field over which we'll do calculations. Verify with:
|
||||||
|
// 2n ** 224n * (2n ** 32n - 1n) + 2n ** 192n + 2n ** 96n - 1n,
|
||||||
|
P: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
|
||||||
|
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
|
||||||
|
lowS: false,
|
||||||
|
// Default options
|
||||||
|
...getHash(sha256),
|
||||||
|
} as const);
|
||||||
|
export const secp256r1 = P256;
|
||||||
|
// https://neuromancer.sk/std/nist/P-384
|
||||||
|
// prettier-ignore
|
||||||
|
export const P384 = weierstrass({
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc'),
|
||||||
|
b: BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef'),
|
||||||
|
// Field over which we'll do calculations. Verify with:
|
||||||
|
// 2n ** 384n - 2n ** 128n - 2n ** 96n + 2n ** 32n - 1n
|
||||||
|
P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'),
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),
|
||||||
|
Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
|
||||||
|
lowS: false,
|
||||||
|
// Default options
|
||||||
|
...getHash(sha384),
|
||||||
|
} as const);
|
||||||
|
export const secp384r1 = P384;
|
||||||
|
// https://neuromancer.sk/std/nist/P-521
|
||||||
|
// prettier-ignore
|
||||||
|
export const P521 = weierstrass({
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc'),
|
||||||
|
b: BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'),
|
||||||
|
// Field over which we'll do calculations. Verify with:
|
||||||
|
// 2n ** 521n - 1n,
|
||||||
|
P: BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
|
||||||
|
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
|
||||||
|
lowS: false,
|
||||||
|
// Default options
|
||||||
|
...getHash(sha512),
|
||||||
|
} as const);
|
||||||
|
export const secp521r1 = P521;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp256k1 definition with efficient square root and endomorphism.
|
||||||
|
* Endomorphism works only for Koblitz curves with a == 0.
|
||||||
|
* It improves efficiency:
|
||||||
|
* Uses 2x less RAM, speeds up precomputation by 2x and ECDH / sign key recovery by 20%.
|
||||||
|
* Should always be used for Jacobian'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
|
||||||
|
*/
|
||||||
|
const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
|
||||||
|
const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
|
||||||
|
const _1n = BigInt(1);
|
||||||
|
const _2n = BigInt(2);
|
||||||
|
const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b;
|
||||||
|
export const secp256k1 = weierstrass({
|
||||||
|
a: 0n,
|
||||||
|
b: 7n,
|
||||||
|
// Field over which we'll do calculations. Verify with:
|
||||||
|
// 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n
|
||||||
|
P: secp256k1P,
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: secp256k1N,
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
||||||
|
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
|
||||||
|
...getHash(sha256),
|
||||||
|
// noble-secp256k1 compat
|
||||||
|
lowS: true,
|
||||||
|
// Used to calculate y - the square root of y².
|
||||||
|
// Exponentiates it to very big number (P+1)/4.
|
||||||
|
// We are unwrapping the loop because it's 2x faster.
|
||||||
|
// (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
|
||||||
|
// We are multiplying it bit-by-bit
|
||||||
|
sqrtMod: (x: bigint): bigint => {
|
||||||
|
const P = secp256k1P;
|
||||||
|
const _3n = BigInt(3);
|
||||||
|
const _6n = BigInt(6);
|
||||||
|
const _11n = BigInt(11);
|
||||||
|
const _22n = BigInt(22);
|
||||||
|
const _23n = BigInt(23);
|
||||||
|
const _44n = BigInt(44);
|
||||||
|
const _88n = BigInt(88);
|
||||||
|
const b2 = (x * x * x) % P; // x^3, 11
|
||||||
|
const b3 = (b2 * b2 * x) % P; // x^7
|
||||||
|
const b6 = (pow2(b3, _3n, P) * b3) % P;
|
||||||
|
const b9 = (pow2(b6, _3n, P) * b3) % P;
|
||||||
|
const b11 = (pow2(b9, _2n, P) * b2) % P;
|
||||||
|
const b22 = (pow2(b11, _11n, P) * b11) % P;
|
||||||
|
const b44 = (pow2(b22, _22n, P) * b22) % P;
|
||||||
|
const b88 = (pow2(b44, _44n, P) * b44) % P;
|
||||||
|
const b176 = (pow2(b88, _88n, P) * b88) % P;
|
||||||
|
const b220 = (pow2(b176, _44n, P) * b44) % P;
|
||||||
|
const b223 = (pow2(b220, _3n, P) * b3) % P;
|
||||||
|
const t1 = (pow2(b223, _23n, P) * b22) % P;
|
||||||
|
const t2 = (pow2(t1, _6n, P) * b2) % P;
|
||||||
|
return pow2(t2, _2n, P);
|
||||||
|
},
|
||||||
|
endo: {
|
||||||
|
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
||||||
|
splitScalar: (k: bigint) => {
|
||||||
|
const n = secp256k1N;
|
||||||
|
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
|
||||||
|
const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
|
||||||
|
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
|
||||||
|
const b2 = a1;
|
||||||
|
const POW_2_128 = BigInt('0x100000000000000000000000000000000');
|
||||||
|
|
||||||
|
const c1 = divNearest(b2 * k, n);
|
||||||
|
const c2 = divNearest(-b1 * k, n);
|
||||||
|
let k1 = mod(k - c1 * a1 - c2 * a2, n);
|
||||||
|
let k2 = mod(-c1 * b1 - c2 * b2, n);
|
||||||
|
const k1neg = k1 > POW_2_128;
|
||||||
|
const k2neg = k2 > POW_2_128;
|
||||||
|
if (k1neg) k1 = n - k1;
|
||||||
|
if (k2neg) k2 = n - k2;
|
||||||
|
if (k1 > POW_2_128 || k2 > POW_2_128) {
|
||||||
|
throw new Error('splitScalar: Endomorphism failed, k=' + k);
|
||||||
|
}
|
||||||
|
return { k1neg, k1, k2neg, k2 };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
35
curve-definitions/src/pasta.ts
Normal file
35
curve-definitions/src/pasta.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
|
import { weierstrass, CHash } from '@noble/curves/shortw';
|
||||||
|
|
||||||
|
function getHash(hash: CHash) {
|
||||||
|
return {
|
||||||
|
hash,
|
||||||
|
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)),
|
||||||
|
randomBytes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const p = BigInt('0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001');
|
||||||
|
const q = BigInt('0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001');
|
||||||
|
|
||||||
|
export const pallas = weierstrass({
|
||||||
|
a: BigInt(0),
|
||||||
|
b: BigInt(5),
|
||||||
|
P: p,
|
||||||
|
n: q,
|
||||||
|
Gx: BigInt(-1),
|
||||||
|
Gy: BigInt(2),
|
||||||
|
...getHash(sha256),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const vesta = weierstrass({
|
||||||
|
a: BigInt(0),
|
||||||
|
b: BigInt(5),
|
||||||
|
P: q,
|
||||||
|
n: p,
|
||||||
|
Gx: BigInt(-1),
|
||||||
|
Gy: BigInt(2),
|
||||||
|
...getHash(sha256),
|
||||||
|
});
|
264
curve-definitions/src/starknet.ts
Normal file
264
curve-definitions/src/starknet.ts
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
import { keccak_256 } from '@noble/hashes/sha3';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
|
import { weierstrass, CHash, JacobianPointType } from '@noble/curves/shortw';
|
||||||
|
import * as cutils from '@noble/curves/utils';
|
||||||
|
|
||||||
|
function getHash(hash: CHash) {
|
||||||
|
return {
|
||||||
|
hash,
|
||||||
|
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)),
|
||||||
|
randomBytes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const CURVE_N = 3618502788666131213697322783095070105526743751716087489154079457884512865583n;
|
||||||
|
const nBitLength = 252;
|
||||||
|
// https://docs.starkware.co/starkex/stark-curve.html
|
||||||
|
export const starkCurve = weierstrass({
|
||||||
|
// Params: a, b
|
||||||
|
a: 1n,
|
||||||
|
b: 3141592653589793238462643383279502884197169399375105820974944592307816406665n,
|
||||||
|
// Field over which we'll do calculations. Verify with:
|
||||||
|
// NOTE: there is no efficient sqrt for field (P%4==1)
|
||||||
|
P: 2n ** 251n + 17n * 2n ** 192n + 1n,
|
||||||
|
// Curve order, total count of valid points in the field. Verify with:
|
||||||
|
n: CURVE_N,
|
||||||
|
nBitLength: nBitLength, // len(bin(N).replace('0b',''))
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: 874739451078007766457464989774322083649278607533249481151382481072868806602n,
|
||||||
|
Gy: 152666792071518830868575557812948353041420400780739481342941381225525861407n,
|
||||||
|
// Default options
|
||||||
|
lowS: false,
|
||||||
|
...getHash(sha256),
|
||||||
|
truncateHash: (hash: Uint8Array, truncateOnly = false): bigint => {
|
||||||
|
// TODO: cleanup, ugly code
|
||||||
|
// Fix truncation
|
||||||
|
if (!truncateOnly) {
|
||||||
|
let hashS = bytesToNumber0x(hash).toString(16);
|
||||||
|
if (hashS.length === 63) {
|
||||||
|
hashS += '0';
|
||||||
|
hash = hexToBytes0x(hashS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Truncate zero bytes on left (compat with elliptic)
|
||||||
|
while (hash[0] === 0) hash = hash.subarray(1);
|
||||||
|
const byteLength = hash.length;
|
||||||
|
const delta = byteLength * 8 - nBitLength; // size of curve.n (252 bits)
|
||||||
|
let h = hash.length ? bytesToNumber0x(hash) : 0n;
|
||||||
|
if (delta > 0) h = h >> BigInt(delta);
|
||||||
|
if (!truncateOnly && h >= CURVE_N) h -= CURVE_N;
|
||||||
|
return h;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Custom Starknet type conversion functions that can handle 0x and unpadded hex
|
||||||
|
function hexToBytes0x(hex: string): Uint8Array {
|
||||||
|
if (typeof hex !== 'string') {
|
||||||
|
throw new TypeError('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 TypeError('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 sign0x(msgHash: Hex, privKey: Hex, opts: any) {
|
||||||
|
return starkCurve.sign(ensureBytes0x(msgHash), ensureBytes0x(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, Point, JacobianPoint, Signature, getPublicKey, getSharedSecret } = starkCurve;
|
||||||
|
export const utils = starkCurve.utils;
|
||||||
|
export {
|
||||||
|
CURVE,
|
||||||
|
Point,
|
||||||
|
Signature,
|
||||||
|
JacobianPoint,
|
||||||
|
getPublicKey,
|
||||||
|
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 bytesToNumber0x(sha256(cutils.concatBytes(key, hexToBytes0x(indexHex))));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function grindKey(seed: Hex) {
|
||||||
|
const _seed = ensureBytes0x(seed);
|
||||||
|
const sha256mask = 2n ** 256n;
|
||||||
|
const limit = sha256mask - starkCurve.utils.mod(sha256mask, starkCurve.CURVE.n);
|
||||||
|
for (let i = 0; ; i++) {
|
||||||
|
const key = hashKeyWithIndex(_seed, i);
|
||||||
|
// key should be in [0, limit)
|
||||||
|
if (key < limit) return starkCurve.utils.mod(key, starkCurve.CURVE.n).toString(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStarkKey(privateKey: Hex) {
|
||||||
|
const priv = typeof privateKey === 'string' ? strip0x(privateKey) : privateKey;
|
||||||
|
return bytesToHexEth(Point.fromPrivateKey(priv).toRawBytes(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(bytesToNumber0x(sha256(layer)));
|
||||||
|
const applicationNum = int31(bytesToNumber0x(sha256(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 = [
|
||||||
|
new Point(
|
||||||
|
2089986280348253421170679821480865132823066470938446095505822317253594081284n,
|
||||||
|
1713931329540660377023406109199410414810705867260802078187082345529207694986n
|
||||||
|
),
|
||||||
|
new Point(
|
||||||
|
996781205833008774514500082376783249102396023663454813447423147977397232763n,
|
||||||
|
1668503676786377725805489344771023921079126552019160156920634619255970485781n
|
||||||
|
),
|
||||||
|
new Point(
|
||||||
|
2251563274489750535117886426533222435294046428347329203627021249169616184184n,
|
||||||
|
1798716007562728905295480679789526322175868328062420237419143593021674992973n
|
||||||
|
),
|
||||||
|
new Point(
|
||||||
|
2138414695194151160943305727036575959195309218611738193261179310511854807447n,
|
||||||
|
113410276730064486255102093846540133784865286929052426931474106396135072156n
|
||||||
|
),
|
||||||
|
new Point(
|
||||||
|
2379962749567351885752724891227938183011949129833673362440656643086021394946n,
|
||||||
|
776496453633298175483985398648758586525933812536653089401905292063708816422n
|
||||||
|
),
|
||||||
|
];
|
||||||
|
// for (const p of PEDERSEN_POINTS) p._setWindowSize(8);
|
||||||
|
const PEDERSEN_POINTS_JACOBIAN = PEDERSEN_POINTS.map(JacobianPoint.fromAffine);
|
||||||
|
|
||||||
|
function pedersenPrecompute(p1: JacobianPointType, p2: JacobianPointType): JacobianPointType[] {
|
||||||
|
const out: JacobianPointType[] = [];
|
||||||
|
let p = p1;
|
||||||
|
for (let i = 0; i < 248; i++) {
|
||||||
|
out.push(p);
|
||||||
|
p = p.double();
|
||||||
|
}
|
||||||
|
p = p2;
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
out.push(p);
|
||||||
|
p = p.double();
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
const PEDERSEN_POINTS1 = pedersenPrecompute(
|
||||||
|
PEDERSEN_POINTS_JACOBIAN[1],
|
||||||
|
PEDERSEN_POINTS_JACOBIAN[2]
|
||||||
|
);
|
||||||
|
const PEDERSEN_POINTS2 = pedersenPrecompute(
|
||||||
|
PEDERSEN_POINTS_JACOBIAN[3],
|
||||||
|
PEDERSEN_POINTS_JACOBIAN[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.P))
|
||||||
|
throw new Error(`PedersenArg should be 0 <= value < CURVE.P: ${value}`);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pedersenSingle(
|
||||||
|
point: JacobianPointType,
|
||||||
|
value: PedersenArg,
|
||||||
|
constants: JacobianPointType[]
|
||||||
|
) {
|
||||||
|
let x = pedersenArg(value);
|
||||||
|
for (let j = 0; j < 252; j++) {
|
||||||
|
const pt = constants[j];
|
||||||
|
if (pt.x === point.x) 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: JacobianPointType = PEDERSEN_POINTS_JACOBIAN[0];
|
||||||
|
point = pedersenSingle(point, x, PEDERSEN_POINTS1);
|
||||||
|
point = pedersenSingle(point, y, PEDERSEN_POINTS2);
|
||||||
|
return bytesToHexEth(point.toAffine().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 = 2n ** 250n - 1n;
|
||||||
|
export const keccak = (data: Uint8Array) => bytesToNumber0x(keccak_256(data)) & MASK_250;
|
97
curve-definitions/test/basic.test.js
Normal file
97
curve-definitions/test/basic.test.js
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
|
import { should } from 'micro-should';
|
||||||
|
import * as nist from '../lib/nist.js';
|
||||||
|
import { hexToBytes } from '@noble/curves/utils';
|
||||||
|
import { default as ecdsa } from './fixtures/ecdsa_test.json' assert { type: 'json' };
|
||||||
|
import { default as ecdh } from './fixtures/ecdh_test.json' assert { type: 'json' };
|
||||||
|
|
||||||
|
// import { hexToBytes } from '@noble/curves';
|
||||||
|
|
||||||
|
should('Curve Fields', () => {
|
||||||
|
const vectors = {
|
||||||
|
secp192r1: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn,
|
||||||
|
secp224r1: 0xffffffffffffffffffffffffffffffff000000000000000000000001n,
|
||||||
|
secp256r1: 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffffn,
|
||||||
|
secp256k1: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
|
||||||
|
secp384r1:
|
||||||
|
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffffn,
|
||||||
|
secp521r1:
|
||||||
|
0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn,
|
||||||
|
};
|
||||||
|
for (const n in vectors) deepStrictEqual(nist[n].CURVE.P, vectors[n]);
|
||||||
|
});
|
||||||
|
|
||||||
|
should('wychenproof ECDSA vectors', () => {
|
||||||
|
for (const group of ecdsa.testGroups) {
|
||||||
|
// Tested in secp256k1.test.js
|
||||||
|
if (group.key.curve === 'secp256k1') continue;
|
||||||
|
// We don't have SHA-224
|
||||||
|
if (group.key.curve === 'secp224r1' && group.sha === 'SHA-224') continue;
|
||||||
|
const CURVE = nist[group.key.curve];
|
||||||
|
if (!CURVE) continue;
|
||||||
|
const pubKey = CURVE.Point.fromHex(group.key.uncompressed);
|
||||||
|
deepStrictEqual(pubKey.x, BigInt(`0x${group.key.wx}`));
|
||||||
|
deepStrictEqual(pubKey.y, BigInt(`0x${group.key.wy}`));
|
||||||
|
for (const test of group.tests) {
|
||||||
|
if (['Hash weaker than DL-group'].includes(test.comment)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const m = CURVE.CURVE.hash(hexToBytes(test.msg));
|
||||||
|
if (test.result === 'valid' || test.result === 'acceptable') {
|
||||||
|
try {
|
||||||
|
CURVE.Signature.fromDER(test.sig);
|
||||||
|
} catch (e) {
|
||||||
|
// Some test has invalid signature which we don't accept
|
||||||
|
if (e.message.includes('Invalid signature: incorrect length')) continue;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
const verified = CURVE.verify(test.sig, m, pubKey);
|
||||||
|
deepStrictEqual(verified, true, 'valid');
|
||||||
|
} else if (test.result === 'invalid') {
|
||||||
|
let failed = false;
|
||||||
|
try {
|
||||||
|
failed = !CURVE.verify(test.sig, m, pubKey);
|
||||||
|
} catch (error) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
deepStrictEqual(failed, true, 'invalid');
|
||||||
|
} else throw new Error('unknown test result');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('wychenproof ECDH vectors', () => {
|
||||||
|
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;
|
||||||
|
for (const test of group.tests) {
|
||||||
|
if (test.result === 'valid' || test.result === 'acceptable') {
|
||||||
|
try {
|
||||||
|
const pub = CURVE.Point.fromHex(test.public);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.message.includes('Point.fromHex: received invalid point.')) continue;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
const shared = CURVE.getSharedSecret(test.private, test.public);
|
||||||
|
deepStrictEqual(shared, test.shared, 'valid');
|
||||||
|
} else if (test.result === 'invalid') {
|
||||||
|
let failed = false;
|
||||||
|
try {
|
||||||
|
CURVE.getSharedSecret(test.private, test.public);
|
||||||
|
} catch (error) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
deepStrictEqual(failed, true, 'invalid');
|
||||||
|
} else throw new Error('unknown test result');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ESM is broken.
|
||||||
|
import url from 'url';
|
||||||
|
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
||||||
|
should.run();
|
||||||
|
}
|
898
curve-definitions/test/fixtures/ecdh_secp224r1_ecpoint_test.json
vendored
Normal file
898
curve-definitions/test/fixtures/ecdh_secp224r1_ecpoint_test.json
vendored
Normal file
@ -0,0 +1,898 @@
|
|||||||
|
{
|
||||||
|
"algorithm" : "ECDH",
|
||||||
|
"generatorVersion" : "0.8r12",
|
||||||
|
"numberOfTests" : 96,
|
||||||
|
"header" : [
|
||||||
|
"Test vectors of type EcdhWebTest are intended for",
|
||||||
|
"testing an ECDH implementations where the public key",
|
||||||
|
"is just an ASN encoded point."
|
||||||
|
],
|
||||||
|
"notes" : {
|
||||||
|
"AddSubChain" : "The private key has a special value. Implementations using addition subtraction chains for the point multiplication may get the point at infinity as an intermediate result. See CVE_2017_10176",
|
||||||
|
"CompressedPoint" : "The point in the public key is compressed. Not every library supports points in compressed format."
|
||||||
|
},
|
||||||
|
"schema" : "ecdh_ecpoint_test_schema.json",
|
||||||
|
"testGroups" : [
|
||||||
|
{
|
||||||
|
"curve" : "secp224r1",
|
||||||
|
"encoding" : "ecpoint",
|
||||||
|
"type" : "EcdhEcpointTest",
|
||||||
|
"tests" : [
|
||||||
|
{
|
||||||
|
"tcId" : 1,
|
||||||
|
"comment" : "normal case",
|
||||||
|
"public" : "047d8ac211e1228eb094e285a957d9912e93deee433ed777440ae9fc719b01d050dfbe653e72f39491be87fb1a2742daa6e0a2aada98bb1aca",
|
||||||
|
"private" : "565577a49415ca761a0322ad54e4ad0ae7625174baf372c2816f5328",
|
||||||
|
"shared" : "b8ecdb552d39228ee332bafe4886dbff272f7109edf933bc7542bd4f",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 2,
|
||||||
|
"comment" : "compressed public key",
|
||||||
|
"public" : "027d8ac211e1228eb094e285a957d9912e93deee433ed777440ae9fc71",
|
||||||
|
"private" : "565577a49415ca761a0322ad54e4ad0ae7625174baf372c2816f5328",
|
||||||
|
"shared" : "b8ecdb552d39228ee332bafe4886dbff272f7109edf933bc7542bd4f",
|
||||||
|
"result" : "acceptable",
|
||||||
|
"flags" : [
|
||||||
|
"CompressedPoint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 3,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04e73a6ca72f3a2fae6e0a01a0ed03bfa3058b04576942eaf063095e62ca16fd31fa0f38eeb592cbeea1147751fdd2a5b6cc0ead404467a5b6",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "00000000000000000000000000000000000000000000000000000003",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 4,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "045763fa2ae16367ad23d471cc9a52466f0d81d864e5640cefe384114594d9fecfbed4f254505ac8b41d2532055a07f0241c4818b552cbb636",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "00000000000000000000000100000000000000000000000000000001",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 5,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04142c1fd80fa2121a59aa898144084ec033f7a56a34eee0b499e29ae51c6d8c1bbb1ef2a76d565899fe44ffc1207d530d7f598fb77f4bb76b",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "00000000000000ffffffffffffff0000000000000100000000000000",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 6,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04ed6f793e10c80d12d871cf8988399c4898a9bf9ffd8f27399f63de25f0051cdf4eec7f368f922cfcd948893ceca0c92e540cc4367a99a66a",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "00000000ffffffffffffffff00000000000000010000000000000000",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 7,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "0408fcfc1a63c82860be12e4137433dfc40be9acdd245f9a8c4e56be61a385fc09f808383383f4b1d0d5365b6e5dcfacdc19bc7bcfed221274",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 8,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04d883ed77f1861e8712800d31df67888fe39f150c79a27aa88caeda6b180f3f623e2ff3ab5370cf8179165b085af3dd4502850c0104caed9a",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "0003fffffff00000003fffffff00000003fffffff000000040000000",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 9,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "042b8b279b85ee3f3d2c0abeb36fdfc5aad6157d652d26489381a32cd73224bd757ef794acc92b0b3b9e7990618bb343a9a09bdb9d3616eff6",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "01fffffffc00000007fffffff00000001fffffffc000000080000001",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 10,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "048bd5f03391eeeae1744e8fc53d314efffafa4d3fa4f1b95c3388a9cd7c86358b273119c537133eb55e79c6ac510b10980b379b919ccf2e2f",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "0a15c112ff784b1445e889f955be7e3ffdf451a2c0e76ab5cb32cf41",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 11,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04ce9631b6a16227778625c8e5421ae083cdd913abefde01dbe69f6c2b95386aff2b483b2c47151cfaabfd000614c683ce2e1778221ae42c1b",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "62989eaaa26a16f07330c3c51e0a4631fd016bfcede26552816aee39",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 12,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "041f441c98eda956a6a7fdbfd8d21910860ab59d16c3e52f8e7fad6ca5df61a55fc508fc0499c55492f1e87bb2faa0cb4170b79f3a85ec2f3d",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "661ac958c0febbc718ccf39cefc6b66c4231fbb9a76f35228a3bf5c3",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 13,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04be74583cb9d3a05ae54923624e478a329a697d842dfae33141c844d7d9ba4fc96e0fe716ac0542e87368662fc2f0cb9b0ae57936ddec7190",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "6d7e41821abe1094d430237923d2a50de31768ab51b12dce8a09e34c",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 14,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04a281ad992b363597ac93ff0de8ab1f7e51a6672dcbb58f9d739ba430ce0192874038daefc3130eec65811c7255da70fea65c1003f6892faa",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "7fffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 15,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04be3e22133f51203f631b81dde8c020cdea5daa1f99cfc05c88fad2dc0f243798d6e72d1de9e3cdca4144e0a6c0f2a584d07589006972c197",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0008001",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 16,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04af14547c20afbd91bfe64ea03d45a76a71241f23520ef897ff91eff1b54ca6ca8c25fd73852ec6654617434eff7f0225684d4dea7a4f8a97",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "ffff0000003ffffff0000003ffffff0000003ffffff0000003ffffff",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 17,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04b1e484925018729926acda56ff3e2f6c1e7e8f162b178d8e8afb45564fceaa6da5d998fe26b6b26a055169063a5ab6908852ca8b54e2de6c",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "fffff0000007fffffe000000ffffffc000001ffffff8000003ffffff",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 18,
|
||||||
|
"comment" : "edge case for shared secret",
|
||||||
|
"public" : "04937eb09fb145c8829cb7df20a4cbeed396791373de277871d6c5f9cc3b5b4fd56464a71fc4a2a6af3bd251952bffa829489e68a8d06f96b6",
|
||||||
|
"private" : "00a2b6442a37f9201b56758034d2009be64b0ab7c02d7e398cac9665d6",
|
||||||
|
"shared" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 19,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04000000000000000000000000000000000000000000000000000000037cac269c67bd55ea14efff4eadefe5e74978514af14c88fab46ec046",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "3fa0b9ff70b884f9f57bb84f7a9532d93f6ba803f89dd8ff008177d7",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 20,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04000000000000000000000001000000000000000000000000000000012ea2f4917bdfdb008306cc10a18e2557633ba861001829dcbfb96fba",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "be1ded8cb7ff8a585181f96d681e31b332fe27dcae922dca2310300d",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 21,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "0400000000000000ffffffffffffff000000000000010000000000000073ca5f8f104997a2399e0c7f25e72a75ec29fc4542533d3fea89a33a",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "a2e86a260e13515918a0cafdd87855f231b5624c560f976159e06a75",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 22,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "0400000000ffffffffffffffff000000000000000100000000000000006fe6805f59b19b0dd389452a1d4a420bfeb6c369cf6fed5b12e6e654",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "31ef7c8d10404a0046994f313a70574b027e87f9028eca242c1b5bf5",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 23,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "040000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff77c5cfa4e2c384938d48bd8dd98f54c86b279f1df8c0a1f6692439c9",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "d1976a8ef5f54f24f5a269ad504fdca849fc9c28587ba294ef267396",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 24,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "040003fffffff00000003fffffff00000003fffffff00000004000000001f0828136016bb97445461bc59f2175d8d23557d6b9381f26136e3d",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "ce7890d108ddb2e5474e6417fcf7a9f2b3bd018816062f4835260dc8",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 25,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "0401fffffffc00000007fffffff00000001fffffffc0000000800000012d8acca6f199d4a94b933ba1aa713a7debde8ac57b928f596ae66a66",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "30b6ff6e8051dae51e4fe34b2d9a0b1879153e007eb0b5bdf1791a9c",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 26,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "040a15c112ff784b1445e889f955be7e3ffdf451a2c0e76ab5cb32cf413d4df973c563c6decdd435e4f864557e4c273096d9941ca4260a266e",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "77ec668a00f72d85aa527624abb16c039fe490d17dd6c455a1ed7fd8",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 27,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "0462989eaaa26a16f07330c3c51e0a4631fd016bfcede26552816aee39389ee9436d616cab90032931aa7fbbfcfc13309f61e2423cc8dab93c",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "a3f432f6aba9a92f49a5ea64ffe7059a9d9b487a0b5223ddc988208b",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 28,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04661ac958c0febbc718ccf39cefc6b66c4231fbb9a76f35228a3bf5c3103b8040e3cb41966fc64a68cacb0c14053f87d27e8ed7bf2d7fe51b",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "1530fd9caf03737af34a4ba716b558cbecbc35d18402535a0a142313",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 29,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "046d7e41821abe1094d430237923d2a50de31768ab51b12dce8a09e34c276cf273d75d367820dd556182def0957af0a314f48fed227c298dc0",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "cfc39ccacb94ad0e0552b2e47112f60fbbe7ae0dc32230b9273dd210",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 30,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "047fffffffffffffffffffffffffffffffffffffffffffffffffffffff7d8dbca36c56bcaae92e3475f799294f30768038e816a7d5f7f07d77",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "73bd63bd384a0faafb75cfed3e95d3892cbacf0db10f282c3b644771",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 31,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc000800174f1ff5ea7fbc72b92f61e06556c26bab84c0b082dd6400ca1c1eb6d",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "85b079c62e1f5b0fd6841dfa16026e15b641f65e13a14042567166bb",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 32,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04ffff0000003ffffff0000003ffffff0000003ffffff0000003ffffff0126fdd5fccd0b5aa7fd5bb5b1308584b30556248cec80208a2fe962",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "8a834ff40e3fc9f9d412a481e18537ea799536c5520c6c7baaf12166",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 33,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04fffff0000007fffffe000000ffffffc000001ffffff8000003ffffff20cfa23077acc9fbcb71339c65880cd0b966b8a9497e65abed17f0b5",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "a0887269766e6efcbc81d2b38f2d4638663f12377468a23421044188",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 34,
|
||||||
|
"comment" : "edge cases for ephemeral key",
|
||||||
|
"public" : "04ffffffff00000000ffffffff00000000ffffffff00000000ffffffff1c05ac2d4f10b69877c3243d51f887277b7bf735c326ab2f0d70da8c",
|
||||||
|
"private" : "2bc15cf3981f4e15bbad387b506df647989e5478160be862f8c26969",
|
||||||
|
"shared" : "c65d1911bc076a74588d8793ce7a0dcabf5793460cd2ebb02754a1be",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 35,
|
||||||
|
"comment" : "point with coordinate y = 1",
|
||||||
|
"public" : "043b5889352ddf7468bf8c0729212aa1b2a3fcb1a844b8be91abb753d500000000000000000000000000000000000000000000000000000001",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "e973c413cc7dd34d4e3637522b2e033c20815412b67574a1f2f6bdd7",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 36,
|
||||||
|
"comment" : "point with coordinate y = 1",
|
||||||
|
"public" : "04bf09e268942555c73ce9e00d272c9b12bf0c3fc13a639acc791167f6b05df0023c9bd41d0b0c461854582d0601182213f2219d44ea44914a",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "ec856e807808a9c5332e886759e03f01be02437cfe0214613e4e7dc7",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 37,
|
||||||
|
"comment" : "point with coordinate y = 1",
|
||||||
|
"public" : "047b664cff2eef0a4f7dce24780113432f66feb25cb0931d033d63910f548ee514f6fdf1cb6f5709581c197d76a5eb218afaed19f205f4ab80",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "91d424e122c9c01720bbed6b53ec1b37a86996fa4fcf74bfd30f723d",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 38,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "045a2b3ec1053390550b587557712bcc0bf85654d23099420154877ec4138322ca02e5fceae870227a43ae8982b67276f6d8f1dd7e12692474",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "012879a1ff456acb8726455836bc4f504c1bd799a4d96f514b3730c6",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 39,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04fc229bb1df3e11351e7e4224f68f40c0d0e194023c6e0840cd45ee5ca242112fbab5736e821dad26493e4006e2c6125342e7d9bc25272856",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "fd6e5edb54d7dd554f8747ec87b8031258fc0bf1d2404b64db4540d4",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 40,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "0469a65f62d4159235801a246f2d13e45c8983a3362da480e7a51d42a65b7047abfc2a179d943bb196fede7ac3ad8a4fcacd4c4caa717b6b26",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "164e95bfa2a9c3a1f959feb88720bb7a37f988a08124639d8adf86df",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 41,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04dc68eb945528af0051cbf23e3eea43b2bc4c728976231e7031e63a2744ba65a4e1e34e8ec50cf7e8df4458582b16413ab83f568508c59037",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "b0ffd55fa112aa48eddc960db4a1200d406e144aac9e109ad9892b2d",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 42,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "0481c89369d7be252920e08e2d6c6841b887efb4fc747db31dd1030b1919bf8ccb629b58fea6234e39812083fb0833a0c937e348eda22ea0c0",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "d6ab4567eff21277284be082d9e09eb08bb80685f4929dc3dca4b333",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 43,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "0451d830f792795409f1ee972d3b94289f59206fe09e12166920739a73d2f1831b26677901bfaf8323f82b81e1012d9d3f1c9296c59c97970f",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "b43de12912b40cbdd56e30fdfe9a2c24fb72687168c9cfe6b7476966",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 44,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04ab63ce55145842149f99023f37a0a89b9fc4ae6a878fdae8caf31d17ffd0d55830eed46f8255f94b6dcf98a22f1ff26dabf773d556788881",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "588ee0af3bc60118a715325c6d56c850f73067dcb37b7596d0cfda5f",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 45,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "041d64535d54bfcccb38165acbfac01ae33db20e802c5687343cb21b7eb59d86f1892a974741925624477eef21f4e72fa04ee6ce35dfffe5f2",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "7219ef73ac9e47ac2e03dead23fa8382ae898e2415017cdeb4739f0f",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 46,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04d9d78436a3f9c1fa20e8c2318e61e62b94623e23a0ab746c5ac0cbc38262bd66c17515d3048944dae43b2bd6dd9d7c7a0f7042de2d1001c6",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "267b069aac5d768a720acc62c92f20b786fc48c7da42f1f5677424ee",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 47,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "0465eb3750c6401339caa69ebe6dec86dfc4d79bf657d68bbdd082c5a03eb81e85931352ff338ccbc3a1d332e2d8bc84342d516da06bef220f",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "bbdd4ac5890b9c0412e4ef3135f666e5b3ddb658ec837691e8129be8",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 48,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04e92d3be1614555ae17a90647979fbb37468c55a1fff9e15f376d49994e470f515b7b3fe50cb55def16142df594c3e46d9d1354730778f9e8",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "f793ff0d14bd7690840c733162b589cd3413d8c41f4488b427da496f",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 49,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "043c92710c9a7f6f98bbec9d2a4fa617cc70e96bc96ecd4597e329143f4750a027c6972459c091ab02c0e2a3082fccec429a38d3596e7aff2b",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "56c703d4716239c954109b9b841db75b04a790f1f72aa966aece3494",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 50,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04568dfbfa42efc94ce207322e637b4c94f37a5668ad230e987a91d048dcadd244fc059cffab5fa8820a969353620e708e85bd5eec8a0c68ec",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "7823fe7eb642d50984fb32f911ef289419d85330c3398423d0eda05f",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 51,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04ec10837e495b644904dba58d8dd82133c905a285ae7c2a06d5ccaf6bf0fbf00d13e21a399dc95ae5524a1a37044193e94e3300259b70e058",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "f7014d38f460836a51075cce9667b56b8851ba19011c8b0274b74a4b",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 52,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04bee2f9352f42ceeb3bf3109e90e6578d0bd4888458df7d179d746977e50e53503dee83eca1824a290566588fa3591645b1a2d56861bda760",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "777f99f2bdaa72a1185388465ddda1d059872ad043c7cb85b94e28bb",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 53,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "04546facbcaa8b551c51715a9add5edc3c8a66dcc47a6223f605614cf7af6d92f5bdebea738658a42c6231e53c08237ccf52f79399579b2dcc",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "a1db178b716e51e0fa46c1d74a2603005326bca7e81170d4b33a3d2a",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 54,
|
||||||
|
"comment" : "point with coordinate y = 1 in left to right addition chain",
|
||||||
|
"public" : "0423b1811fee891adb33c8bfee289964e92a9d3358daf975d0efb73e229a3332668b7d6da290a2edc941e8bd6f2e33745fc606756eddc013bb",
|
||||||
|
"private" : "00938f3dbe37135cdbdb9993a187a0e9b9f0def035fbc52ad59fc50421",
|
||||||
|
"shared" : "f455c8273416199505019861266ddb9bcde7bee3c3f15a98ee54607b",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 55,
|
||||||
|
"comment" : "point with coordinate y = 1 in precomputation or right to left addition chain",
|
||||||
|
"public" : "0458f53d67332415fe5b4b81999f8332fb6dcdb965d96dbcbab0fac375f29efef7ab4d94bb2d25d25205eae29fe8d9a85b811114a50f6c6859",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "d3af1857aca1689514fcfee8d8c40b8637d40452ae35c404f9e67494",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 56,
|
||||||
|
"comment" : "point with coordinate y = 1 in precomputation or right to left addition chain",
|
||||||
|
"public" : "04f2d6e58fcd3ed3f656a9bc687fe4c789ba9614d0359967bc0468eabfa1658a14ef0633f2485e29141e2c4a13bd328ec9bf6af4c7a774131b",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "933c385d5fadb57de53e4a5d385118fce830430703c3f585a5d4d0b5",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 57,
|
||||||
|
"comment" : "point with coordinate y = 1 in precomputation or right to left addition chain",
|
||||||
|
"public" : "0402ca5d1b7638b7b88ad02176bd10ff1cfe8812a62f9769a6d62e0c6c787b3e3b2a063940911bf987fc38deebf542400b8bbd9dfeb7d90a8a",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "75aea79d99e5c7edaab0284443b548843371d1d9b55f2d73a1a9092f",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 58,
|
||||||
|
"comment" : "point with coordinate y = 1 in precomputation or right to left addition chain",
|
||||||
|
"public" : "04a394d8bf9b479ec3c7ac3fc6a631d01d57d338b9fb5a0ed6e5130e050cfc600cfb08e67727ac5a33345ec1d48d4a9a18516c2203acbd2667",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "8c1d0850691cda7523ffccf1cba44b4d472193e6a3bb0727e490a8b5",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 59,
|
||||||
|
"comment" : "point with coordinate y = 1 in precomputation or right to left addition chain",
|
||||||
|
"public" : "04642e26421e96fa88f956d098ac26f02f1d6faa80e460e701a3789a66c38dd95c6b33de8768c85cbe6879d0d77e29fe5a18b26a35cb60c0b6",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "50b9ed4d99e2f24e0096eaeded0b552cf8deff5ca8f976964ae47e92",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 60,
|
||||||
|
"comment" : "point with coordinate y = 1 in precomputation or right to left addition chain",
|
||||||
|
"public" : "04f974d1cbbf4171d4773c3e84eab80bc3c6c2858dadcfbd11d64316905df36fbe345f28a3ef663125649474c6fc1ebe175c3865c4469e192b",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "5616ee3e63dfb424d329c2b9b50cf378bb77a8bd7e314a241b5942c7",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 61,
|
||||||
|
"comment" : "point with coordinate y = 1 in right to left addition chain",
|
||||||
|
"public" : "0455561db3cc8fb08a71654ee9573a1a36a44f0913ca8ad7582cfafbfc62b31e5e78be98ad8c8ceab4bb82e8efc0acb29f1a8d031ed044046c",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "b1da14507b5c05159e15f77d085c017acd89f158011357a97802855d",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 62,
|
||||||
|
"comment" : "point with coordinate y = 1 in right to left addition chain",
|
||||||
|
"public" : "04a363bcb9bddd5de84a2f4433c039f7be3fce6057b0d3b4a3459e54a2ba32302871e7ba5c3dd7ec9b76946cdc702c15a8d9ec0f4a04e7afb6",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "2f1bd4a5a497481c4a21222320ff61f32674a95d540cc3f4f3ca5849",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 63,
|
||||||
|
"comment" : "point with coordinate y = 1 in right to left addition chain",
|
||||||
|
"public" : "043a656d0e25bce27282f256b121fbfcde0a180ccd7aa601a5929fc74002f89e45b4dcb873c56da5d1a28fbca33a126177b217a098e0952e62",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "8c807d65ba7b9fd3061dffef26c025a89524a26b942edd3a984fe51d",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 64,
|
||||||
|
"comment" : "point with coordinate y = 1 in right to left addition chain",
|
||||||
|
"public" : "04bf5f49ba0086eec289b068b783438ef24b6f28130bb1ed969ef8b041f11b0de95f15edcd835f01bab1f5faaa1749c2ca4f16a7d99d916ff4",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "8fda76f4d124e6727f855e5f4921cc05c48e2a8ed0fee7c75d6a8047",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 65,
|
||||||
|
"comment" : "point with coordinate y = 1 in right to left addition chain",
|
||||||
|
"public" : "04a57232560d9d604655181f775859b0723d4e01a4c867844eb9d81dabb5d19507bbe9cda3346bad7c184daa432e7f794a5b9b8b8d4e55be3a",
|
||||||
|
"private" : "00c1781d86cac2c0af3fb50d54c554a67bd75d25ca796f0486e3fa84f9",
|
||||||
|
"shared" : "daf35bb7bf3a056bb62bb01ba00f581c107f64de85842b3a49bc2a4a",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 66,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "03",
|
||||||
|
"shared" : "e71f2157bfe37697ea5193d4732dcc6e5412fa9d38387eacd391c1c6",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 67,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"shared" : "fa2664717c7fa0161ec2c669b2c0986cdc20456a6e5406302bb53c77",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 68,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "01000000000000000000000000000000000000000000000000000000",
|
||||||
|
"shared" : "af6e5ad34497bae0745f53ad78ce8b285d79f400d5c6e6a071f8e6bd",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 69,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "7fffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"shared" : "12fd302ff8c13c55a9c111f8bb6b0a13ecf88299c0ae3032ce2bcaff",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 70,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "0080000000000000000000000000000000000000000000000000000000",
|
||||||
|
"shared" : "73f1a395b842f1a6752ae417e2c3dc90cafc4476d1d861b7e68ad030",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 71,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03d13dd29455c5c2a3d",
|
||||||
|
"shared" : "b329c20ddb7c78ee4e622bb23a984c0d273ba34b6269f3d9e8f89f8e",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 72,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13cd29455c5c2a3d",
|
||||||
|
"shared" : "6f48345209b290ffc5abbe754a201479e5d667a209468080d06197b4",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 73,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13d529455c5c2a3d",
|
||||||
|
"shared" : "9f6e30c1c9dad42a153aacd4b49a8e5c721d085cd07b5d5aec244fc1",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 74,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13dd29445c5c2a3d",
|
||||||
|
"shared" : "8cadfb19a80949e61bd5b829ad0e76d18a5bb2eeb9ed7fe2b901cecd",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 75,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c29b7",
|
||||||
|
"shared" : "475fd96e0eb8cb8f100a5d7fe043a7a6851d1d611da2643a3c6ae708",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : [
|
||||||
|
"AddSubChain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 76,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a37",
|
||||||
|
"shared" : "41ef931d669d1f57d8bb95a01a92321da74be8c6cbc3bbe0b2e73ebd",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : [
|
||||||
|
"AddSubChain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 77,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3a",
|
||||||
|
"shared" : "e71f2157bfe37697ea5193d4732dcc6e5412fa9d38387eacd391c1c6",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 78,
|
||||||
|
"comment" : "edge case private key",
|
||||||
|
"public" : "04478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504",
|
||||||
|
"private" : "00ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3b",
|
||||||
|
"shared" : "11ff15126411299cbd49e2b7542e69e91ef132e2551a16ecfebb23a3",
|
||||||
|
"result" : "valid",
|
||||||
|
"flags" : [
|
||||||
|
"AddSubChain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 79,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 80,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 81,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "0400000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 82,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "0400000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 83,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "040000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 84,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "040000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 85,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "0400000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffff000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 86,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "0400000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffff000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 87,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 88,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 89,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 90,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 91,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff00000000000000000000000100000000000000000000000000000000000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 92,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff00000000000000000000000100000000000000000000000000000000000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 93,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff000000000000000000000001ffffffffffffffffffffffffffffffff000000000000000000000000",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 94,
|
||||||
|
"comment" : "point is not on curve",
|
||||||
|
"public" : "04ffffffffffffffffffffffffffffffff000000000000000000000001ffffffffffffffffffffffffffffffff000000000000000000000001",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 95,
|
||||||
|
"comment" : "",
|
||||||
|
"public" : "",
|
||||||
|
"private" : "00c6cafb74e2a5b5ed4b991cbbfbc28c18f6df208b6d05e7a2e6668014",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tcId" : 96,
|
||||||
|
"comment" : "invalid public key",
|
||||||
|
"public" : "020ca753db5ddeca474241f8d2dafc0844343fd0e37eded2f0192d51b2",
|
||||||
|
"private" : "00fc28a0ca0f8e36b0d4f71421845135a22aef543b9fddf8c775b2d18f",
|
||||||
|
"shared" : "",
|
||||||
|
"result" : "invalid",
|
||||||
|
"flags" : [
|
||||||
|
"CompressedPoint"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
3581
curve-definitions/test/fixtures/ecdh_secp224r1_test.json
vendored
Normal file
3581
curve-definitions/test/fixtures/ecdh_secp224r1_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4545
curve-definitions/test/fixtures/ecdh_secp256k1_test.json
vendored
Normal file
4545
curve-definitions/test/fixtures/ecdh_secp256k1_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1994
curve-definitions/test/fixtures/ecdh_secp256r1_ecpoint_test.json
vendored
Normal file
1994
curve-definitions/test/fixtures/ecdh_secp256r1_ecpoint_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4677
curve-definitions/test/fixtures/ecdh_secp256r1_test.json
vendored
Normal file
4677
curve-definitions/test/fixtures/ecdh_secp256r1_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1672
curve-definitions/test/fixtures/ecdh_secp384r1_ecpoint_test.json
vendored
Normal file
1672
curve-definitions/test/fixtures/ecdh_secp384r1_ecpoint_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4366
curve-definitions/test/fixtures/ecdh_secp384r1_test.json
vendored
Normal file
4366
curve-definitions/test/fixtures/ecdh_secp384r1_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2196
curve-definitions/test/fixtures/ecdh_secp521r1_ecpoint_test.json
vendored
Normal file
2196
curve-definitions/test/fixtures/ecdh_secp521r1_ecpoint_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4868
curve-definitions/test/fixtures/ecdh_secp521r1_test.json
vendored
Normal file
4868
curve-definitions/test/fixtures/ecdh_secp521r1_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
29390
curve-definitions/test/fixtures/ecdh_test.json
vendored
Normal file
29390
curve-definitions/test/fixtures/ecdh_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
24578
curve-definitions/test/fixtures/ecdsa_test.json
vendored
Normal file
24578
curve-definitions/test/fixtures/ecdsa_test.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
107
curve-definitions/test/fixtures/rfc6979.json
vendored
Normal file
107
curve-definitions/test/fixtures/rfc6979.json
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"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": "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC",
|
||||||
|
"message": "sample",
|
||||||
|
"r": "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA",
|
||||||
|
"s": "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904",
|
||||||
|
"message": "test",
|
||||||
|
"r": "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6",
|
||||||
|
"s": "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
8
curve-definitions/test/index.test.js
Normal file
8
curve-definitions/test/index.test.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { should } from 'micro-should';
|
||||||
|
|
||||||
|
import './basic.test.js';
|
||||||
|
import './rfc6979.test.js';
|
||||||
|
import './secp256k1.test.js';
|
||||||
|
import './starknet/starknet.test.js';
|
||||||
|
|
||||||
|
should.run();
|
33
curve-definitions/test/rfc6979.test.js
Normal file
33
curve-definitions/test/rfc6979.test.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { deepStrictEqual } from 'assert';
|
||||||
|
import { should } from 'micro-should';
|
||||||
|
import * as nist from '../lib/nist.js';
|
||||||
|
import { default as rfc6979 } from './fixtures/rfc6979.json' assert { type: 'json' };
|
||||||
|
function hexToBigint(hex) {
|
||||||
|
return BigInt('0x' + hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
should('RFC6979', () => {
|
||||||
|
for (const v of rfc6979) {
|
||||||
|
const curve = nist[v.curve];
|
||||||
|
deepStrictEqual(curve.CURVE.n, hexToBigint(v.q));
|
||||||
|
const pubKey = curve.getPublicKey(v.private);
|
||||||
|
const pubPoint = curve.Point.fromHex(pubKey);
|
||||||
|
deepStrictEqual(pubPoint.x, hexToBigint(v.Ux));
|
||||||
|
deepStrictEqual(pubPoint.y, hexToBigint(v.Uy));
|
||||||
|
for (const c of v.cases) {
|
||||||
|
const h = curve.CURVE.hash(c.message);
|
||||||
|
const sigObj = curve.sign(h, v.private);
|
||||||
|
// const sigObj = curve.Signature.fromDER(sig);
|
||||||
|
deepStrictEqual(sigObj.r, hexToBigint(c.r), 'R');
|
||||||
|
deepStrictEqual(sigObj.s, hexToBigint(c.s), 'S');
|
||||||
|
deepStrictEqual(curve.verify(sigObj.toDERRawBytes(), h, pubKey), true, 'verify(1)');
|
||||||
|
deepStrictEqual(curve.verify(sigObj, h, pubKey), true, 'verify(2)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ESM is broken.
|
||||||
|
import url from 'url';
|
||||||
|
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
||||||
|
should.run();
|
||||||
|
}
|
559
curve-definitions/test/secp256k1.test.js
Normal file
559
curve-definitions/test/secp256k1.test.js
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
import * as fc from 'fast-check';
|
||||||
|
import * as nist from '../lib/nist.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 } from 'micro-should';
|
||||||
|
import { deepStrictEqual, throws, rejects } from 'assert';
|
||||||
|
import { hexToBytes, bytesToHex } from '@noble/hashes/utils';
|
||||||
|
|
||||||
|
const hex = bytesToHex;
|
||||||
|
const secp = nist.secp256k1;
|
||||||
|
const privatesTxt = readFileSync('./test/vectors/privates-2.txt', 'utf-8');
|
||||||
|
const schCsv = readFileSync('./test/vectors/schnorr.csv', 'utf-8');
|
||||||
|
|
||||||
|
const FC_BIGINT = fc.bigInt(1n + 1n, secp.CURVE.n - 1n);
|
||||||
|
// prettier-ignore
|
||||||
|
const INVALID_ITEMS = ['deadbeef', Math.pow(2, 53), [1], 'xyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxyxyzxyzxy', secp.CURVE.n + 2n];
|
||||||
|
|
||||||
|
const toBEHex = (n) => n.toString(16).padStart(64, '0');
|
||||||
|
|
||||||
|
function hexToNumber(hex) {
|
||||||
|
if (typeof hex !== 'string') {
|
||||||
|
throw new TypeError('hexToNumber: expected string, got ' + typeof hex);
|
||||||
|
}
|
||||||
|
// Big Endian
|
||||||
|
return BigInt(`0x${hex}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
should('secp256k1.getPublicKey()', () => {
|
||||||
|
const data = privatesTxt
|
||||||
|
.split('\n')
|
||||||
|
.filter((line) => line)
|
||||||
|
.map((line) => line.split(':'));
|
||||||
|
for (let [priv, x, y] of data) {
|
||||||
|
const point = secp.Point.fromPrivateKey(BigInt(priv));
|
||||||
|
deepStrictEqual(toBEHex(point.x), x);
|
||||||
|
deepStrictEqual(toBEHex(point.y), y);
|
||||||
|
|
||||||
|
const point2 = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv))));
|
||||||
|
deepStrictEqual(toBEHex(point2.x), x);
|
||||||
|
deepStrictEqual(toBEHex(point2.y), y);
|
||||||
|
|
||||||
|
const point3 = secp.Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv)))));
|
||||||
|
deepStrictEqual(toBEHex(point3.x), x);
|
||||||
|
deepStrictEqual(toBEHex(point3.y), y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.getPublicKey() rejects invalid keys', () => {
|
||||||
|
// for (const item of INVALID_ITEMS) {
|
||||||
|
// throws(() => secp.getPublicKey(item));
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
should('secp256k1.precompute', () => {
|
||||||
|
secp.utils.precompute(4);
|
||||||
|
const data = privatesTxt
|
||||||
|
.split('\n')
|
||||||
|
.filter((line) => line)
|
||||||
|
.map((line) => line.split(':'));
|
||||||
|
for (let [priv, x, y] of data) {
|
||||||
|
const point = secp.Point.fromPrivateKey(BigInt(priv));
|
||||||
|
deepStrictEqual(toBEHex(point.x), x);
|
||||||
|
deepStrictEqual(toBEHex(point.y), y);
|
||||||
|
|
||||||
|
const point2 = secp.Point.fromHex(secp.getPublicKey(toBEHex(BigInt(priv))));
|
||||||
|
deepStrictEqual(toBEHex(point2.x), x);
|
||||||
|
deepStrictEqual(toBEHex(point2.y), y);
|
||||||
|
|
||||||
|
const point3 = secp.Point.fromHex(secp.getPublicKey(hexToBytes(toBEHex(BigInt(priv)))));
|
||||||
|
deepStrictEqual(toBEHex(point3.x), x);
|
||||||
|
deepStrictEqual(toBEHex(point3.y), y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point.isValidPoint()', () => {
|
||||||
|
for (const vector of points.valid.isPoint) {
|
||||||
|
const { P, expected } = vector;
|
||||||
|
if (expected) {
|
||||||
|
secp.Point.fromHex(P);
|
||||||
|
} else {
|
||||||
|
throws(() => secp.Point.fromHex(P));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point.fromPrivateKey()', () => {
|
||||||
|
for (const vector of points.valid.pointFromScalar) {
|
||||||
|
const { d, expected } = vector;
|
||||||
|
let p = secp.Point.fromPrivateKey(d);
|
||||||
|
deepStrictEqual(p.toHex(true), expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point#toHex(compressed)', () => {
|
||||||
|
for (const vector of points.valid.pointCompress) {
|
||||||
|
const { P, compress, expected } = vector;
|
||||||
|
let p = secp.Point.fromHex(P);
|
||||||
|
deepStrictEqual(p.toHex(compress), expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point#toHex() roundtrip (failed case)', () => {
|
||||||
|
const point1 =
|
||||||
|
secp.Point.fromPrivateKey(
|
||||||
|
88572218780422190464634044548753414301110513745532121983949500266768436236425n
|
||||||
|
);
|
||||||
|
// const hex = point1.toHex(true);
|
||||||
|
// deepStrictEqual(secp.Point.fromHex(hex).toHex(true), hex);
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point#toHex() roundtrip', () => {
|
||||||
|
fc.assert(
|
||||||
|
fc.property(FC_BIGINT, (x) => {
|
||||||
|
const point1 = secp.Point.fromPrivateKey(x);
|
||||||
|
const hex = point1.toHex(true);
|
||||||
|
deepStrictEqual(secp.Point.fromHex(hex).toHex(true), hex);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point#add(other)', () => {
|
||||||
|
for (const vector of points.valid.pointAdd) {
|
||||||
|
const { P, Q, expected } = vector;
|
||||||
|
let p = secp.Point.fromHex(P);
|
||||||
|
let q = secp.Point.fromHex(Q);
|
||||||
|
if (expected) {
|
||||||
|
deepStrictEqual(p.add(q).toHex(true), expected);
|
||||||
|
} else {
|
||||||
|
if (!p.equals(q.negate())) {
|
||||||
|
throws(() => p.add(q).toHex(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Point#multiply(privateKey)', () => {
|
||||||
|
for (const vector of points.valid.pointMultiply) {
|
||||||
|
const { P, d, expected } = vector;
|
||||||
|
const p = secp.Point.fromHex(P);
|
||||||
|
if (expected) {
|
||||||
|
deepStrictEqual(p.multiply(hexToNumber(d)).toHex(true), expected);
|
||||||
|
} else {
|
||||||
|
throws(() => {
|
||||||
|
p.multiply(hexToNumber(d)).toHex(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const vector of points.invalid.pointMultiply) {
|
||||||
|
const { P, d } = vector;
|
||||||
|
if (hexToNumber(d) < secp.CURVE.n) {
|
||||||
|
throws(() => {
|
||||||
|
const p = secp.Point.fromHex(P);
|
||||||
|
p.multiply(hexToNumber(d)).toHex(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const num of [0n, 0, -1n, -1, 1.1]) {
|
||||||
|
throws(() => secp.Point.BASE.multiply(num));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// multiply() should equal multiplyUnsafe()
|
||||||
|
// should('JacobianPoint#multiplyUnsafe', () => {
|
||||||
|
// const p0 = new secp.JacobianPoint(
|
||||||
|
// 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
||||||
|
// 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
||||||
|
// 1n
|
||||||
|
// );
|
||||||
|
// const z = 106011723082030650010038151861333186846790370053628296836951575624442507889495n;
|
||||||
|
// console.log(p0.multiply(z));
|
||||||
|
// console.log(secp.JacobianPoint.normalizeZ([p0.multiplyUnsafe(z)])[0])
|
||||||
|
// });
|
||||||
|
|
||||||
|
should('secp256k1.Signature.fromCompactHex() roundtrip', () => {
|
||||||
|
fc.assert(
|
||||||
|
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
|
||||||
|
const sig = new secp.Signature(r, s);
|
||||||
|
deepStrictEqual(secp.Signature.fromCompact(sig.toCompactHex()), sig);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.Signature.fromDERHex() roundtrip', () => {
|
||||||
|
fc.assert(
|
||||||
|
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
|
||||||
|
const sig = new secp.Signature(r, s);
|
||||||
|
deepStrictEqual(secp.Signature.fromDER(sig.toDERHex()), sig);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.sign()/should create deterministic signatures with RFC 6979', async () => {
|
||||||
|
for (const vector of ecdsa.valid) {
|
||||||
|
let usig = await secp.sign(vector.m, vector.d);
|
||||||
|
let sig = (usig.toCompactHex());
|
||||||
|
const vsig = vector.signature;
|
||||||
|
deepStrictEqual(sig.slice(0, 64), vsig.slice(0, 64));
|
||||||
|
deepStrictEqual(sig.slice(64, 128), vsig.slice(64, 128));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should(
|
||||||
|
'secp256k1.sign()/should not create invalid deterministic signatures with RFC 6979',
|
||||||
|
async () => {
|
||||||
|
for (const vector of ecdsa.invalid.sign) {
|
||||||
|
throws(() => {
|
||||||
|
return secp.sign(vector.m, vector.d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
should('secp256k1.sign()/edge cases', () => {
|
||||||
|
// @ts-ignore
|
||||||
|
rejects(async () => await secp.sign());
|
||||||
|
// @ts-ignore
|
||||||
|
rejects(async () => await secp.sign(''));
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.sign()/should create correct DER encoding against libsecp256k1', async () => {
|
||||||
|
const CASES = [
|
||||||
|
[
|
||||||
|
'd1a9dc8ed4e46a6a3e5e594615ca351d7d7ef44df1e4c94c1802f3592183794b',
|
||||||
|
'304402203de2559fccb00c148574997f660e4d6f40605acc71267ee38101abf15ff467af02200950abdf40628fd13f547792ba2fc544681a485f2fdafb5c3b909a4df7350e6b',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'5f97983254982546d3976d905c6165033976ee449d300d0e382099fa74deaf82',
|
||||||
|
'3045022100c046d9ff0bd2845b9aa9dff9f997ecebb31e52349f80fe5a5a869747d31dcb88022011f72be2a6d48fe716b825e4117747b397783df26914a58139c3f4c5cbb0e66c',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'0d7017a96b97cd9be21cf28aada639827b2814a654a478c81945857196187808',
|
||||||
|
'3045022100d18990bba7832bb283e3ecf8700b67beb39acc73f4200ed1c331247c46edccc602202e5c8bbfe47ae159512c583b30a3fa86575cddc62527a03de7756517ae4c6c73',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
const privKey = hexToBytes('0101010101010101010101010101010101010101010101010101010101010101');
|
||||||
|
for (let [msg, exp] of CASES) {
|
||||||
|
const res = await 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.sign()/sign ecdsa extraData', async () => {
|
||||||
|
const ent1 = '0000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
const ent2 = '0000000000000000000000000000000000000000000000000000000000000001';
|
||||||
|
const ent3 = '6e723d3fd94ed5d2b6bdd4f123364b0f3ca52af829988a63f8afe91d29db1c33';
|
||||||
|
const ent4 = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
|
||||||
|
const ent5 = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
|
||||||
|
|
||||||
|
for (const e of ecdsa.extraEntropy) {
|
||||||
|
const sign = async (extraEntropy) => {
|
||||||
|
const s = secp.sign(e.m, e.d, {extraEntropy }).toCompactHex();
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
deepStrictEqual(await sign(), e.signature);
|
||||||
|
deepStrictEqual(await sign(ent1), e.extraEntropy0);
|
||||||
|
deepStrictEqual(await sign(ent2), e.extraEntropy1);
|
||||||
|
deepStrictEqual(await sign(ent3), e.extraEntropyRand);
|
||||||
|
deepStrictEqual(await sign(ent4), e.extraEntropyN);
|
||||||
|
deepStrictEqual(await sign(ent5), e.extraEntropyMax);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.verify()/should verify signature', async () => {
|
||||||
|
const MSG = '01'.repeat(32);
|
||||||
|
const PRIV_KEY = 0x2n;
|
||||||
|
const signature = await secp.sign(MSG, PRIV_KEY);
|
||||||
|
const publicKey = secp.getPublicKey(PRIV_KEY);
|
||||||
|
deepStrictEqual(publicKey.length, 65);
|
||||||
|
deepStrictEqual(secp.verify(signature, MSG, publicKey), true);
|
||||||
|
});
|
||||||
|
should('secp256k1.verify()/should not verify signature with wrong public key', async () => {
|
||||||
|
const MSG = '01'.repeat(32);
|
||||||
|
const PRIV_KEY = 0x2n;
|
||||||
|
const WRONG_PRIV_KEY = 0x22n;
|
||||||
|
const signature = await secp.sign(MSG, PRIV_KEY);
|
||||||
|
const publicKey = secp.Point.fromPrivateKey(WRONG_PRIV_KEY).toHex();
|
||||||
|
deepStrictEqual(publicKey.length, 130);
|
||||||
|
deepStrictEqual(secp.verify(signature, MSG, publicKey), false);
|
||||||
|
});
|
||||||
|
should('secp256k1.verify()/should not verify signature with wrong hash', async () => {
|
||||||
|
const MSG = '01'.repeat(32);
|
||||||
|
const PRIV_KEY = 0x2n;
|
||||||
|
const WRONG_MSG = '11'.repeat(32);
|
||||||
|
const signature = await secp.sign(MSG, PRIV_KEY);
|
||||||
|
const publicKey = secp.getPublicKey(PRIV_KEY);
|
||||||
|
deepStrictEqual(publicKey.length, 65);
|
||||||
|
deepStrictEqual(secp.verify(signature, WRONG_MSG, publicKey), false);
|
||||||
|
});
|
||||||
|
should('secp256k1.verify()/should verify random signatures', async () =>
|
||||||
|
fc.assert(
|
||||||
|
fc.asyncProperty(
|
||||||
|
FC_BIGINT,
|
||||||
|
fc.hexaString({ minLength: 64, maxLength: 64 }),
|
||||||
|
async (privKey, msg) => {
|
||||||
|
const pub = secp.getPublicKey(privKey);
|
||||||
|
const sig = await secp.sign(msg, privKey);
|
||||||
|
deepStrictEqual(secp.verify(sig, msg, pub), true);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
should('secp256k1.verify()/should not verify signature with invalid r/s', () => {
|
||||||
|
const msg = new Uint8Array([
|
||||||
|
0xbb, 0x5a, 0x52, 0xf4, 0x2f, 0x9c, 0x92, 0x61, 0xed, 0x43, 0x61, 0xf5, 0x94, 0x22, 0xa1, 0xe3,
|
||||||
|
0x00, 0x36, 0xe7, 0xc3, 0x2b, 0x27, 0x0c, 0x88, 0x07, 0xa4, 0x19, 0xfe, 0xca, 0x60, 0x50, 0x23,
|
||||||
|
]);
|
||||||
|
const x = 100260381870027870612475458630405506840396644859280795015145920502443964769584n;
|
||||||
|
const y = 41096923727651821103518389640356553930186852801619204169823347832429067794568n;
|
||||||
|
const r = 1n;
|
||||||
|
const s = 115792089237316195423570985008687907852837564279074904382605163141518162728904n;
|
||||||
|
|
||||||
|
const pub = new secp.Point(x, y);
|
||||||
|
const signature = new secp.Signature(2n, 2n);
|
||||||
|
// @ts-ignore
|
||||||
|
signature.r = r;
|
||||||
|
// @ts-ignore
|
||||||
|
signature.s = s;
|
||||||
|
|
||||||
|
const verified = secp.verify(signature, msg, pub);
|
||||||
|
// Verifies, but it shouldn't, because signature S > curve order
|
||||||
|
deepStrictEqual(verified, false);
|
||||||
|
});
|
||||||
|
should('secp256k1.verify()/should not verify msg = curve order', async () => {
|
||||||
|
const msg = 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141';
|
||||||
|
const x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n;
|
||||||
|
const y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n;
|
||||||
|
const r = 104546003225722045112039007203142344920046999340768276760147352389092131869133n;
|
||||||
|
const s = 96900796730960181123786672629079577025401317267213807243199432755332205217369n;
|
||||||
|
const pub = new secp.Point(x, y);
|
||||||
|
const sig = new secp.Signature(r, s);
|
||||||
|
deepStrictEqual(secp.verify(sig, msg, pub), false);
|
||||||
|
});
|
||||||
|
should('secp256k1.verify()/should verify non-strict msg bb5a...', async () => {
|
||||||
|
const msg = 'bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023';
|
||||||
|
const x = 3252872872578928810725465493269682203671229454553002637820453004368632726370n;
|
||||||
|
const y = 17482644437196207387910659778872952193236850502325156318830589868678978890912n;
|
||||||
|
const r = 432420386565659656852420866390673177323n;
|
||||||
|
const s = 115792089237316195423570985008687907852837564279074904382605163141518161494334n;
|
||||||
|
const pub = new secp.Point(x, y);
|
||||||
|
const sig = new secp.Signature(r, s);
|
||||||
|
deepStrictEqual(secp.verify(sig, msg, pub, { strict: false }), true);
|
||||||
|
});
|
||||||
|
should(
|
||||||
|
'secp256k1.verify()/should not verify invalid deterministic signatures with RFC 6979',
|
||||||
|
() => {
|
||||||
|
for (const vector of ecdsa.invalid.verify) {
|
||||||
|
const res = secp.verify(vector.signature, vector.m, vector.Q);
|
||||||
|
deepStrictEqual(res, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// describe('schnorr', () => {
|
||||||
|
// // index,secret key,public key,aux_rand,message,signature,verification result,comment
|
||||||
|
// const vectors = schCsv
|
||||||
|
// .split('\n')
|
||||||
|
// .map((line: string) => line.split(','))
|
||||||
|
// .slice(1, -1);
|
||||||
|
// for (let vec of vectors) {
|
||||||
|
// const [index, sec, pub, rnd, msg, expSig, passes, comment] = vec;
|
||||||
|
// it(`should sign with Schnorr scheme vector ${index}`, async () => {
|
||||||
|
// if (sec) {
|
||||||
|
// expect(hex(secp.schnorr.getPublicKey(sec))).toBe(pub.toLowerCase());
|
||||||
|
// const sig = await secp.schnorr.sign(msg, sec, rnd);
|
||||||
|
// const sigS = secp.schnorr.signSync(msg, sec, rnd);
|
||||||
|
// expect(hex(sig)).toBe(expSig.toLowerCase());
|
||||||
|
// expect(hex(sigS)).toBe(expSig.toLowerCase());
|
||||||
|
// expect(await secp.schnorr.verify(sigS, msg, pub)).toBe(true);
|
||||||
|
// expect(secp.schnorr.verifySync(sig, msg, pub)).toBe(true);
|
||||||
|
// } else {
|
||||||
|
// const passed = await secp.schnorr.verify(expSig, msg, pub);
|
||||||
|
// const passedS = secp.schnorr.verifySync(expSig, msg, pub);
|
||||||
|
// if (passes === 'TRUE') {
|
||||||
|
// expect(passed).toBeTruthy();
|
||||||
|
// expect(passedS).toBeTruthy();
|
||||||
|
// } else {
|
||||||
|
// expect(passed).toBeFalsy();
|
||||||
|
// expect(passedS).toBeFalsy();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
should('secp256k1.recoverPublicKey()/should recover public key from recovery bit', async () => {
|
||||||
|
const message = '00000000000000000000000000000000000000000000000000000000deadbeef';
|
||||||
|
const privateKey = 123456789n;
|
||||||
|
const publicKey = secp.Point.fromHex(secp.getPublicKey(privateKey)).toHex(false);
|
||||||
|
const sig = await secp.sign(message, privateKey);
|
||||||
|
const recoveredPubkey = sig.recoverPublicKey(message);
|
||||||
|
// const recoveredPubkey = secp.recoverPublicKey(message, signature, recovery);
|
||||||
|
deepStrictEqual(recoveredPubkey !== null, true);
|
||||||
|
deepStrictEqual((recoveredPubkey).toHex(), publicKey);
|
||||||
|
deepStrictEqual(secp.verify(sig, message, publicKey), true);
|
||||||
|
});
|
||||||
|
should('secp256k1.recoverPublicKey()/should not recover zero points', () => {
|
||||||
|
const msgHash = '6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9';
|
||||||
|
const sig =
|
||||||
|
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9';
|
||||||
|
const recovery = 0;
|
||||||
|
throws(() => secp.recoverPublicKey(msgHash, sig, recovery));
|
||||||
|
});
|
||||||
|
should('secp256k1.recoverPublicKey()/should handle all-zeros msghash', async () => {
|
||||||
|
const privKey = secp.utils.randomPrivateKey();
|
||||||
|
const pub = secp.getPublicKey(privKey);
|
||||||
|
const zeros = '0000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
const sig = await secp.sign(zeros, privKey, { recovered: true });
|
||||||
|
const recoveredKey = sig.recoverPublicKey(zeros);
|
||||||
|
deepStrictEqual(recoveredKey.toRawBytes(), pub);
|
||||||
|
});
|
||||||
|
should('secp256k1.recoverPublicKey()/should handle RFC 6979 vectors', async () => {
|
||||||
|
for (const vector of ecdsa.valid) {
|
||||||
|
if (secp.utils.mod(hexToNumber(vector.m), secp.CURVE.n) === 0n) continue;
|
||||||
|
let usig = secp.sign(vector.m, vector.d);
|
||||||
|
let sig = (usig).toDERHex();
|
||||||
|
const vpub = secp.getPublicKey(vector.d);
|
||||||
|
const recovered = usig.recoverPublicKey(vector.m);
|
||||||
|
deepStrictEqual((recovered).toHex(), hex(vpub));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Real implementation.
|
||||||
|
function derToPub(der) {
|
||||||
|
return der.slice(46);
|
||||||
|
}
|
||||||
|
should('secp256k1.getSharedSecret()/should produce correct results', () => {
|
||||||
|
// TODO: Once der is there, run all tests.
|
||||||
|
for (const vector of ecdh.testGroups[0].tests.slice(0, 230)) {
|
||||||
|
if (vector.result === 'invalid' || vector.private.length !== 64) {
|
||||||
|
// We support eth-like hexes
|
||||||
|
if (vector.private.length < 64) continue;
|
||||||
|
throws(() => {
|
||||||
|
secp.getSharedSecret(vector.private, derToPub(vector.public), true);
|
||||||
|
});
|
||||||
|
} else if (vector.result === 'valid') {
|
||||||
|
const res = secp.getSharedSecret(vector.private, derToPub(vector.public), true);
|
||||||
|
deepStrictEqual(hex(res.slice(1)), `${vector.shared}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.getSharedSecret()/priv/pub order matters', () => {
|
||||||
|
for (const vector of ecdh.testGroups[0].tests.slice(0, 100)) {
|
||||||
|
if (vector.result === 'valid') {
|
||||||
|
let priv = vector.private;
|
||||||
|
priv = priv.length === 66 ? priv.slice(2) : priv;
|
||||||
|
throws(() => secp.getSharedSecret(derToPub(vector.public), priv, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.getSharedSecret()/rejects invalid keys', () => {
|
||||||
|
throws(() => secp.getSharedSecret('01', '02'));
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.utils.isValidPrivateKey()', () => {
|
||||||
|
for (const vector of privates.valid.isPrivate) {
|
||||||
|
const { d, expected } = vector;
|
||||||
|
deepStrictEqual(secp.utils.isValidPrivateKey(d), expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const normal = secp.utils._normalizePrivateKey;
|
||||||
|
const tweakUtils = {
|
||||||
|
privateAdd: (privateKey, tweak) => {
|
||||||
|
const p = normal(privateKey);
|
||||||
|
const t = normal(tweak);
|
||||||
|
return secp.utils._bigintToBytes(secp.utils.mod(p + t, secp.CURVE.n));
|
||||||
|
},
|
||||||
|
|
||||||
|
privateNegate: (privateKey) => {
|
||||||
|
const p = normal(privateKey);
|
||||||
|
return secp.utils._bigintToBytes(secp.CURVE.n - p);
|
||||||
|
},
|
||||||
|
|
||||||
|
pointAddScalar: (p, tweak, isCompressed) => {
|
||||||
|
const P = secp.Point.fromHex(p);
|
||||||
|
const t = normal(tweak);
|
||||||
|
const Q = secp.Point.BASE.multiplyAndAddUnsafe(P, t, 1n);
|
||||||
|
if (!Q) throw new Error('Tweaked point at infinity');
|
||||||
|
return Q.toRawBytes(isCompressed);
|
||||||
|
},
|
||||||
|
|
||||||
|
pointMultiply: (p, tweak, isCompressed) => {
|
||||||
|
const P = secp.Point.fromHex(p);
|
||||||
|
const h = typeof tweak === 'string' ? tweak : bytesToHex(tweak);
|
||||||
|
const t = BigInt(`0x${h}`);
|
||||||
|
return P.multiply(t).toRawBytes(isCompressed);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
should('secp256k1.privateAdd()', () => {
|
||||||
|
for (const vector of privates.valid.add) {
|
||||||
|
const { a, b, expected } = vector;
|
||||||
|
deepStrictEqual(bytesToHex(tweakUtils.privateAdd(a, b)), expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.privateNegate()', () => {
|
||||||
|
for (const vector of privates.valid.negate) {
|
||||||
|
const { a, expected } = vector;
|
||||||
|
deepStrictEqual(bytesToHex(tweakUtils.privateNegate(a)), expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.pointAddScalar() invalid', () => {
|
||||||
|
for (const vector of points.invalid.pointAddScalar) {
|
||||||
|
const { P, d, exception } = vector;
|
||||||
|
throws(() => tweakUtils.pointAddScalar(P, d));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.pointMultiply()', () => {
|
||||||
|
for (const vector of points.valid.pointMultiply) {
|
||||||
|
const { P, d, expected } = vector;
|
||||||
|
deepStrictEqual(bytesToHex(tweakUtils.pointMultiply(P, d, true)), expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
should('secp256k1.pointMultiply() invalid', () => {
|
||||||
|
for (const vector of points.invalid.pointMultiply) {
|
||||||
|
const { P, d, exception } = vector;
|
||||||
|
throws(() => tweakUtils.pointMultiply(P, d));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should('secp256k1.wychenproof vectors', () => {
|
||||||
|
for (let group of wp.testGroups) {
|
||||||
|
const pubKey = secp.Point.fromHex(group.key.uncompressed);
|
||||||
|
for (let test of group.tests) {
|
||||||
|
const m = secp.CURVE.hash(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()) {
|
||||||
|
deepStrictEqual(verified, false);
|
||||||
|
} else {
|
||||||
|
deepStrictEqual(verified, true);
|
||||||
|
}
|
||||||
|
} else if (test.result === 'invalid') {
|
||||||
|
let failed = false;
|
||||||
|
try {
|
||||||
|
const verified = secp.verify(test.sig, m, pubKey);
|
||||||
|
if (!verified) failed = true;
|
||||||
|
} catch (error) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
deepStrictEqual(failed, true);
|
||||||
|
} else {
|
||||||
|
deepStrictEqual(false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
should.run();
|
200
curve-definitions/test/starknet/basic.test.js
Normal file
200
curve-definitions/test/starknet/basic.test.js
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
|
import { should } from 'micro-should';
|
||||||
|
import * as starknet from '../../lib/starknet.js';
|
||||||
|
import { default as issue2 } from './fixtures/issue2.json' assert { type: 'json' };
|
||||||
|
|
||||||
|
should('Basic elliptic sanity check', () => {
|
||||||
|
const g1 = starknet.Point.BASE;
|
||||||
|
deepStrictEqual(
|
||||||
|
g1.x.toString(16),
|
||||||
|
'1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca'
|
||||||
|
);
|
||||||
|
deepStrictEqual(
|
||||||
|
g1.y.toString(16),
|
||||||
|
'5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f'
|
||||||
|
);
|
||||||
|
const g2 = g1.double();
|
||||||
|
deepStrictEqual(
|
||||||
|
g2.x.toString(16),
|
||||||
|
'759ca09377679ecd535a81e83039658bf40959283187c654c5416f439403cf5'
|
||||||
|
);
|
||||||
|
deepStrictEqual(
|
||||||
|
g2.y.toString(16),
|
||||||
|
'6f524a3400e7708d5c01a28598ad272e7455aa88778b19f93b562d7a9646c41'
|
||||||
|
);
|
||||||
|
const g3 = g2.add(g1);
|
||||||
|
deepStrictEqual(
|
||||||
|
g3.x.toString(16),
|
||||||
|
'411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20'
|
||||||
|
);
|
||||||
|
deepStrictEqual(
|
||||||
|
g3.y.toString(16),
|
||||||
|
'7e1b3ebac08924d2c26f409549191fcf94f3bf6f301ed3553e22dfb802f0686'
|
||||||
|
);
|
||||||
|
const g32 = g1.multiply(3);
|
||||||
|
deepStrictEqual(
|
||||||
|
g32.x.toString(16),
|
||||||
|
'411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20'
|
||||||
|
);
|
||||||
|
deepStrictEqual(
|
||||||
|
g32.y.toString(16),
|
||||||
|
'7e1b3ebac08924d2c26f409549191fcf94f3bf6f301ed3553e22dfb802f0686'
|
||||||
|
);
|
||||||
|
const minus1 = g1.multiply(starknet.CURVE.n - 1n);
|
||||||
|
deepStrictEqual(
|
||||||
|
minus1.x.toString(16),
|
||||||
|
'1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca'
|
||||||
|
);
|
||||||
|
deepStrictEqual(
|
||||||
|
minus1.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'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
import * as bip32 from '@scure/bip32';
|
||||||
|
import * as bip39 from '@scure/bip39';
|
||||||
|
|
||||||
|
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.Point.BASE;
|
||||||
|
const half = starknet.CURVE.n / 2n;
|
||||||
|
const last = starknet.CURVE.n;
|
||||||
|
const vectors = [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
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, _WINDOW_SIZE: undefined });
|
||||||
|
for (const v of vectors) {
|
||||||
|
const uncompressed = v.toHex();
|
||||||
|
const compressed = v.toHex(true);
|
||||||
|
const exp = fixPoint(v);
|
||||||
|
deepStrictEqual(fixPoint(starknet.Point.fromHex(uncompressed)), exp);
|
||||||
|
deepStrictEqual(fixPoint(starknet.Point.fromHex(compressed)), exp);
|
||||||
|
deepStrictEqual(starknet.Point.fromHex(compressed).toHex(), uncompressed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ESM is broken.
|
||||||
|
import url from 'url';
|
||||||
|
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
||||||
|
should.run();
|
||||||
|
}
|
57
curve-definitions/test/starknet/benchmark/index.js
Normal file
57
curve-definitions/test/starknet/benchmark/index.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import * as microStark from '../../../lib/starknet.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();
|
19
curve-definitions/test/starknet/benchmark/package.json
Normal file
19
curve-definitions/test/starknet/benchmark/package.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
1306
curve-definitions/test/starknet/fixtures/issue2.json
Normal file
1306
curve-definitions/test/starknet/fixtures/issue2.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
5
curve-definitions/test/starknet/index.test.js
Normal file
5
curve-definitions/test/starknet/index.test.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
import './basic.test.js';
|
||||||
|
import './starknet.test.js';
|
||||||
|
import './property.test.js';
|
||||||
|
|
51
curve-definitions/test/starknet/property.test.js
Normal file
51
curve-definitions/test/starknet/property.test.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
|
import { should } from 'micro-should';
|
||||||
|
import * as starknet from '../../lib/starknet.js';
|
||||||
|
import * as fc from 'fast-check';
|
||||||
|
|
||||||
|
const FC_BIGINT = fc.bigInt(1n + 1n, starknet.CURVE.n - 1n);
|
||||||
|
|
||||||
|
should('Point#toHex() roundtrip', () => {
|
||||||
|
fc.assert(
|
||||||
|
fc.property(FC_BIGINT, (x) => {
|
||||||
|
const point1 = starknet.Point.fromPrivateKey(x);
|
||||||
|
const hex = point1.toHex(true);
|
||||||
|
deepStrictEqual(starknet.Point.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.asyncProperty(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();
|
||||||
|
}
|
286
curve-definitions/test/starknet/starknet.test.js
Normal file
286
curve-definitions/test/starknet/starknet.test.js
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
|
import { 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/starknet.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' };
|
||||||
|
|
||||||
|
should('Starknet 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();
|
||||||
|
}
|
4545
curve-definitions/test/vectors/ecdh.json
Normal file
4545
curve-definitions/test/vectors/ecdh.json
Normal file
File diff suppressed because it is too large
Load Diff
10372
curve-definitions/test/vectors/ecdsa.json
Normal file
10372
curve-definitions/test/vectors/ecdsa.json
Normal file
File diff suppressed because it is too large
Load Diff
10838
curve-definitions/test/vectors/points.json
Normal file
10838
curve-definitions/test/vectors/points.json
Normal file
File diff suppressed because it is too large
Load Diff
1272
curve-definitions/test/vectors/points.txt
Normal file
1272
curve-definitions/test/vectors/points.txt
Normal file
File diff suppressed because it is too large
Load Diff
45
curve-definitions/test/vectors/privates-2.txt
Normal file
45
curve-definitions/test/vectors/privates-2.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
1:79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798:483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
|
||||||
|
2:c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5:1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a
|
||||||
|
3:f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9:388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672
|
||||||
|
4:e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13:51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922
|
||||||
|
5:2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4:d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6
|
||||||
|
6:fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556:ae12777aacfbb620f3be96017f45c560de80f0f6518fe4a03c870c36b075f297
|
||||||
|
7:5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc:6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da
|
||||||
|
8:2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01:5c4da8a741539949293d082a132d13b4c2e213d6ba5b7617b5da2cb76cbde904
|
||||||
|
9:acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe:cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37
|
||||||
|
10:a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7:893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7
|
||||||
|
11:774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb:d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b
|
||||||
|
12:d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a:a9f34ffdc815e0d7a8b64537e17bd81579238c5dd9a86d526b051b13f4062327
|
||||||
|
13:f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8:0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81
|
||||||
|
14:499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4:cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b
|
||||||
|
15:d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e:581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58
|
||||||
|
16:e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a:f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821
|
||||||
|
17:defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34:4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77
|
||||||
|
18:5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc:c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58
|
||||||
|
19:2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c:85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a
|
||||||
|
20:4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97:12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a
|
||||||
|
112233445566778899:a90cc3d3f3e146daadfc74ca1372207cb4b725ae708cef713a98edd73d99ef29:5a79d6b289610c68bc3b47f3d72f9788a26a06868b4d8e433e1e2ad76fb7dc76
|
||||||
|
112233445566778899112233445566778899:e5a2636bcfd412ebf36ec45b19bfb68a1bc5f8632e678132b885f7df99c5e9b3:736c1ce161ae27b405cafd2a7520370153c2c861ac51d6c1d5985d9606b45f39
|
||||||
|
28948022309329048855892746252171976963209391069768726095651290785379540373584:a6b594b38fb3e77c6edf78161fade2041f4e09fd8497db776e546c41567feb3c:71444009192228730cd8237a490feba2afe3d27d7cc1136bc97e439d13330d55
|
||||||
|
57896044618658097711785492504343953926418782139537452191302581570759080747168:00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63:3f3979bf72ae8202983dc989aec7f2ff2ed91bdd69ce02fc0700ca100e59ddf3
|
||||||
|
86844066927987146567678238756515930889628173209306178286953872356138621120752:e24ce4beee294aa6350faa67512b99d388693ae4e7f53d19882a6ea169fc1ce1:8b71e83545fc2b5872589f99d948c03108d36797c4de363ebd3ff6a9e1a95b10
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494317:4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97:ed45d9234ef13e9da259e05ef57bb3989e9d6b7d8e269698bafd77106dcc1ff5
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494318:2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c:7a17643fc86ba26c4cbcf7c4a5e379ece5fe09f3afd9689c4a8f37aa1a3f60b5
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494319:5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc:3ec93e23f34146cf161d67fbca76cae27e271f438c951d5e0ae6d1a074f9ded7
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494320:defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34:bdee54f96b9cae9716684f152d56c251312e0b5fb56a3f09304e660861a910b8
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494321:e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a:081caf8c661a6a6d624660cb0a86c8efed6976e1bb2dc0f41e0cd330969e940e
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494322:d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e:a7e1d78d57938d597c7bd13dd733921015bf50d427692c5a3afb235f095d90d7
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494323:499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4:353d093b4ab17aae6f0fbb1b584c2b9bb9bd863d85c06a4339a0bf2afc5ebcd4
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494324:f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8:f54f6fd17277f5768a7ded149a3250b8c5e5f925ade056e0d64a34ac24fc0eae
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494325:d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a:560cb00237ea1f285749bac81e8427ea86dc73a2265792ad94fae4eb0bf9d908
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494326:774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb:267b5fcd1494a1e6fdbc22a928484c9ac8d24e1d20062957cfe28b3536ac3614
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494327:a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7:76c545bdabe643d85c4938196c5db3969086b3d127885ea6c3411ac3fc8c9358
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494328:acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe:33cc76de4f5826029bc7f68e89c49e165227775bc8a071f0fa33d9d439b05ff8
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494329:2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01:a3b25758beac66b6d6c2f7d5ecd2ec4b3d1dec2945a489e84a25d3479342132b
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494330:5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc:951435bf45daa69f5ce8729279e5ab2457ec2f47ec02184a5af7d9d6f78d9755
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494331:fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556:51ed8885530449df0c4169fe80ba3a9f217f0f09ae701b5fc378f3c84f8a0998
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494332:2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4:2753ddd9c91a1c292b24562259363bd90877d8e454f297bf235782c459539959
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494333:e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13:ae1266c15f2baa48a9bd1df6715aebb7269851cc404201bf30168422b88c630d
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494334:f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9:c77084f09cd217ebf01cc819d5c80ca99aff5666cb3ddce4934602897b4715bd
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494335:c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5:e51e970159c23cc65c3a7be6b99315110809cd9acd992f1edc9bce55af301705
|
||||||
|
115792089237316195423570985008687907852837564279074904382605163141518161494336:79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798:b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777
|
173423
curve-definitions/test/vectors/privates.json
Normal file
173423
curve-definitions/test/vectors/privates.json
Normal file
File diff suppressed because it is too large
Load Diff
72
curve-definitions/test/vectors/rfc6979.json
Normal file
72
curve-definitions/test/vectors/rfc6979.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
16
curve-definitions/test/vectors/schnorr.csv
Normal file
16
curve-definitions/test/vectors/schnorr.csv
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
index,secret key,public key,aux_rand,message,signature,verification result,comment
|
||||||
|
0,0000000000000000000000000000000000000000000000000000000000000003,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9,0000000000000000000000000000000000000000000000000000000000000000,0000000000000000000000000000000000000000000000000000000000000000,E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0,TRUE,
|
||||||
|
1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,0000000000000000000000000000000000000000000000000000000000000001,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A,TRUE,
|
||||||
|
2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906,7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7,TRUE,
|
||||||
|
3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3,TRUE,test fails if msg is reduced modulo p or n
|
||||||
|
4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4,TRUE,
|
||||||
|
5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key not on the curve
|
||||||
|
6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2,FALSE,has_even_y(R) is false
|
||||||
|
7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD,FALSE,negated message
|
||||||
|
8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6,FALSE,negated s value
|
||||||
|
9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051,FALSE,sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 0
|
||||||
|
10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197,FALSE,sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 1
|
||||||
|
11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is not an X coordinate on the curve
|
||||||
|
12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is equal to field size
|
||||||
|
13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order
|
||||||
|
14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key is not a valid X coordinate because it exceeds the field size
|
|
4474
curve-definitions/test/vectors/wychenproof.json
Normal file
4474
curve-definitions/test/vectors/wychenproof.json
Normal file
File diff suppressed because it is too large
Load Diff
25
curve-definitions/tsconfig.json
Normal file
25
curve-definitions/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"target": "es2020",
|
||||||
|
"lib": [
|
||||||
|
"es2020",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"module": "es6",
|
||||||
|
"moduleResolution": "node16",
|
||||||
|
"outDir": "lib",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"preserveConstEnums": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src",
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"lib"
|
||||||
|
]
|
||||||
|
}
|
1
index.js
Normal file
1
index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
throw new Error('Incorrect usage. Import submodules instead');
|
7
lib/esm/package.json
Normal file
7
lib/esm/package.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"browser": {
|
||||||
|
"crypto": false,
|
||||||
|
"./crypto": "./esm/cryptoBrowser.js"
|
||||||
|
}
|
||||||
|
}
|
75
package.json
Normal file
75
package.json
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "@noble/curves",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Minimal, zero-dependency JS implementation of elliptic curve cryptography",
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"lib",
|
||||||
|
"lib/esm"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"bench": "node test/benchmark/index.js",
|
||||||
|
"build": "tsc && tsc -p tsconfig.esm.json",
|
||||||
|
"build:release": "rollup -c rollup.config.js",
|
||||||
|
"lint": "prettier --check 'src/**/*.{js,ts}' 'curve-definitions/src/**/*.{js,ts}'",
|
||||||
|
"format": "prettier --write 'src/**/*.{js,ts}' 'curve-definitions/src/**/*.{js,ts}'",
|
||||||
|
"test": "cd curve-definitions; node test/index.test.js"
|
||||||
|
},
|
||||||
|
"author": "Paul Miller (https://paulmillr.com)",
|
||||||
|
"homepage": "https://paulmillr.com/noble/",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/paulmillr/noble-curves.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-node-resolve": "13.3.0",
|
||||||
|
"micro-bmark": "0.2.0",
|
||||||
|
"micro-should": "0.2.0",
|
||||||
|
"prettier": "2.6.2",
|
||||||
|
"rollup": "2.75.5",
|
||||||
|
"typescript": "4.7.3"
|
||||||
|
},
|
||||||
|
"main": "index.js",
|
||||||
|
"exports": {
|
||||||
|
"./modular": {
|
||||||
|
"types": "./lib/modular.d.ts",
|
||||||
|
"import": "./lib/esm/modular.js",
|
||||||
|
"default": "./lib/modular.js"
|
||||||
|
},
|
||||||
|
"./shortw": {
|
||||||
|
"types": "./lib/shortw.d.ts",
|
||||||
|
"import": "./lib/esm/shortw.js",
|
||||||
|
"default": "./lib/shortw.js"
|
||||||
|
},
|
||||||
|
"./utils": {
|
||||||
|
"types": "./lib/utils.d.ts",
|
||||||
|
"import": "./lib/esm/utils.js",
|
||||||
|
"default": "./lib/utils.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"elliptic",
|
||||||
|
"curve",
|
||||||
|
"cryptography",
|
||||||
|
"hyperelliptic",
|
||||||
|
"p256",
|
||||||
|
"p384",
|
||||||
|
"p521",
|
||||||
|
"nist",
|
||||||
|
"weierstrass",
|
||||||
|
"edwards",
|
||||||
|
"montgomery",
|
||||||
|
"hashes",
|
||||||
|
"ecc",
|
||||||
|
"ecdsa",
|
||||||
|
"eddsa",
|
||||||
|
"schnorr"
|
||||||
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
146
src/modular.ts
Normal file
146
src/modular.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
const _0n = BigInt(0);
|
||||||
|
const _1n = BigInt(1);
|
||||||
|
const _2n = BigInt(2);
|
||||||
|
const _3n = BigInt(3);
|
||||||
|
const _4n = BigInt(4);
|
||||||
|
const _5n = BigInt(5);
|
||||||
|
const _8n = BigInt(8);
|
||||||
|
|
||||||
|
// Calculates a modulo b
|
||||||
|
export function mod(a: bigint, b: bigint): bigint {
|
||||||
|
const result = a % b;
|
||||||
|
return result >= _0n ? result : b + result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Efficiently exponentiate num to power and do modular division.
|
||||||
|
* @example
|
||||||
|
* powMod(2n, 6n, 11n) // 64n % 11n == 9n
|
||||||
|
*/
|
||||||
|
export function pow(num: bigint, power: bigint, modulo: bigint): bigint {
|
||||||
|
if (modulo <= _0n || power < _0n) throw new Error('Expected power/modulo > 0');
|
||||||
|
if (modulo === _1n) return _0n;
|
||||||
|
let res = _1n;
|
||||||
|
while (power > _0n) {
|
||||||
|
if (power & _1n) res = (res * num) % modulo;
|
||||||
|
num = (num * num) % modulo;
|
||||||
|
power >>= _1n;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
|
||||||
|
export function pow2(x: bigint, power: bigint, modulo: bigint): bigint {
|
||||||
|
let res = x;
|
||||||
|
while (power-- > _0n) {
|
||||||
|
res *= res;
|
||||||
|
res %= modulo;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inverses number over modulo
|
||||||
|
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/
|
||||||
|
let a = mod(number, modulo);
|
||||||
|
let b = modulo;
|
||||||
|
// prettier-ignore
|
||||||
|
let x = _0n, y = _1n, u = _1n, v = _0n;
|
||||||
|
while (a !== _0n) {
|
||||||
|
const q = b / a;
|
||||||
|
const r = b % a;
|
||||||
|
const m = x - u * q;
|
||||||
|
const n = y - v * q;
|
||||||
|
// prettier-ignore
|
||||||
|
b = a, a = r, x = u, y = v, u = m, v = n;
|
||||||
|
}
|
||||||
|
const gcd = b;
|
||||||
|
if (gcd !== _1n) throw new Error('invert: does not exist');
|
||||||
|
return mod(x, modulo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a list of numbers, efficiently inverts all of them.
|
||||||
|
* @param nums list of bigints
|
||||||
|
* @param p modulo
|
||||||
|
* @returns list of inverted bigints
|
||||||
|
* @example
|
||||||
|
* invertBatch([1n, 2n, 4n], 21n);
|
||||||
|
* // => [1n, 11n, 16n]
|
||||||
|
*/
|
||||||
|
export function invertBatch(nums: bigint[], modulo: bigint): bigint[] {
|
||||||
|
const scratch = new Array(nums.length);
|
||||||
|
// Walk from first to last, multiply them by each other MOD p
|
||||||
|
const lastMultiplied = nums.reduce((acc, num, i) => {
|
||||||
|
if (num === _0n) return acc;
|
||||||
|
scratch[i] = acc;
|
||||||
|
return mod(acc * num, modulo);
|
||||||
|
}, _1n);
|
||||||
|
// Invert last element
|
||||||
|
const inverted = invert(lastMultiplied, modulo);
|
||||||
|
// Walk from last to first, multiply them by inverted each other MOD p
|
||||||
|
nums.reduceRight((acc, num, i) => {
|
||||||
|
if (num === _0n) return acc;
|
||||||
|
scratch[i] = mod(acc * scratch[i], modulo);
|
||||||
|
return mod(acc * num, modulo);
|
||||||
|
}, inverted);
|
||||||
|
return scratch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates Legendre symbol: num^((P-1)/2)
|
||||||
|
export function legendre(num: bigint, fieldPrime: bigint): bigint {
|
||||||
|
return pow(num, (fieldPrime - _1n) / _2n, fieldPrime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates square root of a number in a finite field.
|
||||||
|
* Used to calculate y - the square root of y².
|
||||||
|
*/
|
||||||
|
export function sqrt(number: bigint, modulo: bigint): bigint {
|
||||||
|
const n = number;
|
||||||
|
const P = modulo;
|
||||||
|
const p1div4 = (P + _1n) / _4n;
|
||||||
|
|
||||||
|
// P = 3 (mod 4)
|
||||||
|
// sqrt n = n^((P+1)/4)
|
||||||
|
if (P % _4n === _3n) return pow(n, p1div4, P);
|
||||||
|
// P = 5 (mod 8)
|
||||||
|
if (P % _8n === _5n) {
|
||||||
|
const n2 = mod(n * _2n, P);
|
||||||
|
const v = pow(n2, (P - _5n) / _8n, P);
|
||||||
|
const nv = mod(n * v, P);
|
||||||
|
const i = mod(_2n * nv * v, P);
|
||||||
|
const r = mod(nv * (i - _1n), P);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other cases: Tonelli-Shanks algorithm
|
||||||
|
if (legendre(n, P) !== _1n) throw new Error('Cannot find square root');
|
||||||
|
let q: bigint, s: number, z: bigint;
|
||||||
|
for (q = P - _1n, s = 0; q % _2n === _0n; q /= _2n, s++);
|
||||||
|
if (s === 1) return pow(n, p1div4, P);
|
||||||
|
for (z = _2n; z < P && legendre(z, P) !== P - _1n; z++);
|
||||||
|
|
||||||
|
let c = pow(z, q, P);
|
||||||
|
let r = pow(n, (q + _1n) / _2n, P);
|
||||||
|
let t = pow(n, q, P);
|
||||||
|
|
||||||
|
let t2 = _0n;
|
||||||
|
while (mod(t - _1n, P) !== _0n) {
|
||||||
|
t2 = mod(t * t, P);
|
||||||
|
let i;
|
||||||
|
for (i = 1; i < s; i++) {
|
||||||
|
if (mod(t2 - _1n, P) === _0n) break;
|
||||||
|
t2 = mod(t2 * t2, P);
|
||||||
|
}
|
||||||
|
let b = pow(c, BigInt(1 << (s - i - 1)), P);
|
||||||
|
r = mod(r * b, P);
|
||||||
|
c = mod(b * b, P);
|
||||||
|
t = mod(t * c, P);
|
||||||
|
s = i;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
1262
src/shortw.ts
Normal file
1262
src/shortw.ts
Normal file
File diff suppressed because it is too large
Load Diff
69
src/utils.ts
Normal file
69
src/utils.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
// Convert between types
|
||||||
|
// ---------------------
|
||||||
|
|
||||||
|
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
|
||||||
|
export function bytesToHex(uint8a: Uint8Array): string {
|
||||||
|
if (!(uint8a instanceof Uint8Array)) throw new Error('Expected Uint8Array');
|
||||||
|
// pre-caching improves the speed 6x
|
||||||
|
let hex = '';
|
||||||
|
for (let i = 0; i < uint8a.length; i++) {
|
||||||
|
hex += hexes[uint8a[i]];
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function numberToHexUnpadded(num: number | bigint): string {
|
||||||
|
const hex = num.toString(16);
|
||||||
|
return hex.length & 1 ? `0${hex}` : hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hexToNumber(hex: string): bigint {
|
||||||
|
if (typeof hex !== 'string') {
|
||||||
|
throw new TypeError('hexToNumber: expected string, got ' + typeof hex);
|
||||||
|
}
|
||||||
|
// Big Endian
|
||||||
|
return BigInt(`0x${hex}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caching slows it down 2-3x
|
||||||
|
export function hexToBytes(hex: string): Uint8Array {
|
||||||
|
if (typeof hex !== 'string') {
|
||||||
|
throw new TypeError('hexToBytes: expected string, got ' + typeof hex);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Big Endian
|
||||||
|
export function bytesToNumber(bytes: Uint8Array): bigint {
|
||||||
|
return hexToNumber(bytesToHex(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureBytes(hex: string | Uint8Array): 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) : hexToBytes(hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copies several Uint8Arrays into one.
|
||||||
|
export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
|
||||||
|
if (!arrays.every((b) => b instanceof Uint8Array)) throw new Error('Uint8Array list expected');
|
||||||
|
if (arrays.length === 1) return arrays[0];
|
||||||
|
const length = arrays.reduce((a, arr) => a + arr.length, 0);
|
||||||
|
const result = new Uint8Array(length);
|
||||||
|
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
||||||
|
const arr = arrays[i];
|
||||||
|
result.set(arr, pad);
|
||||||
|
pad += arr.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
19
tsconfig.esm.json
Normal file
19
tsconfig.esm.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"outDir": "lib/esm",
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "es6",
|
||||||
|
"moduleResolution": "node16",
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@noble/hashes/crypto": [ "src/crypto" ]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"lib",
|
||||||
|
],
|
||||||
|
}
|
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "lib",
|
||||||
|
"target": "es2020",
|
||||||
|
"lib": ["es2020"], // Set explicitly to remove DOM
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"*.d.ts"
|
||||||
|
],
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user