Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5784ef23f6 | ||
|
|
ef55efe842 | ||
|
|
1cfd6a76ca | ||
|
|
89f81b2204 | ||
|
|
d77ac16f51 | ||
|
|
fe68da61f6 | ||
|
|
32c0841bed | ||
|
|
49a659b248 | ||
|
|
9d0a2e25dc | ||
|
|
7c461af2b2 | ||
|
|
4a8f447c8d | ||
|
|
4b2d31ce7f | ||
|
|
16115f27a6 | ||
|
|
0e0d0f530d | ||
|
|
fa5105aef2 | ||
|
|
11f1626ecc | ||
|
|
53ff287bf7 | ||
|
|
214c9aa553 | ||
|
|
ec2c3e1248 | ||
|
|
e64a9d654c | ||
|
|
088edd0fbb | ||
|
|
3e90930e9d | ||
|
|
b8b2e91f74 | ||
|
|
9ee694ae23 | ||
|
|
6bc4b35cf4 | ||
|
|
0163b63532 | ||
|
|
7e825520f1 | ||
|
|
d739297b2c | ||
|
|
285aa6375d | ||
|
|
8c77331ef2 | ||
|
|
669641e0a3 | ||
|
|
68dd57ed31 | ||
|
|
a9fdd6df9f | ||
|
|
d485d8b0e6 | ||
|
|
0fdd763dc7 | ||
|
|
586e2ad5fb | ||
|
|
ed81707bdc | ||
|
|
6d56b2d78e | ||
|
|
8397241a8f | ||
|
|
001d0cc24a | ||
|
|
ce9d165657 | ||
|
|
2902b0299a | ||
|
|
e1cb8549e8 | ||
|
|
26ebb5dcce | ||
|
|
8b2863aeac | ||
|
|
b1f50d9364 | ||
|
|
b81d74d3cb | ||
|
|
d5fe537159 | ||
|
|
cde1d5c488 | ||
|
|
3486bbf6b8 | ||
|
|
0d7a8296c5 | ||
|
|
0f1e7a5a43 | ||
|
|
3da48cf899 | ||
|
|
4ec46dd65d | ||
|
|
7073f63c6b | ||
|
|
80966cbd03 | ||
|
|
98ea15dca4 | ||
|
|
e1910e85ea | ||
|
|
4d311d7294 | ||
|
|
c36d90cae6 | ||
|
|
af5aa8424f | ||
|
|
67b99652fc | ||
|
|
c8d292976b | ||
|
|
daffaa2339 | ||
|
|
a462fc5779 |
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,7 +1,13 @@
|
|||||||
build/
|
build/
|
||||||
node_modules/
|
node_modules/
|
||||||
coverage/
|
coverage/
|
||||||
/lib/**/*.js
|
/*.js
|
||||||
/lib/**/*.ts
|
/*.ts
|
||||||
/lib/**/*.d.ts.map
|
/*.js.map
|
||||||
/curve-definitions/lib
|
/*.d.ts.map
|
||||||
|
/esm/*.js
|
||||||
|
/esm/*.ts
|
||||||
|
/esm/*.js.map
|
||||||
|
/esm/*.d.ts.map
|
||||||
|
/esm/abstract
|
||||||
|
/abstract/
|
||||||
|
|||||||
781
README.md
781
README.md
@@ -1,36 +1,35 @@
|
|||||||
# noble-curves
|
# noble-curves
|
||||||
|
|
||||||
Minimal, auditable JS implementation of elliptic curve cryptography.
|
[Audited](#security) & minimal JS implementation of elliptic curve cryptography.
|
||||||
|
|
||||||
|
- **noble** family, zero dependencies
|
||||||
- Short Weierstrass, Edwards, Montgomery curves
|
- Short Weierstrass, Edwards, Montgomery curves
|
||||||
- ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
|
- ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
|
||||||
- [hash to curve](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/)
|
- #️⃣ [hash to curve](#abstracthash-to-curve-hashing-strings-to-curve-points)
|
||||||
for encoding or hashing an arbitrary string to a point on an elliptic curve
|
for encoding or hashing an arbitrary string to an elliptic curve point
|
||||||
- [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
|
- 🧜♂️ [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
|
||||||
- 🏎 [Ultra-fast](#speed), hand-optimized for caveats of JS engines
|
- 🏎 [Ultra-fast](#speed), hand-optimized for caveats of JS engines
|
||||||
- 🔍 Unique tests ensure correctness. Wycheproof vectors included
|
- 🔍 Unique tests ensure correctness with Wycheproof vectors and [cryptofuzz](https://github.com/guidovranken/cryptofuzz) differential fuzzing
|
||||||
- 🔻 Tree-shaking-friendly: there is no entry point, which ensures small size of your app
|
- 🔻 Tree-shaking-friendly: there is no entry point, which ensures small size of your app
|
||||||
|
|
||||||
Package consists of two parts:
|
Package consists of two parts:
|
||||||
|
|
||||||
1. `abstract/` directory specifies zero-dependency EC algorithms
|
1. [Abstract](#abstract-api), zero-dependency EC algorithms
|
||||||
2. root directory utilizes one dependency `@noble/hashes` and provides ready-to-use:
|
2. [Implementations](#implementations), utilizing one dependency `@noble/hashes`, providing ready-to-use:
|
||||||
- NIST curves secp192r1/P192, secp224r1/P224, secp256r1/P256, secp384r1/P384, secp521r1/P521
|
- NIST curves secp256r1/P256, secp384r1/P384, secp521r1/P521
|
||||||
- SECG curve secp256k1
|
- SECG curve secp256k1
|
||||||
|
- ed25519/curve25519/x25519/ristretto255, edwards448/curve448/x448 [RFC7748](https://www.rfc-editor.org/rfc/rfc7748) / [RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [ZIP215](https://zips.z.cash/zip-0215) stuff
|
||||||
- pairing-friendly curves bls12-381, bn254
|
- pairing-friendly curves bls12-381, bn254
|
||||||
- ed25519/curve25519/x25519/ristretto, edwards448/curve448/x448 RFC7748 / RFC8032 / ZIP215 stuff
|
|
||||||
|
|
||||||
Curves incorporate work from previous noble packages
|
Check out [Upgrading](#upgrading) if you've previously used single-feature noble packages
|
||||||
([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
([secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519)).
|
||||||
[ed25519](https://github.com/paulmillr/noble-ed25519)),
|
See [Resources](#resources) for articles and real-world software that uses curves.
|
||||||
which had security audits and were developed from 2019 to 2022.
|
|
||||||
Check out [Upgrading](#upgrading) section if you've used them before.
|
|
||||||
|
|
||||||
### This library belongs to _noble_ crypto
|
### This library belongs to _noble_ crypto
|
||||||
|
|
||||||
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
|
||||||
|
|
||||||
- Protection against supply chain attacks
|
- No dependencies, protection against supply chain attacks
|
||||||
- Easily auditable TypeScript/JS code
|
- Easily auditable TypeScript/JS code
|
||||||
- Supported in all major browsers and stable node.js versions
|
- Supported in all major browsers and stable node.js versions
|
||||||
- All releases are signed with PGP keys
|
- All releases are signed with PGP keys
|
||||||
@@ -42,84 +41,255 @@ Check out [Upgrading](#upgrading) section if you've used them before.
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Use NPM in node.js / browser, or include single file from
|
Use NPM for browser / node.js:
|
||||||
[GitHub's releases page](https://github.com/paulmillr/noble-curves/releases):
|
|
||||||
|
|
||||||
> npm install @noble/curves
|
> npm install @noble/curves
|
||||||
|
|
||||||
The library does not have an entry point. It allows you to select specific primitives and drop everything else. If you only want to use secp256k1, just use the library with rollup or other bundlers. This is done to make your bundles tiny. All curves:
|
For [Deno](https://deno.land), use it with [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers). In browser, you could also include the single file from
|
||||||
|
[GitHub's releases page](https://github.com/paulmillr/noble-curves/releases).
|
||||||
|
|
||||||
|
The library is tree-shaking-friendly and does not expose root entry point as `import * from '@noble/curves'`.
|
||||||
|
Instead, you need to import specific primitives. This is done to ensure small size of your apps.
|
||||||
|
|
||||||
|
### Implementations
|
||||||
|
|
||||||
|
Each curve can be used in the following way:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { secp256k1 } from '@noble/curves/secp256k1';
|
import { secp256k1 } from '@noble/curves/secp256k1'; // ECMAScript Modules (ESM) and Common.js
|
||||||
|
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
|
||||||
|
const priv = secp256k1.utils.randomPrivateKey();
|
||||||
|
const pub = secp256k1.getPublicKey(priv);
|
||||||
|
const msg = new Uint8Array(32).fill(1);
|
||||||
|
const sig = secp256k1.sign(msg, priv);
|
||||||
|
secp256k1.verify(sig, msg, pub) === true;
|
||||||
|
|
||||||
|
const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236';
|
||||||
|
const pub2 = secp256k1.getPublicKey(privHex); // keys & other inputs can be Uint8Array-s or hex strings
|
||||||
|
```
|
||||||
|
|
||||||
|
All curves:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { secp256k1, schnorr } from '@noble/curves/secp256k1';
|
||||||
import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
|
import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519';
|
||||||
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
|
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
|
||||||
import { p256 } from '@noble/curves/p256';
|
import { p256 } from '@noble/curves/p256';
|
||||||
import { p384 } from '@noble/curves/p384';
|
import { p384 } from '@noble/curves/p384';
|
||||||
import { p521 } from '@noble/curves/p521';
|
import { p521 } from '@noble/curves/p521';
|
||||||
import { pallas, vesta } from '@noble/curves/pasta';
|
import { pallas, vesta } from '@noble/curves/pasta';
|
||||||
import * as stark from '@noble/curves/stark';
|
|
||||||
import { bls12_381 } from '@noble/curves/bls12-381';
|
import { bls12_381 } from '@noble/curves/bls12-381';
|
||||||
import { bn254 } from '@noble/curves/bn';
|
import { bn254 } from '@noble/curves/bn';
|
||||||
import { jubjub } from '@noble/curves/jubjub';
|
import { jubjub } from '@noble/curves/jubjub';
|
||||||
```
|
```
|
||||||
|
|
||||||
Every curve can be used in the following way:
|
Weierstrass curves feature recovering public keys from signatures and ECDH key agreement:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { secp256k1 } from '@noble/curves/secp256k1'; // Common.js and ECMAScript Modules (ESM)
|
// extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html
|
||||||
|
const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
|
||||||
const key = secp256k1.utils.randomPrivateKey();
|
sig.recoverPublicKey(msg) === pub; // public key recovery
|
||||||
const pub = secp256k1.getPublicKey(key);
|
|
||||||
const msg = new Uint8Array(32).fill(1);
|
|
||||||
const sig = secp256k1.sign(msg, key);
|
|
||||||
// weierstrass curves should use extraEntropy: https://moderncrypto.org/mail-archive/curves/2017/000925.html
|
|
||||||
const sigImprovedSecurity = secp256k1.sign(msg, key, { extraEntropy: true });
|
|
||||||
secp256k1.verify(sig, msg, pub) === true;
|
|
||||||
// secp, p*, pasta curves allow pub recovery
|
|
||||||
sig.recoverPublicKey(msg) === pub;
|
|
||||||
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
||||||
const shared = secp256k1.getSharedSecret(key, someonesPub);
|
const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH (elliptic curve diffie-hellman)
|
||||||
```
|
```
|
||||||
|
|
||||||
To define a custom curve, check out docs below.
|
secp256k1 has schnorr signature implementation which follows
|
||||||
|
[BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki):
|
||||||
|
|
||||||
## API
|
```ts
|
||||||
|
import { schnorr } from '@noble/curves/secp256k1';
|
||||||
|
const priv = schnorr.utils.randomPrivateKey();
|
||||||
|
const pub = schnorr.getPublicKey(priv);
|
||||||
|
const msg = new TextEncoder().encode('hello');
|
||||||
|
const sig = schnorr.sign(msg, priv);
|
||||||
|
const isValid = schnorr.verify(sig, msg, pub);
|
||||||
|
console.log(isValid);
|
||||||
|
```
|
||||||
|
|
||||||
- [Overview](#overview)
|
ed25519 module has ed25519ctx / ed25519ph variants,
|
||||||
|
x25519 ECDH and [ristretto255](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
|
||||||
|
It follows [ZIP215](https://zips.z.cash/zip-0215) and [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { ed25519 } from '@noble/curves/ed25519';
|
||||||
|
|
||||||
|
// Variants from RFC8032: with context, prehashed
|
||||||
|
import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519';
|
||||||
|
|
||||||
|
// ECDH using curve25519 aka x25519
|
||||||
|
import { x25519 } from '@noble/curves/ed25519';
|
||||||
|
const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4';
|
||||||
|
const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c';
|
||||||
|
x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases
|
||||||
|
x25519.getPublicKey(priv) === x25519.scalarMultBase(priv);
|
||||||
|
|
||||||
|
// hash-to-curve
|
||||||
|
import { hashToCurve, encodeToCurve } from '@noble/curves/ed25519';
|
||||||
|
|
||||||
|
import { RistrettoPoint } from '@noble/curves/ed25519';
|
||||||
|
const rp = RistrettoPoint.fromHex(
|
||||||
|
'6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919'
|
||||||
|
);
|
||||||
|
RistrettoPoint.hashToCurve('Ristretto is traditionally a short shot of espresso coffee');
|
||||||
|
// also has add(), equals(), multiply(), toRawBytes() methods
|
||||||
|
```
|
||||||
|
|
||||||
|
ed448 module is basically the same:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
|
||||||
|
import { hashToCurve, encodeToCurve } from '@noble/curves/ed448';
|
||||||
|
```
|
||||||
|
|
||||||
|
BLS12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to
|
||||||
|
construct [zk-SNARKs](https://z.cash/technology/zksnarks/) at the 128-bit security
|
||||||
|
and use aggregated, batch-verifiable
|
||||||
|
[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
|
||||||
|
using Boneh-Lynn-Shacham signature scheme.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { bls12_381 as bls } from '@noble/curves/bls12-381';
|
||||||
|
const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
|
||||||
|
const message = '64726e3da8';
|
||||||
|
const publicKey = bls.getPublicKey(privateKey);
|
||||||
|
const signature = bls.sign(message, privateKey);
|
||||||
|
const isValid = bls.verify(signature, message, publicKey);
|
||||||
|
console.log({ publicKey, signature, isValid });
|
||||||
|
|
||||||
|
// Sign 1 msg with 3 keys
|
||||||
|
const privateKeys = [
|
||||||
|
'18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4',
|
||||||
|
'ed69a8c50cf8c9836be3b67c7eeff416612d45ba39a5c099d48fa668bf558c9c',
|
||||||
|
'16ae669f3be7a2121e17d0c68c05a8f3d6bef21ec0f2315f1d7aec12484e4cf5',
|
||||||
|
];
|
||||||
|
const messages = ['d2', '0d98', '05caf3'];
|
||||||
|
const publicKeys = privateKeys.map(bls.getPublicKey);
|
||||||
|
const signatures2 = privateKeys.map((p) => bls.sign(message, p));
|
||||||
|
const aggPubKey2 = bls.aggregatePublicKeys(publicKeys);
|
||||||
|
const aggSignature2 = bls.aggregateSignatures(signatures2);
|
||||||
|
const isValid2 = bls.verify(aggSignature2, message, aggPubKey2);
|
||||||
|
console.log({ signatures2, aggSignature2, isValid2 });
|
||||||
|
|
||||||
|
// Sign 3 msgs with 3 keys
|
||||||
|
const signatures3 = privateKeys.map((p, i) => bls.sign(messages[i], p));
|
||||||
|
const aggSignature3 = bls.aggregateSignatures(signatures3);
|
||||||
|
const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
|
||||||
|
console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
|
||||||
|
// bls.pairing(PointG1, PointG2) // pairings
|
||||||
|
|
||||||
|
// hash-to-curve examples can be seen below
|
||||||
|
```
|
||||||
|
|
||||||
|
## Abstract API
|
||||||
|
|
||||||
|
Abstract API allows to define custom curves. All arithmetics is done with JS bigints over finite fields,
|
||||||
|
which is defined from `modular` sub-module. For scalar multiplication, we use [precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/).
|
||||||
|
Precomputes are enabled for weierstrass and edwards BASE points of a curve. You could precompute any
|
||||||
|
other point (e.g. for ECDH) using `utils.precompute()` method: check out examples.
|
||||||
|
|
||||||
|
There are following zero-dependency algorithms:
|
||||||
|
|
||||||
|
- [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
|
||||||
- [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
|
- [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
|
||||||
- [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
|
- [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
|
||||||
- [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
|
|
||||||
- [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
|
- [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
|
||||||
- [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
|
- [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
|
||||||
- [abstract/modular](#abstractmodular)
|
- [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
|
||||||
- [abstract/utils](#abstractutils)
|
- [abstract/utils: General utilities](#abstractutils-general-utilities)
|
||||||
|
|
||||||
### Overview
|
### abstract/weierstrass: Short Weierstrass curve
|
||||||
|
|
||||||
There are following zero-dependency abstract algorithms:
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { bls } from '@noble/curves/abstract/bls';
|
|
||||||
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
|
||||||
import { montgomery } from '@noble/curves/abstract/montgomery';
|
|
||||||
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
||||||
import * as mod from '@noble/curves/abstract/modular';
|
|
||||||
import * as utils from '@noble/curves/abstract/utils';
|
|
||||||
```
|
```
|
||||||
|
|
||||||
They allow to define a new curve in a few lines of code:
|
Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass` expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h`
|
||||||
|
and coordinates `Gx`, `Gy` of generator point.
|
||||||
|
|
||||||
|
**`k` generation** is done deterministically, following [RFC6979](https://www.rfc-editor.org/rfc/rfc6979).
|
||||||
|
For this you will need `hmac` & `hash`, which in our implementations is provided by noble-hashes.
|
||||||
|
If you're using different hashing library, make sure to wrap it in the following interface:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Field } from '@noble/curves/abstract/modular';
|
type CHash = {
|
||||||
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
(message: Uint8Array): Uint8Array;
|
||||||
import { hmac } from '@noble/hashes/hmac';
|
blockLen: number;
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
outputLen: number;
|
||||||
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
create(): any;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
// secq (NOT secp) 256k1: cycle of secp256k1 with Fp/N flipped.
|
**Weierstrass points:**
|
||||||
// https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
|
|
||||||
// https://personaelabs.org/posts/spartan-ecdsa
|
1. Exported as `ProjectivePoint`
|
||||||
|
2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
|
||||||
|
3. Use complete exception-free formulas for addition and doubling
|
||||||
|
4. Can be decoded/encoded from/to Uint8Array / hex strings using `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()`
|
||||||
|
5. Have `assertValidity()` which checks for being on-curve
|
||||||
|
6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// T is usually bigint, but can be something else like complex numbers in BLS curves
|
||||||
|
interface ProjPointType<T> extends Group<ProjPointType<T>> {
|
||||||
|
readonly px: T;
|
||||||
|
readonly py: T;
|
||||||
|
readonly pz: T;
|
||||||
|
multiply(scalar: bigint): ProjPointType<T>;
|
||||||
|
multiplyUnsafe(scalar: bigint): ProjPointType<T>;
|
||||||
|
multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
|
||||||
|
toAffine(iz?: T): AffinePoint<T>;
|
||||||
|
isTorsionFree(): boolean;
|
||||||
|
clearCofactor(): ProjPointType<T>;
|
||||||
|
assertValidity(): void;
|
||||||
|
hasEvenY(): boolean;
|
||||||
|
toRawBytes(isCompressed?: boolean): Uint8Array;
|
||||||
|
toHex(isCompressed?: boolean): string;
|
||||||
|
}
|
||||||
|
// Static methods for 3d XYZ points
|
||||||
|
interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
|
||||||
|
new (x: T, y: T, z: T): ProjPointType<T>;
|
||||||
|
fromAffine(p: AffinePoint<T>): ProjPointType<T>;
|
||||||
|
fromHex(hex: Hex): ProjPointType<T>;
|
||||||
|
fromPrivateKey(privateKey: PrivKey): ProjPointType<T>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**ECDSA signatures** are represented by `Signature` instances and can be described by the interface:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface SignatureType {
|
||||||
|
readonly r: bigint;
|
||||||
|
readonly s: bigint;
|
||||||
|
readonly recovery?: number;
|
||||||
|
assertValidity(): void;
|
||||||
|
addRecoveryBit(recovery: number): SignatureType;
|
||||||
|
hasHighS(): boolean;
|
||||||
|
normalizeS(): SignatureType;
|
||||||
|
recoverPublicKey(msgHash: Hex): ProjPointType<bigint>;
|
||||||
|
toCompactRawBytes(): Uint8Array;
|
||||||
|
toCompactHex(): string;
|
||||||
|
// DER-encoded
|
||||||
|
toDERRawBytes(): Uint8Array;
|
||||||
|
toDERHex(): string;
|
||||||
|
}
|
||||||
|
type SignatureConstructor = {
|
||||||
|
new (r: bigint, s: bigint): SignatureType;
|
||||||
|
fromCompact(hex: Hex): SignatureType;
|
||||||
|
fromDER(hex: Hex): SignatureType;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Example implementing [secq256k1](https://personaelabs.org/posts/spartan-ecdsa) (NOT secp256k1)
|
||||||
|
[cycle](https://zcash.github.io/halo2/background/curves.html#cycles-of-curves) of secp256k1 with Fp/N flipped.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
||||||
|
import { Field } from '@noble/curves/abstract/modular'; // finite field, mod arithmetics done over it
|
||||||
|
import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash, with blockLen/outputLen
|
||||||
|
import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256()
|
||||||
|
import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities
|
||||||
const secq256k1 = weierstrass({
|
const secq256k1 = weierstrass({
|
||||||
|
// secq256k1: cycle of secp256k1 with Fp/N flipped.
|
||||||
a: 0n,
|
a: 0n,
|
||||||
b: 7n,
|
b: 7n,
|
||||||
Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
|
Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
|
||||||
@@ -130,50 +300,110 @@ const secq256k1 = weierstrass({
|
|||||||
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
|
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
|
||||||
randomBytes,
|
randomBytes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// All curves expose same generic interface.
|
||||||
|
const priv = secq256k1.utils.randomPrivateKey();
|
||||||
|
secq256k1.getPublicKey(priv); // Convert private key to public.
|
||||||
|
const sig = secq256k1.sign(msg, priv); // Sign msg with private key.
|
||||||
|
secq256k1.verify(sig, msg, priv); // Verify if sig is correct.
|
||||||
|
|
||||||
|
const Point = secq256k1.ProjectivePoint;
|
||||||
|
const point = Point.BASE; // Elliptic curve Point class and BASE point static var.
|
||||||
|
point.add(point).equals(point.double()); // add(), equals(), double() methods
|
||||||
|
point.subtract(point).equals(Point.ZERO); // subtract() method, ZERO static var
|
||||||
|
point.negate(); // Flips point over x/y coordinate.
|
||||||
|
point.multiply(31415n); // Multiplication of Point by scalar.
|
||||||
|
|
||||||
|
point.assertValidity(); // Checks for being on-curve
|
||||||
|
point.toAffine(); // Converts to 2d affine xy coordinates
|
||||||
|
|
||||||
|
secq256k1.CURVE.n;
|
||||||
|
secq256k1.CURVE.Fp.mod();
|
||||||
|
secq256k1.CURVE.hash();
|
||||||
|
|
||||||
|
// precomputes
|
||||||
|
const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey));
|
||||||
|
fast.multiply(privKey); // much faster ECDH now
|
||||||
```
|
```
|
||||||
|
|
||||||
- To initialize new curve, you must specify its variables, order (number of points on curve), field prime (over which the modular division would be done)
|
`weierstrass()` returns `CurveFn`:
|
||||||
- All curves expose same generic interface:
|
|
||||||
- `getPublicKey()`, `sign()`, `verify()` functions
|
|
||||||
- `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
|
|
||||||
- `CURVE` object with curve variables like `Gx`, `Gy`, `Fp` (field), `n` (order)
|
|
||||||
- `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
|
|
||||||
- All arithmetics is done with JS bigints over finite fields, which is defined from `modular` sub-module
|
|
||||||
- Many features require hashing, which is not provided. `@noble/hashes` can be used for this purpose.
|
|
||||||
Any other library must conform to the CHash interface:
|
|
||||||
```ts
|
```ts
|
||||||
export type CHash = {
|
type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array };
|
||||||
(message: Uint8Array): Uint8Array;
|
type CurveFn = {
|
||||||
blockLen: number;
|
CURVE: ReturnType<typeof validateOpts>;
|
||||||
outputLen: number;
|
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
|
||||||
create(): any;
|
getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
|
||||||
|
sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
|
||||||
|
verify: (
|
||||||
|
signature: Hex | SignatureType,
|
||||||
|
msgHash: Hex,
|
||||||
|
publicKey: Hex,
|
||||||
|
opts?: { lowS?: boolean; prehash?: boolean }
|
||||||
|
) => boolean;
|
||||||
|
ProjectivePoint: ProjectivePointConstructor;
|
||||||
|
Signature: SignatureConstructor;
|
||||||
|
utils: {
|
||||||
|
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
||||||
|
isValidPrivateKey(key: PrivKey): boolean;
|
||||||
|
randomPrivateKey: () => Uint8Array;
|
||||||
|
precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
- w-ary non-adjacent form (wNAF) method with constant-time adjustments is used for point multiplication.
|
|
||||||
It is possible to enable precomputes for edwards & weierstrass curves.
|
|
||||||
Precomputes are calculated once (takes ~20-40ms), after that most `G` base point multiplications:
|
|
||||||
for example, `getPublicKey()`, `sign()` and similar methods - would be much faster.
|
|
||||||
Use `curve.utils.precompute()` to adjust precomputation window size
|
|
||||||
- You could use optional special params to tune performance:
|
|
||||||
- `Fp({sqrt})` square root calculation, used for point decompression
|
|
||||||
- `endo` endomorphism options for Koblitz curves
|
|
||||||
|
|
||||||
### abstract/edwards: Twisted Edwards curve
|
### abstract/edwards: Twisted Edwards curve
|
||||||
|
|
||||||
Twisted Edwards curve's formula is: ax² + y² = 1 + dx²y².
|
Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h`
|
||||||
|
and coordinates `Gx`, `Gy` of generator point.
|
||||||
|
|
||||||
- You must specify curve params `a`, `d`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
|
For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified.
|
||||||
- For EdDSA signatures, params `hash` is also required. `adjustScalarBytes` which instructs how to change private scalars could be specified
|
|
||||||
|
|
||||||
```typescript
|
**Edwards points:**
|
||||||
|
|
||||||
|
1. Exported as `ExtendedPoint`
|
||||||
|
2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z)
|
||||||
|
3. Use complete exception-free formulas for addition and doubling
|
||||||
|
4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()`
|
||||||
|
5. Have `assertValidity()` which checks for being on-curve
|
||||||
|
6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
|
||||||
|
7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface ExtPointType extends Group<ExtPointType> {
|
||||||
|
readonly ex: bigint;
|
||||||
|
readonly ey: bigint;
|
||||||
|
readonly ez: bigint;
|
||||||
|
readonly et: bigint;
|
||||||
|
assertValidity(): void;
|
||||||
|
multiply(scalar: bigint): ExtPointType;
|
||||||
|
multiplyUnsafe(scalar: bigint): ExtPointType;
|
||||||
|
isSmallOrder(): boolean;
|
||||||
|
isTorsionFree(): boolean;
|
||||||
|
clearCofactor(): ExtPointType;
|
||||||
|
toAffine(iz?: bigint): AffinePoint<bigint>;
|
||||||
|
}
|
||||||
|
// Static methods of Extended Point with coordinates in X, Y, Z, T
|
||||||
|
interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
|
||||||
|
new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
|
||||||
|
fromAffine(p: AffinePoint<bigint>): ExtPointType;
|
||||||
|
fromHex(hex: Hex): ExtPointType;
|
||||||
|
fromPrivateKey(privateKey: Hex): ExtPointType;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Example implementing edwards25519:
|
||||||
|
|
||||||
|
```ts
|
||||||
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
||||||
import { div } from '@noble/curves/abstract/modular';
|
import { Field, div } from '@noble/curves/abstract/modular';
|
||||||
import { sha512 } from '@noble/hashes/sha512';
|
import { sha512 } from '@noble/hashes/sha512';
|
||||||
|
|
||||||
|
const Fp = Field(2n ** 255n - 19n);
|
||||||
const ed25519 = twistedEdwards({
|
const ed25519 = twistedEdwards({
|
||||||
a: -1n,
|
a: -1n,
|
||||||
d: div(-121665n, 121666n, 2n ** 255n - 19n), // -121665n/121666n
|
d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p
|
||||||
P: 2n ** 255n - 19n,
|
Fp,
|
||||||
n: 2n ** 252n + 27742317777372353535851937790883648493n,
|
n: 2n ** 252n + 27742317777372353535851937790883648493n,
|
||||||
h: 8n,
|
h: 8n,
|
||||||
Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
|
Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
|
||||||
@@ -181,31 +411,24 @@ const ed25519 = twistedEdwards({
|
|||||||
hash: sha512,
|
hash: sha512,
|
||||||
randomBytes,
|
randomBytes,
|
||||||
adjustScalarBytes(bytes) {
|
adjustScalarBytes(bytes) {
|
||||||
// optional in general, mandatory in ed25519
|
// optional; but mandatory in ed25519
|
||||||
bytes[0] &= 248;
|
bytes[0] &= 248;
|
||||||
bytes[31] &= 127;
|
bytes[31] &= 127;
|
||||||
bytes[31] |= 64;
|
bytes[31] |= 64;
|
||||||
return bytes;
|
return bytes;
|
||||||
},
|
},
|
||||||
} as const);
|
} as const);
|
||||||
const key = ed25519.utils.randomPrivateKey();
|
|
||||||
const pub = ed25519.getPublicKey(key);
|
|
||||||
const msg = new TextEncoder().encode('hello world'); // strings not accepted, must be Uint8Array
|
|
||||||
const sig = ed25519.sign(msg, key);
|
|
||||||
ed25519.verify(sig, msg, pub) === true;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`twistedEdwards()` returns `CurveFn` of following type:
|
`twistedEdwards()` returns `CurveFn` of following type:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export type CurveFn = {
|
type CurveFn = {
|
||||||
CURVE: ReturnType<typeof validateOpts>;
|
CURVE: ReturnType<typeof validateOpts>;
|
||||||
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
|
getPublicKey: (privateKey: Hex) => Uint8Array;
|
||||||
sign: (message: Hex, privateKey: Hex) => Uint8Array;
|
sign: (message: Hex, privateKey: Hex, context?: Hex) => Uint8Array;
|
||||||
verify: (sig: SigType, message: Hex, publicKey: PubKey) => boolean;
|
verify: (sig: SigType, message: Hex, publicKey: Hex, context?: Hex) => boolean;
|
||||||
Point: PointConstructor;
|
ExtendedPoint: ExtPointConstructor;
|
||||||
ExtendedPoint: ExtendedPointConstructor;
|
|
||||||
Signature: SignatureConstructor;
|
|
||||||
utils: {
|
utils: {
|
||||||
randomPrivateKey: () => Uint8Array;
|
randomPrivateKey: () => Uint8Array;
|
||||||
getExtendedPublicKey: (key: PrivKey) => {
|
getExtendedPublicKey: (key: PrivKey) => {
|
||||||
@@ -221,26 +444,20 @@ export type CurveFn = {
|
|||||||
|
|
||||||
### abstract/montgomery: Montgomery curve
|
### abstract/montgomery: Montgomery curve
|
||||||
|
|
||||||
For now the module only contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
|
The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748. Proper Elliptic Curve Points are not implemented yet.
|
||||||
|
|
||||||
Proper Elliptic Curve Points are not implemented yet.
|
You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
|
||||||
|
|
||||||
You must specify curve field, `a24` special variable, `montgomeryBits`, `nByteLength`, and coordinate `u` of generator point.
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { montgomery } from '@noble/curves/abstract/montgomery';
|
import { montgomery } from '@noble/curves/abstract/montgomery';
|
||||||
|
|
||||||
const x25519 = montgomery({
|
const x25519 = montgomery({
|
||||||
P: 2n ** 255n - 19n,
|
Fp: Field(2n ** 255n - 19n),
|
||||||
a24: 121665n, // TODO: change to a
|
a: 486662n,
|
||||||
|
Gu: 9n,
|
||||||
montgomeryBits: 255,
|
montgomeryBits: 255,
|
||||||
nByteLength: 32,
|
nByteLength: 32,
|
||||||
Gu: '0900000000000000000000000000000000000000000000000000000000000000',
|
// Optional param
|
||||||
|
|
||||||
// Optional params
|
|
||||||
powPminus2: (x: bigint): bigint => {
|
|
||||||
return mod.pow(x, P - 2, P);
|
|
||||||
},
|
|
||||||
adjustScalarBytes(bytes) {
|
adjustScalarBytes(bytes) {
|
||||||
bytes[0] &= 248;
|
bytes[0] &= 248;
|
||||||
bytes[31] &= 127;
|
bytes[31] &= 127;
|
||||||
@@ -250,88 +467,29 @@ const x25519 = montgomery({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### abstract/weierstrass: Short Weierstrass curve
|
|
||||||
|
|
||||||
Short Weierstrass curve's formula is: y² = x³ + ax + b. Uses deterministic ECDSA from RFC6979. You can also specify `extraEntropy` in `sign()`.
|
|
||||||
|
|
||||||
- You must specify curve params: `a`, `b`, field `Fp`, order `n`, cofactor `h` and coordinates `Gx`, `Gy` of generator point
|
|
||||||
- For ECDSA, you must specify `hash`, `hmac`. It is also possible to recover keys from signatures
|
|
||||||
- For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
|
|
||||||
- Optional params are `lowS` (default value) and `endo` (endomorphism)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Fp } from '@noble/curves/abstract/modular';
|
|
||||||
import { weierstrass } from '@noble/curves/abstract/weierstrass'; // Short Weierstrass curve
|
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
|
||||||
import { hmac } from '@noble/hashes/hmac';
|
|
||||||
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
||||||
|
|
||||||
const secp256k1 = weierstrass({
|
|
||||||
a: 0n,
|
|
||||||
b: 7n,
|
|
||||||
Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
|
|
||||||
n: 2n ** 256n - 432420386565659656852420866394968145599n,
|
|
||||||
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
|
||||||
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
|
||||||
hash: sha256,
|
|
||||||
hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
|
|
||||||
randomBytes,
|
|
||||||
|
|
||||||
// Optional params
|
|
||||||
h: 1n, // Cofactor
|
|
||||||
lowS: true, // Allow only low-S signatures by default in sign() and verify()
|
|
||||||
endo: {
|
|
||||||
// Endomorphism options for Koblitz curve
|
|
||||||
// Beta param
|
|
||||||
beta: 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501een,
|
|
||||||
// Split scalar k into k1, k2
|
|
||||||
splitScalar: (k: bigint) => {
|
|
||||||
// return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Usage
|
|
||||||
const key = secp256k1.utils.randomPrivateKey();
|
|
||||||
const pub = secp256k1.getPublicKey(key);
|
|
||||||
const msg = randomBytes(32);
|
|
||||||
const sig = secp256k1.sign(msg, key);
|
|
||||||
secp256k1.verify(sig, msg, pub); // true
|
|
||||||
sig.recoverPublicKey(msg); // == pub
|
|
||||||
const someonesPubkey = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
|
||||||
const shared = secp256k1.getSharedSecret(key, someonesPubkey);
|
|
||||||
```
|
|
||||||
|
|
||||||
`weierstrass()` returns `CurveFn`:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
export type CurveFn = {
|
|
||||||
CURVE: ReturnType<typeof validateOpts>;
|
|
||||||
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
|
|
||||||
getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;
|
|
||||||
sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
|
|
||||||
verify: (
|
|
||||||
signature: Hex | SignatureType,
|
|
||||||
msgHash: Hex,
|
|
||||||
publicKey: Hex,
|
|
||||||
opts?: { lowS?: boolean }
|
|
||||||
) => boolean;
|
|
||||||
Point: PointConstructor;
|
|
||||||
ProjectivePoint: ProjectivePointConstructor;
|
|
||||||
Signature: SignatureConstructor;
|
|
||||||
utils: {
|
|
||||||
isValidPrivateKey(privateKey: PrivKey): boolean;
|
|
||||||
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
|
||||||
randomPrivateKey: () => Uint8Array;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### abstract/hash-to-curve: Hashing strings to curve points
|
### abstract/hash-to-curve: Hashing strings to curve points
|
||||||
|
|
||||||
The module allows to hash arbitrary strings to elliptic curve points.
|
The module allows to hash arbitrary strings to elliptic curve points. Implements [hash-to-curve v16](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16).
|
||||||
|
|
||||||
- `expand_message_xmd` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1) produces a uniformly random byte string using a cryptographic hash function H that outputs b bits..
|
Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1';
|
||||||
|
import { randomBytes } from '@noble/hashes/utils';
|
||||||
|
hashToCurve('0102abcd');
|
||||||
|
console.log(hashToCurve(randomBytes()));
|
||||||
|
console.log(encodeToCurve(randomBytes()));
|
||||||
|
|
||||||
|
import { bls12_381 } from '@noble/curves/bls12-381';
|
||||||
|
bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' });
|
||||||
|
bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' });
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need low-level methods from spec:
|
||||||
|
|
||||||
|
`expand_message_xmd` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1) produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
|
||||||
|
|
||||||
|
Hash must conform to `CHash` interface (see [weierstrass section](#abstractweierstrass-short-weierstrass-curve)).
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
function expand_message_xmd(
|
function expand_message_xmd(
|
||||||
@@ -349,46 +507,29 @@ The module allows to hash arbitrary strings to elliptic curve points.
|
|||||||
): Uint8Array;
|
): Uint8Array;
|
||||||
```
|
```
|
||||||
|
|
||||||
- `hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
|
`hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
|
||||||
hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
||||||
_ `msg` a byte string containing the message to hash
|
|
||||||
_ `count` the number of elements of F to output
|
- `msg` a byte string containing the message to hash
|
||||||
_ `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
|
- `count` the number of elements of F to output
|
||||||
_ Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
|
- `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`.
|
||||||
|
- `p` is field prime, m=field extension (1 for prime fields)
|
||||||
|
- `k` is security target in bits (e.g. 128).
|
||||||
|
- `expand` should be `xmd` for SHA2, SHA3, BLAKE; `xof` for SHAKE, BLAKE-XOF
|
||||||
|
- `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
|
||||||
|
- Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
function hash_to_field(msg: Uint8Array, count: number, options: htfOpts): bigint[][];
|
function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
|
||||||
type htfOpts = {
|
|
||||||
// DST: a domain separation tag
|
|
||||||
// defined in section 2.2.5
|
|
||||||
DST: string;
|
|
||||||
// p: the characteristic of F
|
|
||||||
// where F is a finite field of characteristic p and order q = p^m
|
|
||||||
p: bigint;
|
|
||||||
// m: the extension degree of F, m >= 1
|
|
||||||
// where F is a finite field of characteristic p and order q = p^m
|
|
||||||
m: number;
|
|
||||||
// k: the target security level for the suite in bits
|
|
||||||
// defined in section 5.1
|
|
||||||
k: number;
|
|
||||||
// option to use a message that has already been processed by
|
|
||||||
// expand_message_xmd
|
|
||||||
expand?: 'xmd' | 'xof';
|
|
||||||
// Hash functions for: expand_message_xmd is appropriate for use with a
|
|
||||||
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
|
||||||
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
|
||||||
// TODO: verify that hash is shake if expand==='xof' via types
|
|
||||||
hash: CHash;
|
|
||||||
};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### abstract/poseidon: Poseidon hash
|
### abstract/poseidon: Poseidon hash
|
||||||
|
|
||||||
Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.
|
Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.
|
||||||
|
|
||||||
There are many poseidon instances with different constants. We don't provide them,
|
There are many poseidon variants with different constants.
|
||||||
but we provide ability to specify them manually. For actual usage, check out
|
We don't provide them: you should construct them manually.
|
||||||
stark curve source code.
|
Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { poseidon } from '@noble/curves/abstract/poseidon';
|
import { poseidon } from '@noble/curves/abstract/poseidon';
|
||||||
@@ -399,34 +540,60 @@ type PoseidonOpts = {
|
|||||||
roundsFull: number;
|
roundsFull: number;
|
||||||
roundsPartial: number;
|
roundsPartial: number;
|
||||||
sboxPower?: number;
|
sboxPower?: number;
|
||||||
reversePartialPowIdx?: boolean; // Hack for stark
|
reversePartialPowIdx?: boolean;
|
||||||
mds: bigint[][];
|
mds: bigint[][];
|
||||||
roundConstants: bigint[][];
|
roundConstants: bigint[][];
|
||||||
};
|
};
|
||||||
const instance = poseidon(opts: PoseidonOpts);
|
const instance = poseidon(opts: PoseidonOpts);
|
||||||
```
|
```
|
||||||
|
|
||||||
### abstract/modular
|
### abstract/bls
|
||||||
|
|
||||||
Modular arithmetics utilities.
|
The module abstracts BLS (Barreto-Lynn-Scott) primitives. In theory you should be able to write BLS12-377, BLS24,
|
||||||
|
and others with it.
|
||||||
|
|
||||||
```typescript
|
### abstract/modular: Modular arithmetics utilities
|
||||||
import { Fp, mod, invert, div, invertBatch, sqrt } from '@noble/curves/abstract/modular';
|
|
||||||
const fp = Fp(2n ** 255n - 19n); // Finite field over 2^255-19
|
```ts
|
||||||
fp.mul(591n, 932n);
|
import * as mod from '@noble/curves/abstract/modular';
|
||||||
fp.pow(481n, 11024858120n);
|
const fp = mod.Field(2n ** 255n - 19n); // Finite field over 2^255-19
|
||||||
|
fp.mul(591n, 932n); // multiplication
|
||||||
|
fp.pow(481n, 11024858120n); // exponentiation
|
||||||
|
fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
|
||||||
|
fp.sqrt(21n); // square root
|
||||||
|
|
||||||
// Generic non-FP utils are also available
|
// Generic non-FP utils are also available
|
||||||
mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
|
mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
|
||||||
invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
|
mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
|
||||||
div(5n, 17n, 10n); // 5/17 mod 10 == 5 * invert(17) mod 10; division
|
mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
|
||||||
invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion
|
|
||||||
sqrt(21n, 73n); // √21 mod 73; square root
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### abstract/utils
|
#### Creating private keys from hashes
|
||||||
|
|
||||||
```typescript
|
Suppose you have `sha256(something)` (e.g. from HMAC) and you want to make a private key from it.
|
||||||
|
Even though p256 or secp256k1 may have 32-byte private keys,
|
||||||
|
and sha256 output is also 32-byte, you can't just use it and reduce it modulo `CURVE.n`.
|
||||||
|
|
||||||
|
Doing so will make the result key [biased](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/).
|
||||||
|
|
||||||
|
To avoid the bias, we implement FIPS 186 B.4.1, which allows to take arbitrary
|
||||||
|
byte array and produce valid scalars / private keys with bias being neglible.
|
||||||
|
|
||||||
|
Use [hash-to-curve](#abstracthash-to-curve-hashing-strings-to-curve-points) if you need
|
||||||
|
hashing to **public keys**; the function in the module instead operates on **private keys**.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { p256 } from '@noble/curves/p256';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { hkdf } from '@noble/hashes/hkdf';
|
||||||
|
const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)
|
||||||
|
const derived = hkdf(sha256, someKey, undefined, 'application', 40); // 40 bytes
|
||||||
|
const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n);
|
||||||
|
```
|
||||||
|
|
||||||
|
### abstract/utils: General utilities
|
||||||
|
|
||||||
|
```ts
|
||||||
import * as utils from '@noble/curves/abstract/utils';
|
import * as utils from '@noble/curves/abstract/utils';
|
||||||
|
|
||||||
utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
||||||
@@ -434,93 +601,133 @@ utils.hexToBytes('deadbeef');
|
|||||||
utils.hexToNumber();
|
utils.hexToNumber();
|
||||||
utils.bytesToNumberBE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
utils.bytesToNumberBE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
||||||
utils.bytesToNumberLE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
utils.bytesToNumberLE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));
|
||||||
utils.numberToBytesBE(123n);
|
utils.numberToBytesBE(123n, 32);
|
||||||
utils.numberToBytesLE(123n);
|
utils.numberToBytesLE(123n, 64);
|
||||||
utils.numberToHexUnpadded(123n);
|
utils.numberToHexUnpadded(123n);
|
||||||
utils.concatBytes(Uint8Array.from([0xde, 0xad]), Uint8Array.from([0xbe, 0xef]));
|
utils.concatBytes(Uint8Array.from([0xde, 0xad]), Uint8Array.from([0xbe, 0xef]));
|
||||||
utils.nLength(255n);
|
utils.nLength(255n);
|
||||||
utils.hashToPrivateScalar(sha512_of_something, secp256r1.n);
|
|
||||||
utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
|
utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde]));
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
The library had no prior security audit.
|
1. The library has been audited during Jan-Feb 2023 by an independent security firm [Trail of Bits](https://www.trailofbits.com):
|
||||||
|
[PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
|
||||||
|
The audit has been funded by Ryan Shea. Audit scope was abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass`, and top-level modules `_shortw_utils` and `secp256k1`. See [changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main).
|
||||||
|
2. The library has been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). You can run the fuzzer by yourself to check it.
|
||||||
|
3. [Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations: _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library can't have constant-timeness_. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.
|
||||||
|
|
||||||
[Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations: _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library can't have constant-timeness_. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time.
|
We consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector. As for devDependencies used by the library:
|
||||||
|
|
||||||
We consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector.
|
- `@scure` base, bip32, bip39 (used in tests), micro-bmark (benchmark), micro-should (testing) are developed by us
|
||||||
|
and follow the same practices such as: minimal library size, auditability, signed releases
|
||||||
|
- prettier (linter), fast-check (property-based testing),
|
||||||
|
typescript versions are locked and rarely updated. Every update is checked with `npm-diff`.
|
||||||
|
The packages are big, which makes it hard to audit their source code thoroughly and fully.
|
||||||
|
- They are only used if you clone the git repo and want to add some feature to it. End-users won't use them.
|
||||||
|
|
||||||
## Speed
|
## Speed
|
||||||
|
|
||||||
Benchmark results on Apple M2 with node v18.10:
|
Benchmark results on Apple M2 with node v19:
|
||||||
|
|
||||||
```
|
```
|
||||||
secp256k1
|
secp256k1
|
||||||
init x 57 ops/sec @ 17ms/op
|
init x 58 ops/sec @ 17ms/op
|
||||||
getPublicKey x 4,946 ops/sec @ 202μs/op
|
getPublicKey x 5,640 ops/sec @ 177μs/op
|
||||||
sign x 3,914 ops/sec @ 255μs/op
|
sign x 3,909 ops/sec @ 255μs/op
|
||||||
verify x 682 ops/sec @ 1ms/op
|
verify x 780 ops/sec @ 1ms/op
|
||||||
getSharedSecret x 427 ops/sec @ 2ms/op
|
getSharedSecret x 465 ops/sec @ 2ms/op
|
||||||
recoverPublicKey x 683 ops/sec @ 1ms/op
|
recoverPublicKey x 740 ops/sec @ 1ms/op
|
||||||
schnorr.sign x 539 ops/sec @ 1ms/op
|
schnorr.sign x 597 ops/sec @ 1ms/op
|
||||||
schnorr.verify x 716 ops/sec @ 1ms/op
|
schnorr.verify x 775 ops/sec @ 1ms/op
|
||||||
|
|
||||||
P256
|
P256
|
||||||
init x 30 ops/sec @ 32ms/op
|
init x 31 ops/sec @ 31ms/op
|
||||||
getPublicKey x 5,008 ops/sec @ 199μs/op
|
getPublicKey x 5,607 ops/sec @ 178μs/op
|
||||||
sign x 3,970 ops/sec @ 251μs/op
|
sign x 3,930 ops/sec @ 254μs/op
|
||||||
verify x 515 ops/sec @ 1ms/op
|
verify x 540 ops/sec @ 1ms/op
|
||||||
|
|
||||||
P384
|
P384
|
||||||
init x 14 ops/sec @ 66ms/op
|
init x 15 ops/sec @ 63ms/op
|
||||||
getPublicKey x 2,434 ops/sec @ 410μs/op
|
getPublicKey x 2,622 ops/sec @ 381μs/op
|
||||||
sign x 1,942 ops/sec @ 514μs/op
|
sign x 1,913 ops/sec @ 522μs/op
|
||||||
verify x 206 ops/sec @ 4ms/op
|
verify x 222 ops/sec @ 4ms/op
|
||||||
|
|
||||||
P521
|
P521
|
||||||
init x 7 ops/sec @ 126ms/op
|
init x 8 ops/sec @ 119ms/op
|
||||||
getPublicKey x 1,282 ops/sec @ 779μs/op
|
getPublicKey x 1,371 ops/sec @ 729μs/op
|
||||||
sign x 1,077 ops/sec @ 928μs/op
|
sign x 1,090 ops/sec @ 917μs/op
|
||||||
verify x 110 ops/sec @ 9ms/op
|
verify x 118 ops/sec @ 8ms/op
|
||||||
|
|
||||||
ed25519
|
ed25519
|
||||||
init x 37 ops/sec @ 26ms/op
|
init x 47 ops/sec @ 20ms/op
|
||||||
getPublicKey x 8,147 ops/sec @ 122μs/op
|
getPublicKey x 9,414 ops/sec @ 106μs/op
|
||||||
sign x 3,979 ops/sec @ 251μs/op
|
sign x 4,516 ops/sec @ 221μs/op
|
||||||
verify x 848 ops/sec @ 1ms/op
|
verify x 912 ops/sec @ 1ms/op
|
||||||
|
|
||||||
ed448
|
ed448
|
||||||
init x 17 ops/sec @ 58ms/op
|
init x 17 ops/sec @ 56ms/op
|
||||||
getPublicKey x 3,083 ops/sec @ 324μs/op
|
getPublicKey x 3,363 ops/sec @ 297μs/op
|
||||||
sign x 1,473 ops/sec @ 678μs/op
|
sign x 1,615 ops/sec @ 619μs/op
|
||||||
verify x 323 ops/sec @ 3ms/op
|
verify x 319 ops/sec @ 3ms/op
|
||||||
|
|
||||||
|
ecdh
|
||||||
|
├─x25519 x 1,337 ops/sec @ 747μs/op
|
||||||
|
├─secp256k1 x 461 ops/sec @ 2ms/op
|
||||||
|
├─P256 x 441 ops/sec @ 2ms/op
|
||||||
|
├─P384 x 179 ops/sec @ 5ms/op
|
||||||
|
├─P521 x 93 ops/sec @ 10ms/op
|
||||||
|
└─x448 x 496 ops/sec @ 2ms/op
|
||||||
|
|
||||||
bls12-381
|
bls12-381
|
||||||
init x 30 ops/sec @ 33ms/op
|
init x 32 ops/sec @ 30ms/op
|
||||||
getPublicKey x 788 ops/sec @ 1ms/op
|
getPublicKey 1-bit x 858 ops/sec @ 1ms/op
|
||||||
sign x 45 ops/sec @ 21ms/op
|
getPublicKey x 858 ops/sec @ 1ms/op
|
||||||
verify x 32 ops/sec @ 30ms/op
|
sign x 49 ops/sec @ 20ms/op
|
||||||
pairing x 88 ops/sec @ 11ms/op
|
verify x 34 ops/sec @ 28ms/op
|
||||||
|
pairing x 94 ops/sec @ 10ms/op
|
||||||
|
aggregatePublicKeys/8 x 116 ops/sec @ 8ms/op
|
||||||
|
aggregatePublicKeys/32 x 31 ops/sec @ 31ms/op
|
||||||
|
aggregatePublicKeys/128 x 7 ops/sec @ 125ms/op
|
||||||
|
aggregateSignatures/8 x 45 ops/sec @ 22ms/op
|
||||||
|
aggregateSignatures/32 x 11 ops/sec @ 84ms/op
|
||||||
|
aggregateSignatures/128 x 3 ops/sec @ 332ms/opp
|
||||||
|
|
||||||
stark
|
hash-to-curve
|
||||||
init x 31 ops/sec @ 31ms/op
|
hash_to_field x 850,340 ops/sec @ 1μs/op
|
||||||
pedersen
|
hashToCurve
|
||||||
├─old x 84 ops/sec @ 11ms/op
|
├─secp256k1 x 1,850 ops/sec @ 540μs/op
|
||||||
└─noble x 802 ops/sec @ 1ms/op
|
├─P256 x 3,352 ops/sec @ 298μs/op
|
||||||
poseidon x 7,466 ops/sec @ 133μs/op
|
├─P384 x 1,367 ops/sec @ 731μs/op
|
||||||
verify
|
├─P521 x 691 ops/sec @ 1ms/op
|
||||||
├─old x 300 ops/sec @ 3ms/op
|
├─ed25519 x 2,492 ops/sec @ 401μs/op
|
||||||
└─noble x 474 ops/sec @ 2ms/op
|
└─ed448 x 1,045 ops/sec @ 956μs/op
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
Article about some of library's features: [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
|
||||||
|
|
||||||
|
Projects using the library:
|
||||||
|
|
||||||
|
- secp256k1
|
||||||
|
- [btc-signer](https://github.com/paulmillr/scure-btc-signer), [eth-signer](https://github.com/paulmillr/micro-eth-signer)
|
||||||
|
- ed25519
|
||||||
|
- [sol-signer](https://github.com/paulmillr/micro-sol-signer)
|
||||||
|
- BLS12-381
|
||||||
|
- Check out `bls12-381.ts` for articles about the curve
|
||||||
|
- Threshold sigs demo [genthresh.com](https://genthresh.com)
|
||||||
|
- BBS signatures [github.com/Wind4Greg/BBS-Draft-Checks](https://github.com/Wind4Greg/BBS-Draft-Checks) following [draft-irtf-cfrg-bbs-signatures-latest](https://identity.foundation/bbs-signature/draft-irtf-cfrg-bbs-signatures.html)
|
||||||
|
- Others
|
||||||
|
- All curves demo: Elliptic curve calculator [paulmillr.com/ecc](https://paulmillr.com/ecc)
|
||||||
|
- [micro-starknet](https://github.com/paulmillr/micro-starknet) for stark-friendly elliptic curve.
|
||||||
## Upgrading
|
## Upgrading
|
||||||
|
|
||||||
If you're coming from single-curve noble packages, the following changes need to be kept in mind:
|
If you're coming from single-feature noble packages, the following changes need to be kept in mind:
|
||||||
|
|
||||||
- 2d affine (x, y) points have been removed to reduce complexity and improve speed
|
- 2d affine (x, y) points have been removed to reduce complexity and improve speed
|
||||||
- Removed `number` support as a type for private keys. `bigint` is still supported
|
- Removed `number` support as a type for private keys, `bigint` is still supported
|
||||||
- `mod`, `invert` are no longer present in `utils`. Use `@noble/curves/abstract/modular.js` now.
|
- `mod`, `invert` are no longer present in `utils`: use `@noble/curves/abstract/modular`
|
||||||
|
|
||||||
Upgrading from @noble/secp256k1 1.7:
|
Upgrading from @noble/secp256k1 1.7:
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| >=0.5.0 | :white_check_mark: |
|
| >=1.0.0 | :white_check_mark: |
|
||||||
| <0.5.0 | :x: |
|
| <1.0.0 | :x: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
|||||||
BIN
audit/2023-01-trailofbits-audit-curves.pdf
Normal file
BIN
audit/2023-01-trailofbits-audit-curves.pdf
Normal file
Binary file not shown.
11
audit/README.md
Normal file
11
audit/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Audit
|
||||||
|
|
||||||
|
The library has been audited during Jan-Feb 2023 by an independent security firm [Trail of Bits](https://www.trailofbits.com):
|
||||||
|
[PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
|
||||||
|
The audit has been funded by Ryan Shea. Audit scope was abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass`, and top-level modules `_shortw_utils` and `secp256k1`. See [changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main).
|
||||||
|
|
||||||
|
File in the directory was saved from
|
||||||
|
[github.com/trailofbits/publications](https://github.com/trailofbits/publications).
|
||||||
|
Check out their repo and verify checksums to ensure the PDF in this directory has not been altered.
|
||||||
|
|
||||||
|
See information about fuzzing in root [README](../README.md).
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { mark, run } from 'micro-bmark';
|
import { mark, run } from 'micro-bmark';
|
||||||
import { bls12_381 as bls } from '../lib/bls12-381.js';
|
import { bls12_381 as bls } from '../bls12-381.js';
|
||||||
|
|
||||||
const G2_VECTORS = readFileSync('../test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
|
const G2_VECTORS = readFileSync('../test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
|
||||||
.trim()
|
.trim()
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { run, mark, utils } from 'micro-bmark';
|
import { run, mark, utils } from 'micro-bmark';
|
||||||
import { generateData } from './_shared.js';
|
import { generateData } from './_shared.js';
|
||||||
import { P256 } from '../lib/p256.js';
|
import { P256 } from '../p256.js';
|
||||||
import { P384 } from '../lib/p384.js';
|
import { P384 } from '../p384.js';
|
||||||
import { P521 } from '../lib/p521.js';
|
import { P521 } from '../p521.js';
|
||||||
import { ed25519 } from '../lib/ed25519.js';
|
import { ed25519 } from '../ed25519.js';
|
||||||
import { ed448 } from '../lib/ed448.js';
|
import { ed448 } from '../ed448.js';
|
||||||
|
|
||||||
run(async () => {
|
run(async () => {
|
||||||
const RAM = false
|
const RAM = false
|
||||||
|
|||||||
19
benchmark/ecdh.js
Normal file
19
benchmark/ecdh.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { run, mark, compare, utils } from 'micro-bmark';
|
||||||
|
import { generateData } from './_shared.js';
|
||||||
|
import { secp256k1 } from '../secp256k1.js';
|
||||||
|
import { P256 } from '../p256.js';
|
||||||
|
import { P384 } from '../p384.js';
|
||||||
|
import { P521 } from '../p521.js';
|
||||||
|
import { x25519 } from '../ed25519.js';
|
||||||
|
import { x448 } from '../ed448.js';
|
||||||
|
|
||||||
|
run(async () => {
|
||||||
|
const curves = { x25519, secp256k1, P256, P384, P521, x448 };
|
||||||
|
const fns = {};
|
||||||
|
for (let [k, c] of Object.entries(curves)) {
|
||||||
|
const pubB = c.getPublicKey(c.utils.randomPrivateKey());
|
||||||
|
const privA = c.utils.randomPrivateKey();
|
||||||
|
fns[k] = () => c.getSharedSecret(privA, pubB);
|
||||||
|
}
|
||||||
|
await compare('ecdh', 1000, fns);
|
||||||
|
});
|
||||||
29
benchmark/hash-to-curve.js
Normal file
29
benchmark/hash-to-curve.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { run, mark, utils } from 'micro-bmark';
|
||||||
|
import { hash_to_field } from '../abstract/hash-to-curve.js';
|
||||||
|
import { hashToPrivateScalar } from '../abstract/modular.js';
|
||||||
|
import { randomBytes } from '@noble/hashes/utils';
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
// import { generateData } from './_shared.js';
|
||||||
|
import { hashToCurve as secp256k1 } from '../secp256k1.js';
|
||||||
|
import { hashToCurve as P256 } from '../p256.js';
|
||||||
|
import { hashToCurve as P384 } from '../p384.js';
|
||||||
|
import { hashToCurve as P521 } from '../p521.js';
|
||||||
|
import { hashToCurve as ed25519 } from '../ed25519.js';
|
||||||
|
import { hashToCurve as ed448 } from '../ed448.js';
|
||||||
|
import { utf8ToBytes } from '../abstract/utils.js';
|
||||||
|
|
||||||
|
const N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
|
||||||
|
run(async () => {
|
||||||
|
const rand = randomBytes(40);
|
||||||
|
await mark('hashToPrivateScalar', 1000000, () => hashToPrivateScalar(rand, N));
|
||||||
|
// - p, the characteristic of F
|
||||||
|
// - m, the extension degree of F, m >= 1
|
||||||
|
// - L = ceil((ceil(log2(p)) + k) / 8), where k is the security of suite (e.g. 128)
|
||||||
|
await mark('hash_to_field', 1000000, () =>
|
||||||
|
hash_to_field(rand, 1, { DST: 'secp256k1', hash: sha256, p: N, m: 1, k: 128 })
|
||||||
|
);
|
||||||
|
const msg = utf8ToBytes('message');
|
||||||
|
for (let [title, fn] of Object.entries({ secp256k1, P256, P384, P521, ed25519, ed448 })) {
|
||||||
|
await mark(`hashToCurve ${title}`, 1000, () => fn(msg));
|
||||||
|
}
|
||||||
|
});
|
||||||
13
benchmark/modular.js
Normal file
13
benchmark/modular.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { run, mark } from 'micro-bmark';
|
||||||
|
import { secp256k1 } from '../secp256k1.js';
|
||||||
|
import { Fp } from '../abstract/modular.js';
|
||||||
|
|
||||||
|
run(async () => {
|
||||||
|
console.log(`\x1b[36mmodular, secp256k1 field\x1b[0m`);
|
||||||
|
const { Fp: secpFp } = secp256k1.CURVE;
|
||||||
|
await mark('invert a', 300000, () => secpFp.inv(2n ** 232n - 5910n));
|
||||||
|
await mark('invert b', 300000, () => secpFp.inv(2n ** 231n - 5910n));
|
||||||
|
await mark('sqrt p = 3 mod 4', 15000, () => secpFp.sqrt(2n ** 231n - 5910n));
|
||||||
|
const FpStark = Fp(BigInt('0x800000000000011000000000000000000000000000000000000000000000001'));
|
||||||
|
await mark('sqrt tonneli-shanks', 500, () => FpStark.sqrt(2n ** 231n - 5909n))
|
||||||
|
});
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/hashes": "^1.1.5",
|
"@noble/hashes": "^1.1.5",
|
||||||
"@starkware-industries/starkware-crypto-utils": "^0.0.2",
|
|
||||||
"elliptic": "^6.5.4"
|
"elliptic": "^6.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { run, mark, utils } from 'micro-bmark';
|
import { run, mark, utils } from 'micro-bmark';
|
||||||
import { secp256k1, schnorr } from '../lib/secp256k1.js';
|
import { secp256k1, schnorr } from '../secp256k1.js';
|
||||||
import { generateData } from './_shared.js';
|
import { generateData } from './_shared.js';
|
||||||
|
|
||||||
run(async () => {
|
run(async () => {
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
import { run, mark, compare, utils } from 'micro-bmark';
|
|
||||||
import * as starkwareCrypto from '@starkware-industries/starkware-crypto-utils';
|
|
||||||
import * as stark from '../lib/stark.js';
|
|
||||||
|
|
||||||
run(async () => {
|
|
||||||
const RAM = false;
|
|
||||||
if (RAM) utils.logMem();
|
|
||||||
console.log(`\x1b[36mstark\x1b[0m`);
|
|
||||||
await mark('init', 1, () => stark.utils.precompute(8));
|
|
||||||
const d = (() => {
|
|
||||||
const priv = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
|
|
||||||
const msg = 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47';
|
|
||||||
const pub = stark.getPublicKey(priv);
|
|
||||||
const sig = stark.sign(msg, priv);
|
|
||||||
|
|
||||||
const privateKey = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
|
|
||||||
const msgHash = 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47';
|
|
||||||
const keyPair = starkwareCrypto.default.ec.keyFromPrivate(privateKey, 'hex');
|
|
||||||
const publicKeyStark = starkwareCrypto.default.ec.keyFromPublic(
|
|
||||||
keyPair.getPublic(true, 'hex'),
|
|
||||||
'hex'
|
|
||||||
);
|
|
||||||
return { priv, sig, msg, pub, publicKeyStark, msgHash, keyPair };
|
|
||||||
})();
|
|
||||||
await compare('pedersen', 500, {
|
|
||||||
old: () => {
|
|
||||||
return starkwareCrypto.default.pedersen([
|
|
||||||
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
|
|
||||||
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a',
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
noble: () => {
|
|
||||||
return stark.pedersen(
|
|
||||||
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
|
|
||||||
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await mark('poseidon', 10000, () => stark.poseidonHash(
|
|
||||||
0x3d937c035c878245caf64531a5756109c53068da139362728feb561405371cbn,
|
|
||||||
0x208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31an
|
|
||||||
));
|
|
||||||
await compare('verify', 500, {
|
|
||||||
old: () => {
|
|
||||||
return starkwareCrypto.default.verify(
|
|
||||||
d.publicKeyStark,
|
|
||||||
d.msgHash,
|
|
||||||
starkwareCrypto.default.sign(d.keyPair, d.msgHash)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
noble: () => {
|
|
||||||
return stark.verify(stark.sign(d.msg, d.priv), d.msg, d.pub);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (RAM) utils.logMem();
|
|
||||||
});
|
|
||||||
@@ -2,6 +2,6 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"browser": {
|
"browser": {
|
||||||
"crypto": false,
|
"crypto": false,
|
||||||
"./crypto": "./esm/cryptoBrowser.js"
|
"./crypto": "./esm/crypto.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@noble/curves",
|
"name": "@noble/curves",
|
||||||
"version": "0.6.2",
|
"version": "0.8.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@noble/curves",
|
"name": "@noble/curves",
|
||||||
"version": "0.6.2",
|
"version": "0.8.0",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -18,12 +18,11 @@
|
|||||||
"@noble/hashes": "1.2.0"
|
"@noble/hashes": "1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@scure/base": "~1.1.1",
|
|
||||||
"@scure/bip32": "~1.1.5",
|
"@scure/bip32": "~1.1.5",
|
||||||
"@scure/bip39": "~1.1.1",
|
"@scure/bip39": "~1.1.1",
|
||||||
"@types/node": "18.11.3",
|
"@types/node": "18.11.3",
|
||||||
"fast-check": "3.0.0",
|
"fast-check": "3.0.0",
|
||||||
"micro-bmark": "0.3.0",
|
"micro-bmark": "0.3.1",
|
||||||
"micro-should": "0.4.0",
|
"micro-should": "0.4.0",
|
||||||
"prettier": "2.8.3",
|
"prettier": "2.8.3",
|
||||||
"typescript": "4.7.3"
|
"typescript": "4.7.3"
|
||||||
@@ -120,9 +119,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/micro-bmark": {
|
"node_modules/micro-bmark": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/micro-bmark/-/micro-bmark-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/micro-bmark/-/micro-bmark-0.3.1.tgz",
|
||||||
"integrity": "sha512-rYu+AtUq8lC3zPCoxkOOtwhgJoMpCDGe0/BXUCkj6+H9f/U/TunH/n/qkN98yh04dCCtDV8Aj9uYO3+DKxYrcw==",
|
"integrity": "sha512-bNaKObD4yPAAPrpEqp5jO6LJ2sEFgLoFSmRjEY809mJ62+2AehI/K3+RlVpN3Oo92RHpgC2RQhj6b1Tb4dmo+w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/micro-should": {
|
"node_modules/micro-should": {
|
||||||
|
|||||||
163
package.json
163
package.json
@@ -1,14 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "@noble/curves",
|
"name": "@noble/curves",
|
||||||
"version": "0.6.4",
|
"version": "0.8.2",
|
||||||
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
|
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"abstract",
|
||||||
|
"esm",
|
||||||
|
"src",
|
||||||
|
"*.js",
|
||||||
|
"*.js.map",
|
||||||
|
"*.d.ts",
|
||||||
|
"*.d.ts.map"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bench": "cd benchmark; node secp256k1.js; node curves.js; node stark.js; node bls.js",
|
"bench": "cd benchmark; node secp256k1.js; node curves.js; node ecdh.js; node hash-to-curve.js; node modular.js; node bls.js",
|
||||||
"build": "tsc && tsc -p tsconfig.esm.json",
|
"build": "tsc && tsc -p tsconfig.esm.json",
|
||||||
"build:release": "rollup -c rollup.config.js",
|
"build:release": "rollup -c rollup.config.js",
|
||||||
|
"build:clean": "rm *.{js,d.ts,d.ts.map,js.map} esm/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null",
|
||||||
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'",
|
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'",
|
||||||
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'",
|
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'",
|
||||||
"test": "node test/index.test.js"
|
"test": "node test/index.test.js"
|
||||||
@@ -24,12 +31,11 @@
|
|||||||
"@noble/hashes": "1.2.0"
|
"@noble/hashes": "1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@scure/base": "~1.1.1",
|
|
||||||
"@scure/bip32": "~1.1.5",
|
"@scure/bip32": "~1.1.5",
|
||||||
"@scure/bip39": "~1.1.1",
|
"@scure/bip39": "~1.1.1",
|
||||||
"@types/node": "18.11.3",
|
"@types/node": "18.11.3",
|
||||||
"fast-check": "3.0.0",
|
"fast-check": "3.0.0",
|
||||||
"micro-bmark": "0.3.0",
|
"micro-bmark": "0.3.1",
|
||||||
"micro-should": "0.4.0",
|
"micro-should": "0.4.0",
|
||||||
"prettier": "2.8.3",
|
"prettier": "2.8.3",
|
||||||
"typescript": "4.7.3"
|
"typescript": "4.7.3"
|
||||||
@@ -37,129 +43,114 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./index.d.ts",
|
||||||
"import": "./lib/esm/index.js",
|
"import": "./esm/index.js",
|
||||||
"default": "./lib/index.js"
|
"default": "./index.js"
|
||||||
},
|
},
|
||||||
"./abstract/edwards": {
|
"./abstract/edwards": {
|
||||||
"types": "./lib/abstract/edwards.d.ts",
|
"types": "./abstract/edwards.d.ts",
|
||||||
"import": "./lib/esm/abstract/edwards.js",
|
"import": "./esm/abstract/edwards.js",
|
||||||
"default": "./lib/abstract/edwards.js"
|
"default": "./abstract/edwards.js"
|
||||||
},
|
},
|
||||||
"./abstract/modular": {
|
"./abstract/modular": {
|
||||||
"types": "./lib/abstract/modular.d.ts",
|
"types": "./abstract/modular.d.ts",
|
||||||
"import": "./lib/esm/abstract/modular.js",
|
"import": "./esm/abstract/modular.js",
|
||||||
"default": "./lib/abstract/modular.js"
|
"default": "./abstract/modular.js"
|
||||||
},
|
},
|
||||||
"./abstract/montgomery": {
|
"./abstract/montgomery": {
|
||||||
"types": "./lib/abstract/montgomery.d.ts",
|
"types": "./abstract/montgomery.d.ts",
|
||||||
"import": "./lib/esm/abstract/montgomery.js",
|
"import": "./esm/abstract/montgomery.js",
|
||||||
"default": "./lib/abstract/montgomery.js"
|
"default": "./abstract/montgomery.js"
|
||||||
},
|
},
|
||||||
"./abstract/weierstrass": {
|
"./abstract/weierstrass": {
|
||||||
"types": "./lib/abstract/weierstrass.d.ts",
|
"types": "./abstract/weierstrass.d.ts",
|
||||||
"import": "./lib/esm/abstract/weierstrass.js",
|
"import": "./esm/abstract/weierstrass.js",
|
||||||
"default": "./lib/abstract/weierstrass.js"
|
"default": "./abstract/weierstrass.js"
|
||||||
},
|
},
|
||||||
"./abstract/bls": {
|
"./abstract/bls": {
|
||||||
"types": "./lib/abstract/bls.d.ts",
|
"types": "./abstract/bls.d.ts",
|
||||||
"import": "./lib/esm/abstract/bls.js",
|
"import": "./esm/abstract/bls.js",
|
||||||
"default": "./lib/abstract/bls.js"
|
"default": "./abstract/bls.js"
|
||||||
},
|
},
|
||||||
"./abstract/hash-to-curve": {
|
"./abstract/hash-to-curve": {
|
||||||
"types": "./lib/abstract/hash-to-curve.d.ts",
|
"types": "./abstract/hash-to-curve.d.ts",
|
||||||
"import": "./lib/esm/abstract/hash-to-curve.js",
|
"import": "./esm/abstract/hash-to-curve.js",
|
||||||
"default": "./lib/abstract/hash-to-curve.js"
|
"default": "./abstract/hash-to-curve.js"
|
||||||
},
|
},
|
||||||
"./abstract/curve": {
|
"./abstract/curve": {
|
||||||
"types": "./lib/abstract/curve.d.ts",
|
"types": "./abstract/curve.d.ts",
|
||||||
"import": "./lib/esm/abstract/curve.js",
|
"import": "./esm/abstract/curve.js",
|
||||||
"default": "./lib/abstract/curve.js"
|
"default": "./abstract/curve.js"
|
||||||
},
|
},
|
||||||
"./abstract/utils": {
|
"./abstract/utils": {
|
||||||
"types": "./lib/abstract/utils.d.ts",
|
"types": "./abstract/utils.d.ts",
|
||||||
"import": "./lib/esm/abstract/utils.js",
|
"import": "./esm/abstract/utils.js",
|
||||||
"default": "./lib/abstract/utils.js"
|
"default": "./abstract/utils.js"
|
||||||
},
|
},
|
||||||
"./abstract/poseidon": {
|
"./abstract/poseidon": {
|
||||||
"types": "./lib/abstract/poseidon.d.ts",
|
"types": "./abstract/poseidon.d.ts",
|
||||||
"import": "./lib/esm/abstract/poseidon.js",
|
"import": "./esm/abstract/poseidon.js",
|
||||||
"default": "./lib/abstract/poseidon.js"
|
"default": "./abstract/poseidon.js"
|
||||||
},
|
},
|
||||||
"./_shortw_utils": {
|
"./_shortw_utils": {
|
||||||
"types": "./lib/_shortw_utils.d.ts",
|
"types": "./_shortw_utils.d.ts",
|
||||||
"import": "./lib/esm/_shortw_utils.js",
|
"import": "./esm/_shortw_utils.js",
|
||||||
"default": "./lib/_shortw_utils.js"
|
"default": "./_shortw_utils.js"
|
||||||
},
|
},
|
||||||
"./bls12-381": {
|
"./bls12-381": {
|
||||||
"types": "./lib/bls12-381.d.ts",
|
"types": "./bls12-381.d.ts",
|
||||||
"import": "./lib/esm/bls12-381.js",
|
"import": "./esm/bls12-381.js",
|
||||||
"default": "./lib/bls12-381.js"
|
"default": "./bls12-381.js"
|
||||||
},
|
},
|
||||||
"./bn": {
|
"./bn": {
|
||||||
"types": "./lib/bn.d.ts",
|
"types": "./bn.d.ts",
|
||||||
"import": "./lib/esm/bn.js",
|
"import": "./esm/bn.js",
|
||||||
"default": "./lib/bn.js"
|
"default": "./bn.js"
|
||||||
},
|
},
|
||||||
"./ed25519": {
|
"./ed25519": {
|
||||||
"types": "./lib/ed25519.d.ts",
|
"types": "./ed25519.d.ts",
|
||||||
"import": "./lib/esm/ed25519.js",
|
"import": "./esm/ed25519.js",
|
||||||
"default": "./lib/ed25519.js"
|
"default": "./ed25519.js"
|
||||||
},
|
},
|
||||||
"./ed448": {
|
"./ed448": {
|
||||||
"types": "./lib/ed448.d.ts",
|
"types": "./ed448.d.ts",
|
||||||
"import": "./lib/esm/ed448.js",
|
"import": "./esm/ed448.js",
|
||||||
"default": "./lib/ed448.js"
|
"default": "./ed448.js"
|
||||||
},
|
},
|
||||||
"./index": {
|
"./index": {
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./index.d.ts",
|
||||||
"import": "./lib/esm/index.js",
|
"import": "./esm/index.js",
|
||||||
"default": "./lib/index.js"
|
"default": "./index.js"
|
||||||
},
|
},
|
||||||
"./jubjub": {
|
"./jubjub": {
|
||||||
"types": "./lib/jubjub.d.ts",
|
"types": "./jubjub.d.ts",
|
||||||
"import": "./lib/esm/jubjub.js",
|
"import": "./esm/jubjub.js",
|
||||||
"default": "./lib/jubjub.js"
|
"default": "./jubjub.js"
|
||||||
},
|
|
||||||
"./p192": {
|
|
||||||
"types": "./lib/p192.d.ts",
|
|
||||||
"import": "./lib/esm/p192.js",
|
|
||||||
"default": "./lib/p192.js"
|
|
||||||
},
|
|
||||||
"./p224": {
|
|
||||||
"types": "./lib/p224.d.ts",
|
|
||||||
"import": "./lib/esm/p224.js",
|
|
||||||
"default": "./lib/p224.js"
|
|
||||||
},
|
},
|
||||||
"./p256": {
|
"./p256": {
|
||||||
"types": "./lib/p256.d.ts",
|
"types": "./p256.d.ts",
|
||||||
"import": "./lib/esm/p256.js",
|
"import": "./esm/p256.js",
|
||||||
"default": "./lib/p256.js"
|
"default": "./p256.js"
|
||||||
},
|
},
|
||||||
"./p384": {
|
"./p384": {
|
||||||
"types": "./lib/p384.d.ts",
|
"types": "./p384.d.ts",
|
||||||
"import": "./lib/esm/p384.js",
|
"import": "./esm/p384.js",
|
||||||
"default": "./lib/p384.js"
|
"default": "./p384.js"
|
||||||
},
|
},
|
||||||
"./p521": {
|
"./p521": {
|
||||||
"types": "./lib/p521.d.ts",
|
"types": "./p521.d.ts",
|
||||||
"import": "./lib/esm/p521.js",
|
"import": "./esm/p521.js",
|
||||||
"default": "./lib/p521.js"
|
"default": "./p521.js"
|
||||||
},
|
},
|
||||||
"./pasta": {
|
"./pasta": {
|
||||||
"types": "./lib/pasta.d.ts",
|
"types": "./pasta.d.ts",
|
||||||
"import": "./lib/esm/pasta.js",
|
"import": "./esm/pasta.js",
|
||||||
"default": "./lib/pasta.js"
|
"default": "./pasta.js"
|
||||||
},
|
},
|
||||||
"./secp256k1": {
|
"./secp256k1": {
|
||||||
"types": "./lib/secp256k1.d.ts",
|
"types": "./secp256k1.d.ts",
|
||||||
"import": "./lib/esm/secp256k1.js",
|
"import": "./esm/secp256k1.js",
|
||||||
"default": "./lib/secp256k1.js"
|
"default": "./secp256k1.js"
|
||||||
},
|
|
||||||
"./stark": {
|
|
||||||
"types": "./lib/stark.d.ts",
|
|
||||||
"import": "./lib/esm/stark.js",
|
|
||||||
"default": "./lib/stark.js"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|||||||
import { weierstrass, CurveType } from './abstract/weierstrass.js';
|
import { weierstrass, CurveType } from './abstract/weierstrass.js';
|
||||||
import { CHash } from './abstract/utils.js';
|
import { CHash } from './abstract/utils.js';
|
||||||
|
|
||||||
|
// connects noble-curves to noble-hashes
|
||||||
export function getHash(hash: CHash) {
|
export function getHash(hash: CHash) {
|
||||||
return {
|
return {
|
||||||
hash,
|
hash,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
import { AffinePoint } from './curve.js';
|
import { AffinePoint } from './curve.js';
|
||||||
import { Field, hashToPrivateScalar } from './modular.js';
|
import { Field, hashToPrivateScalar } from './modular.js';
|
||||||
import { Hex, PrivKey, CHash, bitLen, bitGet, hexToBytes, bytesToHex } from './utils.js';
|
import { Hex, PrivKey, CHash, bitLen, bitGet, ensureBytes } from './utils.js';
|
||||||
import * as htf from './hash-to-curve.js';
|
import * as htf from './hash-to-curve.js';
|
||||||
import {
|
import {
|
||||||
CurvePointsType,
|
CurvePointsType,
|
||||||
@@ -67,16 +67,11 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
|
|||||||
Fp2: Field<Fp2>;
|
Fp2: Field<Fp2>;
|
||||||
Fp6: Field<Fp6>;
|
Fp6: Field<Fp6>;
|
||||||
Fp12: Field<Fp12>;
|
Fp12: Field<Fp12>;
|
||||||
G1: CurvePointsRes<Fp>;
|
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
|
||||||
G2: CurvePointsRes<Fp2>;
|
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
|
||||||
Signature: SignatureCoder<Fp2>;
|
Signature: SignatureCoder<Fp2>;
|
||||||
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
|
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
|
||||||
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
|
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
|
||||||
// prettier-ignore
|
|
||||||
hashToCurve: {
|
|
||||||
G1: ReturnType<(typeof htf.hashToCurve<Fp>)>,
|
|
||||||
G2: ReturnType<(typeof htf.hashToCurve<Fp2>)>,
|
|
||||||
},
|
|
||||||
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
|
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
|
||||||
getPublicKey: (privateKey: PrivKey) => Uint8Array;
|
getPublicKey: (privateKey: PrivKey) => Uint8Array;
|
||||||
sign: {
|
sign: {
|
||||||
@@ -102,16 +97,14 @@ export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
|
|||||||
publicKeys: (Hex | ProjPointType<Fp>)[]
|
publicKeys: (Hex | ProjPointType<Fp>)[]
|
||||||
) => boolean;
|
) => boolean;
|
||||||
utils: {
|
utils: {
|
||||||
stringToBytes: typeof htf.stringToBytes;
|
randomPrivateKey: () => Uint8Array;
|
||||||
hashToField: typeof htf.hash_to_field;
|
|
||||||
expandMessageXMD: typeof htf.expand_message_xmd;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function bls<Fp2, Fp6, Fp12>(
|
export function bls<Fp2, Fp6, Fp12>(
|
||||||
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>
|
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>
|
||||||
): CurveFn<Fp, Fp2, Fp6, Fp12> {
|
): CurveFn<Fp, Fp2, Fp6, Fp12> {
|
||||||
// Fields looks pretty specific for curve, so for now we need to pass them with options
|
// Fields looks pretty specific for curve, so for now we need to pass them with opts
|
||||||
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
|
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
|
||||||
const BLS_X_LEN = bitLen(CURVE.x);
|
const BLS_X_LEN = bitLen(CURVE.x);
|
||||||
const groupLen = 32; // TODO: calculate; hardcoded for now
|
const groupLen = 32; // TODO: calculate; hardcoded for now
|
||||||
@@ -180,31 +173,20 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const utils = {
|
const utils = {
|
||||||
hexToBytes: hexToBytes,
|
randomPrivateKey: (): Uint8Array => {
|
||||||
bytesToHex: bytesToHex,
|
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.r));
|
||||||
stringToBytes: htf.stringToBytes,
|
},
|
||||||
// TODO: do we need to export it here?
|
|
||||||
hashToField: (
|
|
||||||
msg: Uint8Array,
|
|
||||||
count: number,
|
|
||||||
options: Partial<typeof CURVE.htfDefaults> = {}
|
|
||||||
) => htf.hash_to_field(msg, count, { ...CURVE.htfDefaults, ...options }),
|
|
||||||
expandMessageXMD: (msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H = CURVE.hash) =>
|
|
||||||
htf.expand_message_xmd(msg, DST, lenInBytes, H),
|
|
||||||
hashToPrivateKey: (hash: Hex): Uint8Array => Fr.toBytes(hashToPrivateScalar(hash, CURVE.r)),
|
|
||||||
randomBytes: (bytesLength: number = groupLen): Uint8Array => CURVE.randomBytes(bytesLength),
|
|
||||||
randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Point on G1 curve: (x, y)
|
// Point on G1 curve: (x, y)
|
||||||
const G1 = weierstrassPoints({
|
const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 });
|
||||||
n: Fr.ORDER,
|
const G1 = Object.assign(
|
||||||
...CURVE.G1,
|
G1_,
|
||||||
});
|
htf.createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
|
||||||
const G1HashToCurve = htf.hashToCurve(G1.ProjectivePoint, CURVE.G1.mapToCurve, {
|
|
||||||
...CURVE.htfDefaults,
|
...CURVE.htfDefaults,
|
||||||
...CURVE.G1.htfDefaults,
|
...CURVE.G1.htfDefaults,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// Sparse multiplication against precomputed coefficients
|
// Sparse multiplication against precomputed coefficients
|
||||||
// TODO: replace with weakmap?
|
// TODO: replace with weakmap?
|
||||||
@@ -223,15 +205,14 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
||||||
const G2 = weierstrassPoints({
|
const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 });
|
||||||
n: Fr.ORDER,
|
const G2 = Object.assign(
|
||||||
...CURVE.G2,
|
G2_,
|
||||||
});
|
htf.createHasher(G2_.ProjectivePoint as htf.H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
|
||||||
const C = G2.ProjectivePoint as htf.H2CPointConstructor<Fp2>; // TODO: fix
|
|
||||||
const G2HashToCurve = htf.hashToCurve(C, CURVE.G2.mapToCurve, {
|
|
||||||
...CURVE.htfDefaults,
|
...CURVE.htfDefaults,
|
||||||
...CURVE.G2.htfDefaults,
|
...CURVE.G2.htfDefaults,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const { Signature } = CURVE.G2;
|
const { Signature } = CURVE.G2;
|
||||||
|
|
||||||
@@ -260,7 +241,7 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {
|
function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {
|
||||||
return point instanceof G2.ProjectivePoint
|
return point instanceof G2.ProjectivePoint
|
||||||
? point
|
? point
|
||||||
: (G2HashToCurve.hashToCurve(point, htfOpts) as G2);
|
: (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies generator by private key.
|
// Multiplies generator by private key.
|
||||||
@@ -276,7 +257,7 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htf.htfBasicOpts): Uint8Array | G2 {
|
function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htf.htfBasicOpts): Uint8Array | G2 {
|
||||||
const msgPoint = normP2Hash(message, htfOpts);
|
const msgPoint = normP2Hash(message, htfOpts);
|
||||||
msgPoint.assertValidity();
|
msgPoint.assertValidity();
|
||||||
const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
|
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
|
||||||
if (message instanceof G2.ProjectivePoint) return sigPoint;
|
if (message instanceof G2.ProjectivePoint) return sigPoint;
|
||||||
return Signature.encode(sigPoint);
|
return Signature.encode(sigPoint);
|
||||||
}
|
}
|
||||||
@@ -383,7 +364,6 @@ export function bls<Fp2, Fp6, Fp12>(
|
|||||||
Signature,
|
Signature,
|
||||||
millerLoop,
|
millerLoop,
|
||||||
calcPairingPrecomputes,
|
calcPairingPrecomputes,
|
||||||
hashToCurve: { G1: G1HashToCurve, G2: G2HashToCurve },
|
|
||||||
pairing,
|
pairing,
|
||||||
getPublicKey,
|
getPublicKey,
|
||||||
sign,
|
sign,
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
static fromHex(hex: Hex, strict = true): Point {
|
static fromHex(hex: Hex, strict = true): Point {
|
||||||
const { d, a } = CURVE;
|
const { d, a } = CURVE;
|
||||||
const len = Fp.BYTES;
|
const len = Fp.BYTES;
|
||||||
hex = ensureBytes(hex, len); // copy hex to a new array
|
hex = ensureBytes('pointHex', hex, len); // copy hex to a new array
|
||||||
const normed = hex.slice(); // copy again, we'll manipulate it
|
const normed = hex.slice(); // copy again, we'll manipulate it
|
||||||
const lastByte = hex[len - 1]; // select last byte
|
const lastByte = hex[len - 1]; // select last byte
|
||||||
normed[len - 1] = lastByte & ~0x80; // clear last bit
|
normed[len - 1] = lastByte & ~0x80; // clear last bit
|
||||||
@@ -392,18 +392,14 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
function modN_LE(hash: Uint8Array): bigint {
|
function modN_LE(hash: Uint8Array): bigint {
|
||||||
return modN(ut.bytesToNumberLE(hash));
|
return modN(ut.bytesToNumberLE(hash));
|
||||||
}
|
}
|
||||||
function isHex(item: Hex, err: string) {
|
|
||||||
if (typeof item !== 'string' && !(item instanceof Uint8Array))
|
|
||||||
throw new Error(`${err} must be hex string or Uint8Array`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */
|
/** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */
|
||||||
function getExtendedPublicKey(key: Hex) {
|
function getExtendedPublicKey(key: Hex) {
|
||||||
isHex(key, 'private key');
|
|
||||||
const len = nByteLength;
|
const len = nByteLength;
|
||||||
|
key = ensureBytes('private key', key, len);
|
||||||
// Hash private key with curve's hash function to produce uniformingly random input
|
// Hash private key with curve's hash function to produce uniformingly random input
|
||||||
// Check byte lengths: ensure(64, h(ensure(32, key)))
|
// Check byte lengths: ensure(64, h(ensure(32, key)))
|
||||||
const hashed = ensureBytes(cHash(ensureBytes(key, len)), 2 * len);
|
const hashed = ensureBytes('hashed private key', cHash(key), 2 * len);
|
||||||
const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE
|
const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE
|
||||||
const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)
|
const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)
|
||||||
const scalar = modN_LE(head); // The actual private scalar
|
const scalar = modN_LE(head); // The actual private scalar
|
||||||
@@ -420,13 +416,12 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
// int('LE', SHA512(dom2(F, C) || msgs)) mod N
|
// int('LE', SHA512(dom2(F, C) || msgs)) mod N
|
||||||
function hashDomainToScalar(context: Hex = new Uint8Array(), ...msgs: Uint8Array[]) {
|
function hashDomainToScalar(context: Hex = new Uint8Array(), ...msgs: Uint8Array[]) {
|
||||||
const msg = ut.concatBytes(...msgs);
|
const msg = ut.concatBytes(...msgs);
|
||||||
return modN_LE(cHash(domain(msg, ensureBytes(context), !!preHash)));
|
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!preHash)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Signs message with privateKey. RFC8032 5.1.6 */
|
/** Signs message with privateKey. RFC8032 5.1.6 */
|
||||||
function sign(msg: Hex, privKey: Hex, context?: Hex): Uint8Array {
|
function sign(msg: Hex, privKey: Hex, context?: Hex): Uint8Array {
|
||||||
isHex(msg, 'message');
|
msg = ensureBytes('message', msg);
|
||||||
msg = ensureBytes(msg);
|
|
||||||
if (preHash) msg = preHash(msg); // for ed25519ph etc.
|
if (preHash) msg = preHash(msg); // for ed25519ph etc.
|
||||||
const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
|
const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
|
||||||
const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
|
const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
|
||||||
@@ -435,15 +430,13 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
const s = modN(r + k * scalar); // S = (r + k * s) mod L
|
const s = modN(r + k * scalar); // S = (r + k * s) mod L
|
||||||
assertGE0(s); // 0 <= s < l
|
assertGE0(s); // 0 <= s < l
|
||||||
const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
|
const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
|
||||||
return ensureBytes(res, nByteLength * 2); // 64-byte signature
|
return ensureBytes('result', res, nByteLength * 2); // 64-byte signature
|
||||||
}
|
}
|
||||||
|
|
||||||
function verify(sig: Hex, msg: Hex, publicKey: Hex, context?: Hex): boolean {
|
function verify(sig: Hex, msg: Hex, publicKey: Hex, context?: Hex): boolean {
|
||||||
isHex(sig, 'sig');
|
|
||||||
isHex(msg, 'message');
|
|
||||||
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
|
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
|
||||||
sig = ensureBytes(sig, 2 * len); // An extended group equation is checked.
|
sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
|
||||||
msg = ensureBytes(msg); // ZIP215 compliant, which means not fully RFC8032 compliant.
|
msg = ensureBytes('message', msg); // ZIP215 compliant, which means not fully RFC8032 compliant.
|
||||||
if (preHash) msg = preHash(msg); // for ed25519ph, etc
|
if (preHash) msg = preHash(msg); // for ed25519ph, etc
|
||||||
const A = Point.fromHex(publicKey, false); // Check for s bounds, hex validity
|
const A = Point.fromHex(publicKey, false); // Check for s bounds, hex validity
|
||||||
const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
|
const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
|
||||||
|
|||||||
@@ -1,45 +1,36 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
|
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
|
||||||
import { mod, Field } from './modular.js';
|
import { mod, Field } from './modular.js';
|
||||||
import { CHash, Hex, concatBytes, ensureBytes, validateObject } from './utils.js';
|
import { bytesToNumberBE, CHash, concatBytes, utf8ToBytes, validateObject } from './utils.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * `DST` is a domain separation tag, defined in section 2.2.5
|
||||||
|
* * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
|
||||||
|
* * `m` is extension degree (1 for prime fields)
|
||||||
|
* * `k` is the target security target in bits (e.g. 128), from section 5.1
|
||||||
|
* * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF)
|
||||||
|
* * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
|
||||||
|
*/
|
||||||
|
type UnicodeOrBytes = string | Uint8Array;
|
||||||
export type Opts = {
|
export type Opts = {
|
||||||
DST: string; // DST: a domain separation tag, defined in section 2.2.5
|
DST: UnicodeOrBytes;
|
||||||
encodeDST: string;
|
p: bigint;
|
||||||
p: bigint; // characteristic of F, where F is a finite field of characteristic p and order q = p^m
|
m: number;
|
||||||
m: number; // extension degree of F, m >= 1
|
k: number;
|
||||||
k: number; // k: the target security level for the suite in bits, defined in section 5.1
|
expand?: 'xmd' | 'xof';
|
||||||
expand?: 'xmd' | 'xof'; // use a message that has already been processed by expand_message_xmd
|
|
||||||
// Hash functions for: expand_message_xmd is appropriate for use with a
|
|
||||||
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
|
||||||
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
|
||||||
// TODO: verify that hash is shake if expand==='xof' via types
|
|
||||||
hash: CHash;
|
hash: CHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global symbols in both browsers and Node.js since v11
|
function validateDST(dst: UnicodeOrBytes): Uint8Array {
|
||||||
// See https://github.com/microsoft/TypeScript/issues/31535
|
if (dst instanceof Uint8Array) return dst;
|
||||||
declare const TextEncoder: any;
|
if (typeof dst === 'string') return utf8ToBytes(dst);
|
||||||
declare const TextDecoder: any;
|
throw new Error('DST must be Uint8Array or string');
|
||||||
|
|
||||||
export function stringToBytes(str: string): Uint8Array {
|
|
||||||
if (typeof str !== 'string') {
|
|
||||||
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
||||||
}
|
|
||||||
return new TextEncoder().encode(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Octet Stream to Integer (bytesToNumberBE)
|
// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
|
||||||
function os2ip(bytes: Uint8Array): bigint {
|
const os2ip = bytesToNumberBE;
|
||||||
let result = 0n;
|
|
||||||
for (let i = 0; i < bytes.length; i++) {
|
|
||||||
result <<= 8n;
|
|
||||||
result += BigInt(bytes[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer to Octet Stream
|
// Integer to Octet Stream (numberToBytesBE)
|
||||||
function i2osp(value: number, length: number): Uint8Array {
|
function i2osp(value: number, length: number): Uint8Array {
|
||||||
if (value < 0 || value >= 1 << (8 * length)) {
|
if (value < 0 || value >= 1 << (8 * length)) {
|
||||||
throw new Error(`bad I2OSP call: value=${value} length=${length}`);
|
throw new Error(`bad I2OSP call: value=${value} length=${length}`);
|
||||||
@@ -60,6 +51,13 @@ function strxor(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isBytes(item: unknown): void {
|
||||||
|
if (!(item instanceof Uint8Array)) throw new Error('Uint8Array expected');
|
||||||
|
}
|
||||||
|
function isNum(item: unknown): void {
|
||||||
|
if (!Number.isSafeInteger(item)) throw new Error('number expected');
|
||||||
|
}
|
||||||
|
|
||||||
// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits
|
// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1
|
||||||
export function expand_message_xmd(
|
export function expand_message_xmd(
|
||||||
@@ -68,15 +66,17 @@ export function expand_message_xmd(
|
|||||||
lenInBytes: number,
|
lenInBytes: number,
|
||||||
H: CHash
|
H: CHash
|
||||||
): Uint8Array {
|
): Uint8Array {
|
||||||
|
isBytes(msg);
|
||||||
|
isBytes(DST);
|
||||||
|
isNum(lenInBytes);
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
||||||
if (DST.length > 255) DST = H(concatBytes(stringToBytes('H2C-OVERSIZE-DST-'), DST));
|
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
|
||||||
const b_in_bytes = H.outputLen;
|
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
|
||||||
const r_in_bytes = H.blockLen;
|
|
||||||
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
||||||
if (ell > 255) throw new Error('Invalid xmd length');
|
if (ell > 255) throw new Error('Invalid xmd length');
|
||||||
const DST_prime = concatBytes(DST, i2osp(DST.length, 1));
|
const DST_prime = concatBytes(DST, i2osp(DST.length, 1));
|
||||||
const Z_pad = i2osp(0, r_in_bytes);
|
const Z_pad = i2osp(0, r_in_bytes);
|
||||||
const l_i_b_str = i2osp(lenInBytes, 2);
|
const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str
|
||||||
const b = new Array<Uint8Array>(ell);
|
const b = new Array<Uint8Array>(ell);
|
||||||
const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));
|
const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));
|
||||||
b[0] = H(concatBytes(b_0, i2osp(1, 1), DST_prime));
|
b[0] = H(concatBytes(b_0, i2osp(1, 1), DST_prime));
|
||||||
@@ -95,11 +95,14 @@ export function expand_message_xof(
|
|||||||
k: number,
|
k: number,
|
||||||
H: CHash
|
H: CHash
|
||||||
): Uint8Array {
|
): Uint8Array {
|
||||||
|
isBytes(msg);
|
||||||
|
isBytes(DST);
|
||||||
|
isNum(lenInBytes);
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
||||||
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
||||||
if (DST.length > 255) {
|
if (DST.length > 255) {
|
||||||
const dkLen = Math.ceil((2 * k) / 8);
|
const dkLen = Math.ceil((2 * k) / 8);
|
||||||
DST = H.create({ dkLen }).update(stringToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
||||||
}
|
}
|
||||||
if (lenInBytes > 65535 || DST.length > 255)
|
if (lenInBytes > 65535 || DST.length > 255)
|
||||||
throw new Error('expand_message_xof: invalid lenInBytes');
|
throw new Error('expand_message_xof: invalid lenInBytes');
|
||||||
@@ -119,29 +122,41 @@ export function expand_message_xof(
|
|||||||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
|
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
|
||||||
* @param msg a byte string containing the message to hash
|
* @param msg a byte string containing the message to hash
|
||||||
* @param count the number of elements of F to output
|
* @param count the number of elements of F to output
|
||||||
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
|
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
|
||||||
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
||||||
*/
|
*/
|
||||||
export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] {
|
export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] {
|
||||||
// if options is provided but incomplete, fill any missing fields with the
|
validateObject(options, {
|
||||||
// value in hftDefaults (ie hash to G2).
|
DST: 'string',
|
||||||
const log2p = options.p.toString(2).length;
|
p: 'bigint',
|
||||||
const L = Math.ceil((log2p + options.k) / 8); // section 5.1 of ietf draft link above
|
m: 'isSafeInteger',
|
||||||
const len_in_bytes = count * options.m * L;
|
k: 'isSafeInteger',
|
||||||
const DST = stringToBytes(options.DST);
|
hash: 'hash',
|
||||||
let pseudo_random_bytes = msg;
|
});
|
||||||
if (options.expand === 'xmd') {
|
const { p, k, m, hash, expand, DST: _DST } = options;
|
||||||
pseudo_random_bytes = expand_message_xmd(msg, DST, len_in_bytes, options.hash);
|
isBytes(msg);
|
||||||
} else if (options.expand === 'xof') {
|
isNum(count);
|
||||||
pseudo_random_bytes = expand_message_xof(msg, DST, len_in_bytes, options.k, options.hash);
|
const DST = validateDST(_DST);
|
||||||
|
const log2p = p.toString(2).length;
|
||||||
|
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
|
||||||
|
const len_in_bytes = count * m * L;
|
||||||
|
let prb; // pseudo_random_bytes
|
||||||
|
if (expand === 'xmd') {
|
||||||
|
prb = expand_message_xmd(msg, DST, len_in_bytes, hash);
|
||||||
|
} else if (expand === 'xof') {
|
||||||
|
prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);
|
||||||
|
} else if (expand === undefined) {
|
||||||
|
prb = msg;
|
||||||
|
} else {
|
||||||
|
throw new Error('expand must be "xmd", "xof" or undefined');
|
||||||
}
|
}
|
||||||
const u = new Array(count);
|
const u = new Array(count);
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const e = new Array(options.m);
|
const e = new Array(m);
|
||||||
for (let j = 0; j < options.m; j++) {
|
for (let j = 0; j < m; j++) {
|
||||||
const elm_offset = L * (j + i * options.m);
|
const elm_offset = L * (j + i * m);
|
||||||
const tv = pseudo_random_bytes.subarray(elm_offset, elm_offset + L);
|
const tv = prb.subarray(elm_offset, elm_offset + L);
|
||||||
e[j] = mod(os2ip(tv), options.p);
|
e[j] = mod(os2ip(tv), p);
|
||||||
}
|
}
|
||||||
u[i] = e;
|
u[i] = e;
|
||||||
}
|
}
|
||||||
@@ -176,42 +191,28 @@ export type MapToCurve<T> = (scalar: bigint[]) => AffinePoint<T>;
|
|||||||
|
|
||||||
// Separated from initialization opts, so users won't accidentally change per-curve parameters
|
// Separated from initialization opts, so users won't accidentally change per-curve parameters
|
||||||
// (changing DST is ok!)
|
// (changing DST is ok!)
|
||||||
export type htfBasicOpts = { DST: string };
|
export type htfBasicOpts = { DST: UnicodeOrBytes };
|
||||||
|
|
||||||
export function hashToCurve<T>(
|
export function createHasher<T>(
|
||||||
Point: H2CPointConstructor<T>,
|
Point: H2CPointConstructor<T>,
|
||||||
mapToCurve: MapToCurve<T>,
|
mapToCurve: MapToCurve<T>,
|
||||||
def: Opts
|
def: Opts & { encodeDST?: UnicodeOrBytes }
|
||||||
) {
|
) {
|
||||||
validateObject(def, {
|
if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined');
|
||||||
DST: 'string',
|
|
||||||
p: 'bigint',
|
|
||||||
m: 'isSafeInteger',
|
|
||||||
k: 'isSafeInteger',
|
|
||||||
hash: 'hash',
|
|
||||||
});
|
|
||||||
if (def.expand !== 'xmd' && def.expand !== 'xof' && def.expand !== undefined)
|
|
||||||
throw new Error('Invalid htf/expand');
|
|
||||||
if (typeof mapToCurve !== 'function')
|
|
||||||
throw new Error('hashToCurve: mapToCurve() has not been defined');
|
|
||||||
return {
|
return {
|
||||||
// Encodes byte string to elliptic curve
|
// Encodes byte string to elliptic curve
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
||||||
hashToCurve(msg: Hex, options?: htfBasicOpts) {
|
hashToCurve(msg: Uint8Array, options?: htfBasicOpts) {
|
||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
|
||||||
msg = ensureBytes(msg);
|
|
||||||
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
||||||
const P = Point.fromAffine(mapToCurve(u[0]))
|
const u0 = Point.fromAffine(mapToCurve(u[0]));
|
||||||
.add(Point.fromAffine(mapToCurve(u[1])))
|
const u1 = Point.fromAffine(mapToCurve(u[1]));
|
||||||
.clearCofactor();
|
const P = u0.add(u1).clearCofactor();
|
||||||
P.assertValidity();
|
P.assertValidity();
|
||||||
return P;
|
return P;
|
||||||
},
|
},
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
||||||
encodeToCurve(msg: Hex, options?: htfBasicOpts) {
|
encodeToCurve(msg: Uint8Array, options?: htfBasicOpts) {
|
||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
|
||||||
msg = ensureBytes(msg);
|
|
||||||
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
||||||
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
||||||
P.assertValidity();
|
P.assertValidity();
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export function invert(number: bigint, modulo: bigint): bigint {
|
|||||||
throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
|
throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
|
||||||
}
|
}
|
||||||
// Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
|
// Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
|
||||||
|
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
|
||||||
let a = mod(number, modulo);
|
let a = mod(number, modulo);
|
||||||
let b = modulo;
|
let b = modulo;
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
@@ -407,7 +408,7 @@ export function hashToPrivateScalar(
|
|||||||
groupOrder: bigint,
|
groupOrder: bigint,
|
||||||
isLE = false
|
isLE = false
|
||||||
): bigint {
|
): bigint {
|
||||||
hash = ensureBytes(hash);
|
hash = ensureBytes('privateHash', hash);
|
||||||
const hashLen = hash.length;
|
const hashLen = hash.length;
|
||||||
const minLen = nLength(groupOrder).nByteLength + 8;
|
const minLen = nLength(groupOrder).nByteLength + 8;
|
||||||
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
||||||
|
|||||||
@@ -11,25 +11,27 @@ export type CurveType = {
|
|||||||
nByteLength: number;
|
nByteLength: number;
|
||||||
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
|
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
|
||||||
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
|
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
|
||||||
a24: bigint; // Related to d, but cannot be derived from it
|
a: bigint;
|
||||||
montgomeryBits: number;
|
montgomeryBits: number;
|
||||||
powPminus2?: (x: bigint) => bigint;
|
powPminus2?: (x: bigint) => bigint;
|
||||||
xyToU?: (x: bigint, y: bigint) => bigint;
|
xyToU?: (x: bigint, y: bigint) => bigint;
|
||||||
Gu: string;
|
Gu: bigint;
|
||||||
|
randomBytes?: (bytesLength?: number) => Uint8Array;
|
||||||
};
|
};
|
||||||
export type CurveFn = {
|
export type CurveFn = {
|
||||||
scalarMult: (scalar: Hex, u: Hex) => Uint8Array;
|
scalarMult: (scalar: Hex, u: Hex) => Uint8Array;
|
||||||
scalarMultBase: (scalar: Hex) => Uint8Array;
|
scalarMultBase: (scalar: Hex) => Uint8Array;
|
||||||
getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array;
|
getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array;
|
||||||
getPublicKey: (privateKey: Hex) => Uint8Array;
|
getPublicKey: (privateKey: Hex) => Uint8Array;
|
||||||
Gu: string;
|
utils: { randomPrivateKey: () => Uint8Array };
|
||||||
|
GuBytes: Uint8Array;
|
||||||
};
|
};
|
||||||
|
|
||||||
function validateOpts(curve: CurveType) {
|
function validateOpts(curve: CurveType) {
|
||||||
validateObject(
|
validateObject(
|
||||||
curve,
|
curve,
|
||||||
{
|
{
|
||||||
a24: 'bigint',
|
a: 'bigint',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
montgomeryBits: 'isSafeInteger',
|
montgomeryBits: 'isSafeInteger',
|
||||||
@@ -37,7 +39,7 @@ function validateOpts(curve: CurveType) {
|
|||||||
adjustScalarBytes: 'function',
|
adjustScalarBytes: 'function',
|
||||||
domain: 'function',
|
domain: 'function',
|
||||||
powPminus2: 'function',
|
powPminus2: 'function',
|
||||||
Gu: 'string',
|
Gu: 'bigint',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Set defaults
|
// Set defaults
|
||||||
@@ -49,7 +51,7 @@ function validateOpts(curve: CurveType) {
|
|||||||
export function montgomery(curveDef: CurveType): CurveFn {
|
export function montgomery(curveDef: CurveType): CurveFn {
|
||||||
const CURVE = validateOpts(curveDef);
|
const CURVE = validateOpts(curveDef);
|
||||||
const { P } = CURVE;
|
const { P } = CURVE;
|
||||||
const modP = (a: bigint) => mod(a, P);
|
const modP = (n: bigint) => mod(n, P);
|
||||||
const montgomeryBits = CURVE.montgomeryBits;
|
const montgomeryBits = CURVE.montgomeryBits;
|
||||||
const montgomeryBytes = Math.ceil(montgomeryBits / 8);
|
const montgomeryBytes = Math.ceil(montgomeryBits / 8);
|
||||||
const fieldLen = CURVE.nByteLength;
|
const fieldLen = CURVE.nByteLength;
|
||||||
@@ -73,12 +75,15 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|||||||
return [x_2, x_3];
|
return [x_2, x_3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accepts 0 as well
|
||||||
function assertFieldElement(n: bigint): bigint {
|
function assertFieldElement(n: bigint): bigint {
|
||||||
if (typeof n === 'bigint' && _0n <= n && n < P) return n;
|
if (typeof n === 'bigint' && _0n <= n && n < P) return n;
|
||||||
throw new Error('Expected valid scalar 0 < scalar < CURVE.P');
|
throw new Error('Expected valid scalar 0 < scalar < CURVE.P');
|
||||||
}
|
}
|
||||||
|
|
||||||
// x25519 from 4
|
// x25519 from 4
|
||||||
|
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
|
||||||
|
const a24 = (CURVE.a - BigInt(2)) / BigInt(4);
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param pointU u coordinate (x) on Montgomery Curve 25519
|
* @param pointU u coordinate (x) on Montgomery Curve 25519
|
||||||
@@ -90,8 +95,6 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|||||||
// Section 5: Implementations MUST accept non-canonical values and process them as
|
// Section 5: Implementations MUST accept non-canonical values and process them as
|
||||||
// if they had been reduced modulo the field prime.
|
// if they had been reduced modulo the field prime.
|
||||||
const k = assertFieldElement(scalar);
|
const k = assertFieldElement(scalar);
|
||||||
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
|
|
||||||
const a24 = CURVE.a24;
|
|
||||||
const x_1 = u;
|
const x_1 = u;
|
||||||
let x_2 = _1n;
|
let x_2 = _1n;
|
||||||
let z_2 = _0n;
|
let z_2 = _0n;
|
||||||
@@ -149,13 +152,13 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|||||||
// MUST mask the most significant bit in the final byte.
|
// MUST mask the most significant bit in the final byte.
|
||||||
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
||||||
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
||||||
const u = ensureBytes(uEnc, montgomeryBytes);
|
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
|
||||||
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
|
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
|
||||||
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
|
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
|
||||||
return bytesToNumberLE(u);
|
return bytesToNumberLE(u);
|
||||||
}
|
}
|
||||||
function decodeScalar(n: Hex): bigint {
|
function decodeScalar(n: Hex): bigint {
|
||||||
const bytes = ensureBytes(n);
|
const bytes = ensureBytes('scalar', n);
|
||||||
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
|
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
|
||||||
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
|
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
|
||||||
return bytesToNumberLE(adjustScalarBytes(bytes));
|
return bytesToNumberLE(adjustScalarBytes(bytes));
|
||||||
@@ -170,8 +173,9 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|||||||
return encodeUCoordinate(pu);
|
return encodeUCoordinate(pu);
|
||||||
}
|
}
|
||||||
// Computes public key from private. By doing scalar multiplication of base point.
|
// Computes public key from private. By doing scalar multiplication of base point.
|
||||||
|
const GuBytes = encodeUCoordinate(CURVE.Gu);
|
||||||
function scalarMultBase(scalar: Hex): Uint8Array {
|
function scalarMultBase(scalar: Hex): Uint8Array {
|
||||||
return scalarMult(scalar, CURVE.Gu);
|
return scalarMult(scalar, GuBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -179,6 +183,7 @@ export function montgomery(curveDef: CurveType): CurveFn {
|
|||||||
scalarMultBase,
|
scalarMultBase,
|
||||||
getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey),
|
getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey),
|
||||||
getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey),
|
getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey),
|
||||||
Gu: CURVE.Gu,
|
utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) },
|
||||||
|
GuBytes: GuBytes,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ export function numberToHexUnpadded(num: number | bigint): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function hexToNumber(hex: string): bigint {
|
export function hexToNumber(hex: string): bigint {
|
||||||
if (typeof hex !== 'string') throw new Error('string expected, got ' + typeof hex);
|
if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
|
||||||
// Big Endian
|
// Big Endian
|
||||||
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caching slows it down 2-3x
|
// Caching slows it down 2-3x
|
||||||
export function hexToBytes(hex: string): Uint8Array {
|
export function hexToBytes(hex: string): Uint8Array {
|
||||||
if (typeof hex !== 'string') throw new Error('string expected, got ' + typeof hex);
|
if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
|
||||||
if (hex.length % 2) throw new Error('hex string is invalid: unpadded ' + hex.length);
|
if (hex.length % 2) throw new Error('hex string is invalid: unpadded ' + hex.length);
|
||||||
const array = new Uint8Array(hex.length / 2);
|
const array = new Uint8Array(hex.length / 2);
|
||||||
for (let i = 0; i < array.length; i++) {
|
for (let i = 0; i < array.length; i++) {
|
||||||
@@ -68,13 +68,25 @@ export const numberToBytesLE = (n: bigint, len: number) => numberToBytesBE(n, le
|
|||||||
// Returns variable number bytes (minimal bigint encoding?)
|
// Returns variable number bytes (minimal bigint encoding?)
|
||||||
export const numberToVarBytesBE = (n: bigint) => hexToBytes(numberToHexUnpadded(n));
|
export const numberToVarBytesBE = (n: bigint) => hexToBytes(numberToHexUnpadded(n));
|
||||||
|
|
||||||
export function ensureBytes(hex: Hex, expectedLength?: number): Uint8Array {
|
export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array {
|
||||||
|
let res: Uint8Array;
|
||||||
|
if (typeof hex === 'string') {
|
||||||
|
try {
|
||||||
|
res = hexToBytes(hex);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
|
||||||
|
}
|
||||||
|
} else if (u8a(hex)) {
|
||||||
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
||||||
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
||||||
const bytes = u8a(hex) ? Uint8Array.from(hex) : hexToBytes(hex);
|
res = Uint8Array.from(hex);
|
||||||
if (typeof expectedLength === 'number' && bytes.length !== expectedLength)
|
} else {
|
||||||
throw new Error(`Expected ${expectedLength} bytes`);
|
throw new Error(`${title} must be hex string or Uint8Array`);
|
||||||
return bytes;
|
}
|
||||||
|
const len = res.length;
|
||||||
|
if (typeof expectedLength === 'number' && len !== expectedLength)
|
||||||
|
throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies several Uint8Arrays into one.
|
// Copies several Uint8Arrays into one.
|
||||||
@@ -96,6 +108,16 @@ export function equalBytes(b1: Uint8Array, b2: Uint8Array) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global symbols in both browsers and Node.js since v11
|
||||||
|
// See https://github.com/microsoft/TypeScript/issues/31535
|
||||||
|
declare const TextEncoder: any;
|
||||||
|
export function utf8ToBytes(str: string): Uint8Array {
|
||||||
|
if (typeof str !== 'string') {
|
||||||
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
||||||
|
}
|
||||||
|
return new TextEncoder().encode(str);
|
||||||
|
}
|
||||||
|
|
||||||
// Bit operations
|
// Bit operations
|
||||||
|
|
||||||
// Amount of bits inside bigint (Same as n.toString(2).length)
|
// Amount of bits inside bigint (Same as n.toString(2).length)
|
||||||
@@ -114,6 +136,70 @@ export const bitSet = (n: bigint, pos: number, value: boolean) =>
|
|||||||
// Not using ** operator with bigints for old engines.
|
// Not using ** operator with bigints for old engines.
|
||||||
export const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;
|
export const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;
|
||||||
|
|
||||||
|
// DRBG
|
||||||
|
|
||||||
|
const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array
|
||||||
|
const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut
|
||||||
|
type Pred<T> = (v: Uint8Array) => T | undefined;
|
||||||
|
/**
|
||||||
|
* Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
||||||
|
* @returns function that will call DRBG until 2nd arg returns something meaningful
|
||||||
|
* @example
|
||||||
|
* const drbg = createHmacDRBG<Key>(32, 32, hmac);
|
||||||
|
* drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
|
||||||
|
*/
|
||||||
|
export function createHmacDrbg<T>(
|
||||||
|
hashLen: number,
|
||||||
|
qByteLen: number,
|
||||||
|
hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array
|
||||||
|
): (seed: Uint8Array, predicate: Pred<T>) => T {
|
||||||
|
if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');
|
||||||
|
if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');
|
||||||
|
if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
|
||||||
|
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
||||||
|
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
||||||
|
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
|
||||||
|
let i = 0; // Iterations counter, will throw when over 1000
|
||||||
|
const reset = () => {
|
||||||
|
v.fill(1);
|
||||||
|
k.fill(0);
|
||||||
|
i = 0;
|
||||||
|
};
|
||||||
|
const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
|
||||||
|
const reseed = (seed = u8n()) => {
|
||||||
|
// HMAC-DRBG reseed() function. Steps D-G
|
||||||
|
k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)
|
||||||
|
v = h(); // v = hmac(k || v)
|
||||||
|
if (seed.length === 0) return;
|
||||||
|
k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)
|
||||||
|
v = h(); // v = hmac(k || v)
|
||||||
|
};
|
||||||
|
const gen = () => {
|
||||||
|
// HMAC-DRBG generate() function
|
||||||
|
if (i++ >= 1000) throw new Error('drbg: tried 1000 values');
|
||||||
|
let len = 0;
|
||||||
|
const out: Uint8Array[] = [];
|
||||||
|
while (len < qByteLen) {
|
||||||
|
v = h();
|
||||||
|
const sl = v.slice();
|
||||||
|
out.push(sl);
|
||||||
|
len += v.length;
|
||||||
|
}
|
||||||
|
return concatBytes(...out);
|
||||||
|
};
|
||||||
|
const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {
|
||||||
|
reset();
|
||||||
|
reseed(seed); // Steps D-G
|
||||||
|
let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
|
||||||
|
while (!(res = pred(gen()))) reseed();
|
||||||
|
reset();
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
return genUntil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validating curves and fields
|
||||||
|
|
||||||
const validatorFns = {
|
const validatorFns = {
|
||||||
bigint: (val: any) => typeof val === 'bigint',
|
bigint: (val: any) => typeof val === 'bigint',
|
||||||
function: (val: any) => typeof val === 'function',
|
function: (val: any) => typeof val === 'function',
|
||||||
|
|||||||
@@ -59,9 +59,6 @@ export interface ProjPointType<T> extends Group<ProjPointType<T>> {
|
|||||||
readonly py: T;
|
readonly py: T;
|
||||||
readonly pz: T;
|
readonly pz: T;
|
||||||
multiply(scalar: bigint): ProjPointType<T>;
|
multiply(scalar: bigint): ProjPointType<T>;
|
||||||
multiplyUnsafe(scalar: bigint): ProjPointType<T>;
|
|
||||||
multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
|
|
||||||
_setWindowSize(windowSize: number): void;
|
|
||||||
toAffine(iz?: T): AffinePoint<T>;
|
toAffine(iz?: T): AffinePoint<T>;
|
||||||
isTorsionFree(): boolean;
|
isTorsionFree(): boolean;
|
||||||
clearCofactor(): ProjPointType<T>;
|
clearCofactor(): ProjPointType<T>;
|
||||||
@@ -69,6 +66,10 @@ export interface ProjPointType<T> extends Group<ProjPointType<T>> {
|
|||||||
hasEvenY(): boolean;
|
hasEvenY(): boolean;
|
||||||
toRawBytes(isCompressed?: boolean): Uint8Array;
|
toRawBytes(isCompressed?: boolean): Uint8Array;
|
||||||
toHex(isCompressed?: boolean): string;
|
toHex(isCompressed?: boolean): string;
|
||||||
|
|
||||||
|
multiplyUnsafe(scalar: bigint): ProjPointType<T>;
|
||||||
|
multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;
|
||||||
|
_setWindowSize(windowSize: number): void;
|
||||||
}
|
}
|
||||||
// Static methods for 3d XYZ points
|
// Static methods for 3d XYZ points
|
||||||
export interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
|
export interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
|
||||||
@@ -121,7 +122,7 @@ function validatePointOpts<T>(curve: CurvePointsType<T>) {
|
|||||||
|
|
||||||
export type CurvePointsRes<T> = {
|
export type CurvePointsRes<T> = {
|
||||||
ProjectivePoint: ProjConstructor<T>;
|
ProjectivePoint: ProjConstructor<T>;
|
||||||
normalizePrivateKey: (key: PrivKey) => bigint;
|
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
||||||
weierstrassEquation: (x: T) => T;
|
weierstrassEquation: (x: T) => T;
|
||||||
isWithinCurveOrder: (num: bigint) => boolean;
|
isWithinCurveOrder: (num: bigint) => boolean;
|
||||||
};
|
};
|
||||||
@@ -202,8 +203,8 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
if (!isWithinCurveOrder(num)) throw new Error('Expected valid bigint: 0 < bigint < curve.n');
|
if (!isWithinCurveOrder(num)) throw new Error('Expected valid bigint: 0 < bigint < curve.n');
|
||||||
}
|
}
|
||||||
// Validates if priv key is valid and converts it to bigint.
|
// Validates if priv key is valid and converts it to bigint.
|
||||||
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
|
// Supports options allowedPrivateKeyLengths and wrapPrivateKey.
|
||||||
function normalizePrivateKey(key: PrivKey): bigint {
|
function normPrivateKeyToScalar(key: PrivKey): bigint {
|
||||||
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
||||||
if (lengths && typeof key !== 'bigint') {
|
if (lengths && typeof key !== 'bigint') {
|
||||||
if (key instanceof Uint8Array) key = ut.bytesToHex(key);
|
if (key instanceof Uint8Array) key = ut.bytesToHex(key);
|
||||||
@@ -213,7 +214,10 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
}
|
}
|
||||||
let num: bigint;
|
let num: bigint;
|
||||||
try {
|
try {
|
||||||
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE(ensureBytes(key, nByteLength));
|
num =
|
||||||
|
typeof key === 'bigint'
|
||||||
|
? key
|
||||||
|
: ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
|
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
|
||||||
}
|
}
|
||||||
@@ -276,14 +280,14 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
* @param hex short/long ECDSA hex
|
* @param hex short/long ECDSA hex
|
||||||
*/
|
*/
|
||||||
static fromHex(hex: Hex): Point {
|
static fromHex(hex: Hex): Point {
|
||||||
const P = Point.fromAffine(CURVE.fromBytes(ensureBytes(hex)));
|
const P = Point.fromAffine(CURVE.fromBytes(ensureBytes('pointHex', hex)));
|
||||||
P.assertValidity();
|
P.assertValidity();
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplies generator point by privateKey.
|
// Multiplies generator point by privateKey.
|
||||||
static fromPrivateKey(privateKey: PrivKey) {
|
static fromPrivateKey(privateKey: PrivKey) {
|
||||||
return Point.BASE.multiply(normalizePrivateKey(privateKey));
|
return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We calculate precomputes for elliptic curve point multiplication
|
// We calculate precomputes for elliptic curve point multiplication
|
||||||
@@ -484,8 +488,9 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
* Constant time multiplication.
|
* Constant time multiplication.
|
||||||
* Uses wNAF method. Windowed method may be 10% faster,
|
* Uses wNAF method. Windowed method may be 10% faster,
|
||||||
* but takes 2x longer to generate and consumes 2x memory.
|
* but takes 2x longer to generate and consumes 2x memory.
|
||||||
|
* Uses precomputes when available.
|
||||||
|
* Uses endomorphism for Koblitz curves.
|
||||||
* @param scalar by which the point would be multiplied
|
* @param scalar by which the point would be multiplied
|
||||||
* @param affinePoint optional point ot save cached precompute windows on it
|
|
||||||
* @returns New point
|
* @returns New point
|
||||||
*/
|
*/
|
||||||
multiply(scalar: bigint): Point {
|
multiply(scalar: bigint): Point {
|
||||||
@@ -513,6 +518,8 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
|
* Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
|
||||||
|
* Not using Strauss-Shamir trick: precomputation tables are faster.
|
||||||
|
* The trick could be useful if both P and Q are not G (not in our case).
|
||||||
* @returns non-zero affine point
|
* @returns non-zero affine point
|
||||||
*/
|
*/
|
||||||
multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined {
|
multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined {
|
||||||
@@ -568,7 +575,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
ProjectivePoint: Point as ProjConstructor<T>,
|
ProjectivePoint: Point as ProjConstructor<T>,
|
||||||
normalizePrivateKey,
|
normPrivateKeyToScalar,
|
||||||
weierstrassEquation,
|
weierstrassEquation,
|
||||||
isWithinCurveOrder,
|
isWithinCurveOrder,
|
||||||
};
|
};
|
||||||
@@ -638,65 +645,11 @@ export type CurveFn = {
|
|||||||
utils: {
|
utils: {
|
||||||
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
||||||
isValidPrivateKey(privateKey: PrivKey): boolean;
|
isValidPrivateKey(privateKey: PrivKey): boolean;
|
||||||
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
|
||||||
randomPrivateKey: () => Uint8Array;
|
randomPrivateKey: () => Uint8Array;
|
||||||
precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
|
precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array
|
|
||||||
const u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut
|
|
||||||
// Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
||||||
type Pred<T> = (v: Uint8Array) => T | undefined;
|
|
||||||
function hmacDrbg<T>(
|
|
||||||
hashLen: number,
|
|
||||||
qByteLen: number,
|
|
||||||
hmacFn: HmacFnSync
|
|
||||||
): (seed: Uint8Array, predicate: Pred<T>) => T {
|
|
||||||
if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');
|
|
||||||
if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');
|
|
||||||
if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
|
|
||||||
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
|
||||||
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
||||||
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
|
|
||||||
let i = 0; // Iterations counter, will throw when over 1000
|
|
||||||
const reset = () => {
|
|
||||||
v.fill(1);
|
|
||||||
k.fill(0);
|
|
||||||
i = 0;
|
|
||||||
};
|
|
||||||
const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
|
|
||||||
const reseed = (seed = u8n()) => {
|
|
||||||
// HMAC-DRBG reseed() function. Steps D-G
|
|
||||||
k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)
|
|
||||||
v = h(); // v = hmac(k || v)
|
|
||||||
if (seed.length === 0) return;
|
|
||||||
k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)
|
|
||||||
v = h(); // v = hmac(k || v)
|
|
||||||
};
|
|
||||||
const gen = () => {
|
|
||||||
// HMAC-DRBG generate() function
|
|
||||||
if (i++ >= 1000) throw new Error('drbg: tried 1000 values');
|
|
||||||
let len = 0;
|
|
||||||
const out: Uint8Array[] = [];
|
|
||||||
while (len < qByteLen) {
|
|
||||||
v = h();
|
|
||||||
const sl = v.slice();
|
|
||||||
out.push(sl);
|
|
||||||
len += v.length;
|
|
||||||
}
|
|
||||||
return ut.concatBytes(...out);
|
|
||||||
};
|
|
||||||
const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {
|
|
||||||
reset();
|
|
||||||
reseed(seed); // Steps D-G
|
|
||||||
let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
|
|
||||||
while (!(res = pred(gen()))) reseed();
|
|
||||||
reset();
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
return genUntil;
|
|
||||||
}
|
|
||||||
export function weierstrass(curveDef: CurveType): CurveFn {
|
export function weierstrass(curveDef: CurveType): CurveFn {
|
||||||
const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;
|
const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;
|
||||||
const CURVE_ORDER = CURVE.n;
|
const CURVE_ORDER = CURVE.n;
|
||||||
@@ -716,7 +669,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
ProjectivePoint: Point,
|
ProjectivePoint: Point,
|
||||||
normalizePrivateKey,
|
normPrivateKeyToScalar,
|
||||||
weierstrassEquation,
|
weierstrassEquation,
|
||||||
isWithinCurveOrder,
|
isWithinCurveOrder,
|
||||||
} = weierstrassPoints({
|
} = weierstrassPoints({
|
||||||
@@ -726,7 +679,6 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
const x = Fp.toBytes(a.x);
|
const x = Fp.toBytes(a.x);
|
||||||
const cat = ut.concatBytes;
|
const cat = ut.concatBytes;
|
||||||
if (isCompressed) {
|
if (isCompressed) {
|
||||||
// TODO: hasEvenY
|
|
||||||
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
|
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
|
||||||
} else {
|
} else {
|
||||||
return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
|
return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
|
||||||
@@ -782,24 +734,22 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
|
|
||||||
// pair (bytes of r, bytes of s)
|
// pair (bytes of r, bytes of s)
|
||||||
static fromCompact(hex: Hex) {
|
static fromCompact(hex: Hex) {
|
||||||
const gl = CURVE.nByteLength;
|
const l = CURVE.nByteLength;
|
||||||
hex = ensureBytes(hex, gl * 2);
|
hex = ensureBytes('compactSignature', hex, l * 2);
|
||||||
return new Signature(slcNum(hex, 0, gl), slcNum(hex, gl, 2 * gl));
|
return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
|
||||||
}
|
}
|
||||||
|
|
||||||
// DER encoded ECDSA signature
|
// DER encoded ECDSA signature
|
||||||
// https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
|
// https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
|
||||||
static fromDER(hex: Hex) {
|
static fromDER(hex: Hex) {
|
||||||
if (typeof hex !== 'string' && !(hex instanceof Uint8Array))
|
const { r, s } = DER.toSig(ensureBytes('DER', hex));
|
||||||
throw new Error(`Signature.fromDER: Expected string or Uint8Array`);
|
|
||||||
const { r, s } = DER.toSig(ensureBytes(hex));
|
|
||||||
return new Signature(r, s);
|
return new Signature(r, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertValidity(): void {
|
assertValidity(): void {
|
||||||
// can use assertGE here
|
// can use assertGE here
|
||||||
if (!isWithinCurveOrder(this.r)) throw new Error('r must be 0 < r < n');
|
if (!isWithinCurveOrder(this.r)) throw new Error('r must be 0 < r < CURVE.n');
|
||||||
if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < n');
|
if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < CURVE.n');
|
||||||
}
|
}
|
||||||
|
|
||||||
addRecoveryBit(recovery: number) {
|
addRecoveryBit(recovery: number) {
|
||||||
@@ -807,11 +757,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recoverPublicKey(msgHash: Hex): typeof Point.BASE {
|
recoverPublicKey(msgHash: Hex): typeof Point.BASE {
|
||||||
const { n: N } = CURVE; // ECDSA public key recovery secg.org/sec1-v2.pdf 4.1.6
|
|
||||||
const { r, s, recovery: rec } = this;
|
const { r, s, recovery: rec } = this;
|
||||||
const h = bits2int_modN(ensureBytes(msgHash)); // Truncate hash
|
const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
|
||||||
if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid');
|
if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid');
|
||||||
const radj = rec === 2 || rec === 3 ? r + N : r;
|
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
|
||||||
if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid');
|
if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid');
|
||||||
const prefix = (rec & 1) === 0 ? '02' : '03';
|
const prefix = (rec & 1) === 0 ? '02' : '03';
|
||||||
const R = Point.fromHex(prefix + numToNByteStr(radj));
|
const R = Point.fromHex(prefix + numToNByteStr(radj));
|
||||||
@@ -853,37 +802,35 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
const utils = {
|
const utils = {
|
||||||
isValidPrivateKey(privateKey: PrivKey) {
|
isValidPrivateKey(privateKey: PrivKey) {
|
||||||
try {
|
try {
|
||||||
normalizePrivateKey(privateKey);
|
normPrivateKeyToScalar(privateKey);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
normPrivateKeyToScalar: normalizePrivateKey,
|
normPrivateKeyToScalar: normPrivateKeyToScalar,
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts some bytes to a valid private key. Needs at least (nBitLength+64) bytes.
|
|
||||||
*/
|
|
||||||
hashToPrivateKey: (hash: Hex): Uint8Array =>
|
|
||||||
ut.numberToBytesBE(mod.hashToPrivateScalar(hash, CURVE_ORDER), CURVE.nByteLength),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produces cryptographically secure private key from random of size (nBitLength+64)
|
* Produces cryptographically secure private key from random of size (nBitLength+64)
|
||||||
* as per FIPS 186 B.4.1 with modulo bias being neglible.
|
* as per FIPS 186 B.4.1 with modulo bias being neglible.
|
||||||
*/
|
*/
|
||||||
randomPrivateKey: (): Uint8Array => utils.hashToPrivateKey(CURVE.randomBytes(Fp.BYTES + 8)),
|
randomPrivateKey: (): Uint8Array => {
|
||||||
|
const rand = CURVE.randomBytes(Fp.BYTES + 8);
|
||||||
|
const num = mod.hashToPrivateScalar(rand, CURVE_ORDER);
|
||||||
|
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it.
|
* Creates precompute table for an arbitrary EC point. Makes point "cached".
|
||||||
* 2. Precomputes point multiplication table. Is done by default on first `getPublicKey()` call.
|
* Allows to massively speed-up `point.multiply(scalar)`.
|
||||||
* If you want your first getPublicKey to take 0.16ms instead of 20ms, make sure to call
|
|
||||||
* utils.precompute() somewhere without arguments first.
|
|
||||||
* @param windowSize 2, 4, 8, 16
|
|
||||||
* @returns cached point
|
* @returns cached point
|
||||||
|
* @example
|
||||||
|
* const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
|
||||||
|
* fast.multiply(privKey); // much faster ECDH now
|
||||||
*/
|
*/
|
||||||
precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE {
|
precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE {
|
||||||
point._setWindowSize(windowSize);
|
point._setWindowSize(windowSize);
|
||||||
point.multiply(BigInt(3));
|
point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
|
||||||
return point;
|
return point;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -914,7 +861,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
/**
|
/**
|
||||||
* ECDH (Elliptic Curve Diffie Hellman).
|
* ECDH (Elliptic Curve Diffie Hellman).
|
||||||
* Computes shared public key from private key and public key.
|
* Computes shared public key from private key and public key.
|
||||||
* Checks: 1) private key validity 2) shared key is on-curve
|
* Checks: 1) private key validity 2) shared key is on-curve.
|
||||||
|
* Does NOT hash the result.
|
||||||
* @param privateA private key
|
* @param privateA private key
|
||||||
* @param publicB different public key
|
* @param publicB different public key
|
||||||
* @param isCompressed whether to return compact (default), or full key
|
* @param isCompressed whether to return compact (default), or full key
|
||||||
@@ -924,7 +872,7 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
if (isProbPub(privateA)) throw new Error('first arg must be private key');
|
if (isProbPub(privateA)) throw new Error('first arg must be private key');
|
||||||
if (!isProbPub(publicB)) throw new Error('second arg must be public key');
|
if (!isProbPub(publicB)) throw new Error('second arg must be public key');
|
||||||
const b = Point.fromHex(publicB); // check for being on-curve
|
const b = Point.fromHex(publicB); // check for being on-curve
|
||||||
return b.multiply(normalizePrivateKey(privateA)).toRawBytes(isCompressed);
|
return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
|
// RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
|
||||||
@@ -936,8 +884,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
function (bytes: Uint8Array): bigint {
|
function (bytes: Uint8Array): bigint {
|
||||||
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
||||||
// for some cases, since bytes.length * 8 is not actual bitLength.
|
// for some cases, since bytes.length * 8 is not actual bitLength.
|
||||||
const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
|
|
||||||
const num = ut.bytesToNumberBE(bytes); // check for == u8 done here
|
const num = ut.bytesToNumberBE(bytes); // check for == u8 done here
|
||||||
|
const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
|
||||||
return delta > 0 ? num >> BigInt(delta) : num;
|
return delta > 0 ? num >> BigInt(delta) : num;
|
||||||
};
|
};
|
||||||
const bits2int_modN =
|
const bits2int_modN =
|
||||||
@@ -947,10 +895,12 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
};
|
};
|
||||||
// NOTE: pads output with zero as per spec
|
// NOTE: pads output with zero as per spec
|
||||||
const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
|
const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
|
||||||
|
/**
|
||||||
|
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
||||||
|
*/
|
||||||
function int2octets(num: bigint): Uint8Array {
|
function int2octets(num: bigint): Uint8Array {
|
||||||
if (typeof num !== 'bigint') throw new Error('bigint expected');
|
if (typeof num !== 'bigint') throw new Error('bigint expected');
|
||||||
if (!(_0n <= num && num < ORDER_MASK))
|
if (!(_0n <= num && num < ORDER_MASK))
|
||||||
// n in [0..ORDER_MASK-1]
|
|
||||||
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
||||||
// works with order, can have different size than numToField!
|
// works with order, can have different size than numToField!
|
||||||
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
||||||
@@ -962,26 +912,25 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
|
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
|
||||||
// Also it can be bigger for P224 + SHA256
|
// Also it can be bigger for P224 + SHA256
|
||||||
function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {
|
function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {
|
||||||
const { hash, randomBytes } = CURVE;
|
|
||||||
if (msgHash == null) throw new Error(`sign: expected valid message hash, not "${msgHash}"`);
|
|
||||||
if (['recovered', 'canonical'].some((k) => k in opts))
|
if (['recovered', 'canonical'].some((k) => k in opts))
|
||||||
// Ban legacy options
|
|
||||||
throw new Error('sign() legacy options not supported');
|
throw new Error('sign() legacy options not supported');
|
||||||
|
const { hash, randomBytes } = CURVE;
|
||||||
let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
|
let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
|
||||||
if (prehash) msgHash = hash(ensureBytes(msgHash));
|
|
||||||
if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
|
if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
|
||||||
|
msgHash = ensureBytes('msgHash', msgHash);
|
||||||
|
if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
|
||||||
|
|
||||||
// We can't later call bits2octets, since nested bits2int is broken for curves
|
// We can't later call bits2octets, since nested bits2int is broken for curves
|
||||||
// with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
|
// with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
|
||||||
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
|
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
|
||||||
const h1int = bits2int_modN(ensureBytes(msgHash));
|
const h1int = bits2int_modN(msgHash);
|
||||||
const d = normalizePrivateKey(privateKey); // validate private key, convert to bigint
|
const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
|
||||||
const seedArgs = [int2octets(d), int2octets(h1int)];
|
const seedArgs = [int2octets(d), int2octets(h1int)];
|
||||||
// extraEntropy. RFC6979 3.6: additional k' (optional).
|
// extraEntropy. RFC6979 3.6: additional k' (optional).
|
||||||
if (ent != null) {
|
if (ent != null) {
|
||||||
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
||||||
// Either pass as-is, or generate random bytes. Then validate for being ui8a of size BYTES
|
const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
|
||||||
seedArgs.push(ensureBytes(ent === true ? randomBytes(Fp.BYTES) : ent, Fp.BYTES));
|
seedArgs.push(ensureBytes('extraEntropy', e, Fp.BYTES)); // check for being of size BYTES
|
||||||
}
|
}
|
||||||
const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2
|
const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2
|
||||||
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
|
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
|
||||||
@@ -994,16 +943,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
const q = Point.BASE.multiply(k).toAffine(); // q = Gk
|
const q = Point.BASE.multiply(k).toAffine(); // q = Gk
|
||||||
const r = modN(q.x); // r = q.x mod n
|
const r = modN(q.x); // r = q.x mod n
|
||||||
if (r === _0n) return;
|
if (r === _0n) return;
|
||||||
// X blinding according to https://tches.iacr.org/index.php/TCHES/article/view/7337/6509
|
// Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
|
||||||
// b * m + b * r * d ∈ [0,q−1] exposed via side-channel, but d (private scalar) is not.
|
// https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
|
||||||
// NOTE: there is still probable some leak in multiplication, since it is not constant-time
|
// a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
|
||||||
const b = ut.bytesToNumberBE(utils.randomPrivateKey()); // random scalar, b ∈ [1,q−1]
|
const s = modN(ik * modN(m + r * d)); // Not using blinding here
|
||||||
const bi = invN(b); // b^-1
|
|
||||||
const bdr = modN(b * d * r); // b * d * r
|
|
||||||
const bm = modN(b * m); // b * m
|
|
||||||
const mrx = modN(bi * modN(bdr + bm)); // b^-1(bm + bdr) -> m + rd
|
|
||||||
|
|
||||||
const s = modN(ik * mrx); // s = k^-1(m + rd) mod n
|
|
||||||
if (s === _0n) return;
|
if (s === _0n) return;
|
||||||
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
|
||||||
let normS = s;
|
let normS = s;
|
||||||
@@ -1030,8 +973,8 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
*/
|
*/
|
||||||
function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): Signature {
|
function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): Signature {
|
||||||
const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
|
const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
|
||||||
const genUntil = hmacDrbg<Signature>(CURVE.hash.outputLen, CURVE.nByteLength, CURVE.hmac);
|
const drbg = ut.createHmacDrbg<Signature>(CURVE.hash.outputLen, CURVE.nByteLength, CURVE.hmac);
|
||||||
return genUntil(seed, k2sig); // Steps B, C, D, E, F, G
|
return drbg(seed, k2sig); // Steps B, C, D, E, F, G
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable precomputes. Slows down first publicKey computation by 20ms.
|
// Enable precomputes. Slows down first publicKey computation by 20ms.
|
||||||
@@ -1057,30 +1000,38 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
publicKey: Hex,
|
publicKey: Hex,
|
||||||
opts = defaultVerOpts
|
opts = defaultVerOpts
|
||||||
): boolean {
|
): boolean {
|
||||||
let P: ProjPointType<bigint>;
|
const sg = signature;
|
||||||
|
msgHash = ensureBytes('msgHash', msgHash);
|
||||||
|
publicKey = ensureBytes('publicKey', publicKey);
|
||||||
|
if ('strict' in opts) throw new Error('options.strict was renamed to lowS');
|
||||||
|
const { lowS, prehash } = opts;
|
||||||
|
|
||||||
let _sig: Signature | undefined = undefined;
|
let _sig: Signature | undefined = undefined;
|
||||||
if (publicKey instanceof Point) throw new Error('publicKey must be hex');
|
let P: ProjPointType<bigint>;
|
||||||
try {
|
try {
|
||||||
if (signature && typeof signature === 'object' && !(signature instanceof Uint8Array)) {
|
if (typeof sg === 'string' || sg instanceof Uint8Array) {
|
||||||
const { r, s } = signature;
|
|
||||||
_sig = new Signature(r, s); // assertValidity() is executed on creation
|
|
||||||
} else {
|
|
||||||
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
|
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
|
||||||
// Since DER can also be 2*nByteLength bytes, we check for it first.
|
// Since DER can also be 2*nByteLength bytes, we check for it first.
|
||||||
try {
|
try {
|
||||||
_sig = Signature.fromDER(signature as Hex);
|
_sig = Signature.fromDER(sg);
|
||||||
} catch (derError) {
|
} catch (derError) {
|
||||||
if (!(derError instanceof DER.Err)) throw derError;
|
if (!(derError instanceof DER.Err)) throw derError;
|
||||||
_sig = Signature.fromCompact(signature as Hex);
|
_sig = Signature.fromCompact(sg);
|
||||||
}
|
}
|
||||||
|
} else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {
|
||||||
|
const { r, s } = sg;
|
||||||
|
_sig = new Signature(r, s);
|
||||||
|
} else {
|
||||||
|
throw new Error('PARSE');
|
||||||
}
|
}
|
||||||
msgHash = ensureBytes(msgHash);
|
|
||||||
P = Point.fromHex(publicKey);
|
P = Point.fromHex(publicKey);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if ((error as Error).message === 'PARSE')
|
||||||
|
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (opts.lowS && _sig.hasHighS()) return false;
|
if (lowS && _sig.hasHighS()) return false;
|
||||||
if (opts.prehash) msgHash = CURVE.hash(msgHash);
|
if (prehash) msgHash = CURVE.hash(msgHash);
|
||||||
const { r, s } = _sig;
|
const { r, s } = _sig;
|
||||||
const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
|
const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
|
||||||
const is = invN(s); // s^-1
|
const is = invN(s); // s^-1
|
||||||
|
|||||||
@@ -1,9 +1,43 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
|
||||||
// The pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
|
// bls12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
|
||||||
// - Construct zk-SNARKs at the 128-bit security
|
// - Construct zk-SNARKs at the 128-bit security
|
||||||
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
|
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and
|
||||||
// Differences from @noble/bls12-381 1.4:
|
// verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
|
||||||
|
//
|
||||||
|
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
|
||||||
|
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
|
||||||
|
// [pairing-curves-10](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-10),
|
||||||
|
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
|
||||||
|
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).
|
||||||
|
//
|
||||||
|
// ### Summary
|
||||||
|
// 1. BLS Relies on Bilinear Pairing (expensive)
|
||||||
|
// 2. Private Keys: 32 bytes
|
||||||
|
// 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes.
|
||||||
|
// 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays.
|
||||||
|
// - The signature is a point on the G2 subgroup, which is defined over a finite field
|
||||||
|
// with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the complex numbers).
|
||||||
|
// 5. The 12 stands for the Embedding degree.
|
||||||
|
//
|
||||||
|
// ### Formulas
|
||||||
|
// - `P = pk x G` - public keys
|
||||||
|
// - `S = pk x H(m)` - signing
|
||||||
|
// - `e(P, H(m)) == e(G, S)` - verification using pairings
|
||||||
|
// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
|
||||||
|
// Filecoin uses little endian byte arrays for private keys -
|
||||||
|
// so ensure to reverse byte order if you'll use it with FIL.
|
||||||
|
//
|
||||||
|
// ### Resources
|
||||||
|
// - [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
|
||||||
|
// - [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
|
||||||
|
// - Pairing over bls12-381:
|
||||||
|
// [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
|
||||||
|
// [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
|
||||||
|
// [part 3](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
|
||||||
|
// - [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
|
||||||
|
//
|
||||||
|
// ### Differences from @noble/bls12-381 1.4
|
||||||
// - PointG1 -> G1.Point
|
// - PointG1 -> G1.Point
|
||||||
// - PointG2 -> G2.Point
|
// - PointG2 -> G2.Point
|
||||||
// - PointG2.fromSignature -> Signature.decode
|
// - PointG2.fromSignature -> Signature.decode
|
||||||
@@ -910,7 +944,7 @@ function G2psi2(c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) {
|
|||||||
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
||||||
// m = 2 (or 1 for G1 see section 8.8.1)
|
// m = 2 (or 1 for G1 see section 8.8.1)
|
||||||
// k = 128
|
// k = 128
|
||||||
const htfDefaults = {
|
const htfDefaults = Object.freeze({
|
||||||
// DST: a domain separation tag
|
// DST: a domain separation tag
|
||||||
// defined in section 2.2.5
|
// defined in section 2.2.5
|
||||||
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
|
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
|
||||||
@@ -932,7 +966,7 @@ const htfDefaults = {
|
|||||||
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
||||||
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
||||||
hash: sha256,
|
hash: sha256,
|
||||||
} as const;
|
} as const);
|
||||||
|
|
||||||
// Encoding utils
|
// Encoding utils
|
||||||
// Point on G1 curve: (x, y)
|
// Point on G1 curve: (x, y)
|
||||||
@@ -1186,7 +1220,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
|
|||||||
Signature: {
|
Signature: {
|
||||||
// TODO: Optimize, it's very slow because of sqrt.
|
// TODO: Optimize, it's very slow because of sqrt.
|
||||||
decode(hex: Hex): ProjPointType<Fp2> {
|
decode(hex: Hex): ProjPointType<Fp2> {
|
||||||
hex = ensureBytes(hex);
|
hex = ensureBytes('signatureHex', hex);
|
||||||
const P = Fp.ORDER;
|
const P = Fp.ORDER;
|
||||||
const half = hex.length / 2;
|
const half = hex.length / 2;
|
||||||
if (half !== 48 && half !== 96)
|
if (half !== 48 && half !== 96)
|
||||||
@@ -1213,7 +1247,6 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
|
|||||||
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
|
const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1;
|
||||||
if (isGreater || isZero) y = Fp2.neg(y);
|
if (isGreater || isZero) y = Fp2.neg(y);
|
||||||
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
||||||
// console.log('Signature.decode', point);
|
|
||||||
point.assertValidity();
|
point.assertValidity();
|
||||||
return point;
|
return point;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ import { twistedEdwards, ExtPointType } from './abstract/edwards.js';
|
|||||||
import { montgomery } from './abstract/montgomery.js';
|
import { montgomery } from './abstract/montgomery.js';
|
||||||
import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
|
import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
|
||||||
import {
|
import {
|
||||||
ensureBytes,
|
|
||||||
equalBytes,
|
equalBytes,
|
||||||
bytesToHex,
|
bytesToHex,
|
||||||
bytesToNumberLE,
|
bytesToNumberLE,
|
||||||
numberToBytesLE,
|
numberToBytesLE,
|
||||||
Hex,
|
Hex,
|
||||||
|
ensureBytes,
|
||||||
} from './abstract/utils.js';
|
} from './abstract/utils.js';
|
||||||
import * as htf from './abstract/hash-to-curve.js';
|
import * as htf from './abstract/hash-to-curve.js';
|
||||||
|
import { AffinePoint } from './abstract/curve.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ed25519 Twisted Edwards curve with following addons:
|
* ed25519 Twisted Edwards curve with following addons:
|
||||||
@@ -138,10 +139,10 @@ export const ed25519ph = twistedEdwards({
|
|||||||
|
|
||||||
export const x25519 = montgomery({
|
export const x25519 = montgomery({
|
||||||
P: ED25519_P,
|
P: ED25519_P,
|
||||||
a24: BigInt('121665'),
|
a: BigInt(486662),
|
||||||
montgomeryBits: 255, // n is 253 bits
|
montgomeryBits: 255, // n is 253 bits
|
||||||
nByteLength: 32,
|
nByteLength: 32,
|
||||||
Gu: '0900000000000000000000000000000000000000000000000000000000000000',
|
Gu: BigInt(9),
|
||||||
powPminus2: (x: bigint): bigint => {
|
powPminus2: (x: bigint): bigint => {
|
||||||
const P = ED25519_P;
|
const P = ED25519_P;
|
||||||
// x^(p-2) aka x^(2^255-21)
|
// x^(p-2) aka x^(2^255-21)
|
||||||
@@ -149,6 +150,7 @@ export const x25519 = montgomery({
|
|||||||
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
|
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
|
||||||
},
|
},
|
||||||
adjustScalarBytes,
|
adjustScalarBytes,
|
||||||
|
randomBytes,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
||||||
@@ -223,7 +225,7 @@ function map_to_curve_elligator2_edwards25519(u: bigint) {
|
|||||||
const inv = Fp.invertBatch([xd, yd]); // batch division
|
const inv = Fp.invertBatch([xd, yd]); // batch division
|
||||||
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
||||||
}
|
}
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
ed25519.ExtendedPoint,
|
ed25519.ExtendedPoint,
|
||||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
(scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
||||||
{
|
{
|
||||||
@@ -308,6 +310,11 @@ export class RistrettoPoint {
|
|||||||
// Private property to discourage combining ExtendedPoint + RistrettoPoint
|
// Private property to discourage combining ExtendedPoint + RistrettoPoint
|
||||||
// Always use Ristretto encoding/decoding instead.
|
// Always use Ristretto encoding/decoding instead.
|
||||||
constructor(private readonly ep: ExtendedPoint) {}
|
constructor(private readonly ep: ExtendedPoint) {}
|
||||||
|
|
||||||
|
static fromAffine(ap: AffinePoint<bigint>) {
|
||||||
|
return new RistrettoPoint(ed25519.ExtendedPoint.fromAffine(ap));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes uniform output of 64-bit hash function like sha512 and converts it to `RistrettoPoint`.
|
* Takes uniform output of 64-bit hash function like sha512 and converts it to `RistrettoPoint`.
|
||||||
* The hash-to-group operation applies Elligator twice and adds the results.
|
* The hash-to-group operation applies Elligator twice and adds the results.
|
||||||
@@ -316,7 +323,7 @@ export class RistrettoPoint {
|
|||||||
* @param hex 64-bit output of a hash function
|
* @param hex 64-bit output of a hash function
|
||||||
*/
|
*/
|
||||||
static hashToCurve(hex: Hex): RistrettoPoint {
|
static hashToCurve(hex: Hex): RistrettoPoint {
|
||||||
hex = ensureBytes(hex, 64);
|
hex = ensureBytes('ristrettoHash', hex, 64);
|
||||||
const r1 = bytes255ToNumberLE(hex.slice(0, 32));
|
const r1 = bytes255ToNumberLE(hex.slice(0, 32));
|
||||||
const R1 = calcElligatorRistrettoMap(r1);
|
const R1 = calcElligatorRistrettoMap(r1);
|
||||||
const r2 = bytes255ToNumberLE(hex.slice(32, 64));
|
const r2 = bytes255ToNumberLE(hex.slice(32, 64));
|
||||||
@@ -330,7 +337,7 @@ export class RistrettoPoint {
|
|||||||
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
||||||
*/
|
*/
|
||||||
static fromHex(hex: Hex): RistrettoPoint {
|
static fromHex(hex: Hex): RistrettoPoint {
|
||||||
hex = ensureBytes(hex, 32);
|
hex = ensureBytes('ristrettoHex', hex, 32);
|
||||||
const { a, d } = ed25519.CURVE;
|
const { a, d } = ed25519.CURVE;
|
||||||
const P = ed25519.CURVE.Fp.ORDER;
|
const P = ed25519.CURVE.Fp.ORDER;
|
||||||
const mod = ed25519.CURVE.Fp.create;
|
const mod = ed25519.CURVE.Fp.create;
|
||||||
@@ -400,7 +407,7 @@ export class RistrettoPoint {
|
|||||||
equals(other: RistrettoPoint): boolean {
|
equals(other: RistrettoPoint): boolean {
|
||||||
assertRstPoint(other);
|
assertRstPoint(other);
|
||||||
const { ex: X1, ey: Y1 } = this.ep;
|
const { ex: X1, ey: Y1 } = this.ep;
|
||||||
const { ex: X2, ey: Y2 } = this.ep;
|
const { ex: X2, ey: Y2 } = other.ep;
|
||||||
const mod = ed25519.CURVE.Fp.create;
|
const mod = ed25519.CURVE.Fp.create;
|
||||||
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
||||||
const one = mod(X1 * Y2) === mod(Y1 * X2);
|
const one = mod(X1 * Y2) === mod(Y1 * X2);
|
||||||
@@ -426,3 +433,13 @@ export class RistrettoPoint {
|
|||||||
return new RistrettoPoint(this.ep.multiplyUnsafe(scalar));
|
return new RistrettoPoint(this.ep.multiplyUnsafe(scalar));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/
|
||||||
|
// Appendix B. Hashing to ristretto255
|
||||||
|
export const hash_to_ristretto255 = (msg: Uint8Array, options: htf.htfBasicOpts) => {
|
||||||
|
const d = options.DST;
|
||||||
|
const DST = typeof d === 'string' ? utf8ToBytes(d) : d;
|
||||||
|
const uniform_bytes = htf.expand_message_xmd(msg, DST, 64, sha512);
|
||||||
|
const P = RistrettoPoint.hashToCurve(uniform_bytes);
|
||||||
|
return P;
|
||||||
|
};
|
||||||
|
|||||||
@@ -122,11 +122,11 @@ export const ed448 = twistedEdwards(ED448_DEF);
|
|||||||
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
|
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
|
||||||
|
|
||||||
export const x448 = montgomery({
|
export const x448 = montgomery({
|
||||||
a24: BigInt(39081),
|
a: BigInt(156326),
|
||||||
montgomeryBits: 448,
|
montgomeryBits: 448,
|
||||||
nByteLength: 57,
|
nByteLength: 57,
|
||||||
P: ed448P,
|
P: ed448P,
|
||||||
Gu: '0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
Gu: BigInt(5),
|
||||||
powPminus2: (x: bigint): bigint => {
|
powPminus2: (x: bigint): bigint => {
|
||||||
const P = ed448P;
|
const P = ed448P;
|
||||||
const Pminus3div4 = ed448_pow_Pminus3div4(x);
|
const Pminus3div4 = ed448_pow_Pminus3div4(x);
|
||||||
@@ -134,6 +134,7 @@ export const x448 = montgomery({
|
|||||||
return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2
|
return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2
|
||||||
},
|
},
|
||||||
adjustScalarBytes,
|
adjustScalarBytes,
|
||||||
|
randomBytes,
|
||||||
// The 4-isogeny maps between the Montgomery curve and this Edwards
|
// The 4-isogeny maps between the Montgomery curve and this Edwards
|
||||||
// curve are:
|
// curve are:
|
||||||
// (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
|
// (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
|
||||||
@@ -225,7 +226,7 @@ function map_to_curve_elligator2_edwards448(u: bigint) {
|
|||||||
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
ed448.ExtendedPoint,
|
ed448.ExtendedPoint,
|
||||||
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
|
(scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]),
|
||||||
{
|
{
|
||||||
|
|||||||
25
src/p192.ts
25
src/p192.ts
@@ -1,25 +0,0 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
||||||
import { createCurve } from './_shortw_utils.js';
|
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
|
||||||
import { Fp } from './abstract/modular.js';
|
|
||||||
|
|
||||||
// NIST secp192r1 aka P192
|
|
||||||
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1
|
|
||||||
export const P192 = createCurve(
|
|
||||||
{
|
|
||||||
// Params: a, b
|
|
||||||
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
|
|
||||||
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
|
|
||||||
// Field over which we'll do calculations; 2n ** 192n - 2n ** 64n - 1n
|
|
||||||
Fp: Fp(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')),
|
|
||||||
// Curve order, total count of valid points in the field.
|
|
||||||
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
|
|
||||||
// Base point (x, y) aka generator point
|
|
||||||
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
|
|
||||||
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
|
|
||||||
h: BigInt(1),
|
|
||||||
lowS: false,
|
|
||||||
} as const,
|
|
||||||
sha256
|
|
||||||
);
|
|
||||||
export const secp192r1 = P192;
|
|
||||||
25
src/p224.ts
25
src/p224.ts
@@ -1,25 +0,0 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
||||||
import { createCurve } from './_shortw_utils.js';
|
|
||||||
import { sha224 } from '@noble/hashes/sha256';
|
|
||||||
import { Fp } from './abstract/modular.js';
|
|
||||||
|
|
||||||
// NIST secp224r1 aka P224
|
|
||||||
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-224
|
|
||||||
export const P224 = createCurve(
|
|
||||||
{
|
|
||||||
// Params: a, b
|
|
||||||
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
|
|
||||||
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
|
|
||||||
// Field over which we'll do calculations;
|
|
||||||
Fp: Fp(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),
|
|
||||||
// Curve order, total count of valid points in the field
|
|
||||||
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
|
|
||||||
// Base point (x, y) aka generator point
|
|
||||||
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
|
|
||||||
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
|
|
||||||
h: BigInt(1),
|
|
||||||
lowS: false,
|
|
||||||
} as const,
|
|
||||||
sha224
|
|
||||||
);
|
|
||||||
export const secp224r1 = P224;
|
|
||||||
@@ -37,7 +37,7 @@ export const P256 = createCurve(
|
|||||||
);
|
);
|
||||||
export const secp256r1 = P256;
|
export const secp256r1 = P256;
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp256r1.ProjectivePoint,
|
secp256r1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => mapSWU(scalars[0]),
|
(scalars: bigint[]) => mapSWU(scalars[0]),
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export const P384 = createCurve({
|
|||||||
);
|
);
|
||||||
export const secp384r1 = P384;
|
export const secp384r1 = P384;
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp384r1.ProjectivePoint,
|
secp384r1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => mapSWU(scalars[0]),
|
(scalars: bigint[]) => mapSWU(scalars[0]),
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export const P521 = createCurve({
|
|||||||
} as const, sha512);
|
} as const, sha512);
|
||||||
export const secp521r1 = P521;
|
export const secp521r1 = P521;
|
||||||
|
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp521r1.ProjectivePoint,
|
secp521r1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => mapSWU(scalars[0]),
|
(scalars: bigint[]) => mapSWU(scalars[0]),
|
||||||
{
|
{
|
||||||
|
|||||||
136
src/secp256k1.ts
136
src/secp256k1.ts
@@ -1,26 +1,12 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
import { Fp as Field, mod, pow2 } from './abstract/modular.js';
|
|
||||||
import { createCurve } from './_shortw_utils.js';
|
|
||||||
import { ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
|
||||||
import {
|
|
||||||
ensureBytes,
|
|
||||||
concatBytes,
|
|
||||||
Hex,
|
|
||||||
bytesToNumberBE as bytesToInt,
|
|
||||||
PrivKey,
|
|
||||||
numberToBytesBE,
|
|
||||||
} from './abstract/utils.js';
|
|
||||||
import { randomBytes } from '@noble/hashes/utils';
|
import { randomBytes } from '@noble/hashes/utils';
|
||||||
|
import { Fp as Field, mod, pow2 } from './abstract/modular.js';
|
||||||
|
import { ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
||||||
|
import type { Hex, PrivKey } from './abstract/utils.js';
|
||||||
|
import { bytesToNumberBE, concatBytes, ensureBytes, numberToBytesBE } from './abstract/utils.js';
|
||||||
import * as htf from './abstract/hash-to-curve.js';
|
import * as htf from './abstract/hash-to-curve.js';
|
||||||
|
import { createCurve } from './_shortw_utils.js';
|
||||||
/**
|
|
||||||
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
|
|
||||||
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
|
|
||||||
* Should always be used for Projective's double-and-add multiplication.
|
|
||||||
* For affines cached multiplication, it trades off 1/2 init time & 1/3 ram for 20% perf hit.
|
|
||||||
* https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
|
|
||||||
*/
|
|
||||||
|
|
||||||
const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
|
const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
|
||||||
const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
|
const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
|
||||||
@@ -61,23 +47,22 @@ type Fp = bigint;
|
|||||||
|
|
||||||
export const secp256k1 = createCurve(
|
export const secp256k1 = createCurve(
|
||||||
{
|
{
|
||||||
// Params: a, b
|
a: BigInt(0), // equation params: a, b
|
||||||
// Seem to be rigid https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
|
b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
|
||||||
a: BigInt(0),
|
Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
||||||
b: BigInt(7),
|
n: secp256k1N, // Curve order, total count of valid points in the field
|
||||||
// Field over which we'll do calculations;
|
|
||||||
// 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
|
||||||
Fp,
|
|
||||||
// Curve order, total count of valid points in the field
|
|
||||||
n: secp256k1N,
|
|
||||||
// Base point (x, y) aka generator point
|
// Base point (x, y) aka generator point
|
||||||
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
||||||
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
|
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
|
||||||
h: BigInt(1),
|
h: BigInt(1), // Cofactor
|
||||||
// Alllow only low-S signatures by default in sign() and verify()
|
lowS: true, // Allow only low-S signatures by default in sign() and verify()
|
||||||
lowS: true,
|
/**
|
||||||
|
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
|
||||||
|
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
|
||||||
|
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
|
||||||
|
* Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
|
||||||
|
*/
|
||||||
endo: {
|
endo: {
|
||||||
// Params taken from https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
|
|
||||||
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
||||||
splitScalar: (k: bigint) => {
|
splitScalar: (k: bigint) => {
|
||||||
const n = secp256k1N;
|
const n = secp256k1N;
|
||||||
@@ -105,19 +90,11 @@ export const secp256k1 = createCurve(
|
|||||||
sha256
|
sha256
|
||||||
);
|
);
|
||||||
|
|
||||||
// Schnorr signatures are superior to ECDSA from above.
|
// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
|
||||||
// Below is Schnorr-specific code as per BIP0340.
|
|
||||||
// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
|
// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
|
||||||
const _0n = BigInt(0);
|
const _0n = BigInt(0);
|
||||||
const fe = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1P;
|
const fe = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1P;
|
||||||
const ge = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1N;
|
const ge = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1N;
|
||||||
|
|
||||||
const TAGS = {
|
|
||||||
challenge: 'BIP0340/challenge',
|
|
||||||
aux: 'BIP0340/aux',
|
|
||||||
nonce: 'BIP0340/nonce',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
|
/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
|
||||||
const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {};
|
const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {};
|
||||||
function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
|
function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
|
||||||
@@ -130,56 +107,70 @@ function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
|
|||||||
return sha256(concatBytes(tagP, ...messages));
|
return sha256(concatBytes(tagP, ...messages));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
|
||||||
const pointToBytes = (point: PointType<bigint>) => point.toRawBytes(true).slice(1);
|
const pointToBytes = (point: PointType<bigint>) => point.toRawBytes(true).slice(1);
|
||||||
const numTo32b = (n: bigint) => numberToBytesBE(n, 32);
|
const numTo32b = (n: bigint) => numberToBytesBE(n, 32);
|
||||||
|
const modP = (x: bigint) => mod(x, secp256k1P);
|
||||||
const modN = (x: bigint) => mod(x, secp256k1N);
|
const modN = (x: bigint) => mod(x, secp256k1N);
|
||||||
const Point = secp256k1.ProjectivePoint;
|
const Point = secp256k1.ProjectivePoint;
|
||||||
const GmulAdd = (Q: PointType<bigint>, a: bigint, b: bigint) =>
|
const GmulAdd = (Q: PointType<bigint>, a: bigint, b: bigint) =>
|
||||||
Point.BASE.multiplyAndAddUnsafe(Q, a, b);
|
Point.BASE.multiplyAndAddUnsafe(Q, a, b);
|
||||||
const hex32ToInt = (key: Hex) => bytesToInt(ensureBytes(key, 32));
|
|
||||||
|
// Calculate point, scalar and bytes
|
||||||
function schnorrGetExtPubKey(priv: PrivKey) {
|
function schnorrGetExtPubKey(priv: PrivKey) {
|
||||||
let d = typeof priv === 'bigint' ? priv : hex32ToInt(priv);
|
let d_ = secp256k1.utils.normPrivateKeyToScalar(priv); // same method executed in fromPrivateKey
|
||||||
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
|
let p = Point.fromPrivateKey(d_); // P = d'⋅G; 0 < d' < n check is done inside
|
||||||
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
|
const scalar = p.hasEvenY() ? d_ : modN(-d_);
|
||||||
return { point, scalar, bytes: pointToBytes(point) };
|
return { scalar: scalar, bytes: pointToBytes(p) };
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.
|
||||||
|
* @returns valid point checked for being on-curve
|
||||||
|
*/
|
||||||
function lift_x(x: bigint): PointType<bigint> {
|
function lift_x(x: bigint): PointType<bigint> {
|
||||||
if (!fe(x)) throw new Error('bad x: need 0 < x < p'); // Fail if x ≥ p.
|
if (!fe(x)) throw new Error('bad x: need 0 < x < p'); // Fail if x ≥ p.
|
||||||
const c = mod(x * x * x + BigInt(7), secp256k1P); // Let c = x³ + 7 mod p.
|
const xx = modP(x * x);
|
||||||
|
const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.
|
||||||
let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.
|
let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.
|
||||||
if (y % 2n !== 0n) y = mod(-y, secp256k1P); // Return the unique point P such that x(P) = x and
|
if (y % 2n !== 0n) y = modP(-y); // Return the unique point P such that x(P) = x and
|
||||||
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
||||||
p.assertValidity();
|
p.assertValidity();
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Create tagged hash, convert it to bigint, reduce modulo-n.
|
||||||
|
*/
|
||||||
function challenge(...args: Uint8Array[]): bigint {
|
function challenge(...args: Uint8Array[]): bigint {
|
||||||
return modN(bytesToInt(taggedHash(TAGS.challenge, ...args)));
|
return modN(bytesToNumberBE(taggedHash('BIP0340/challenge', ...args)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schnorr's pubkey is just `x` of Point (BIP340)
|
/**
|
||||||
|
* Schnorr public key is just `x` coordinate of Point as per BIP340.
|
||||||
|
*/
|
||||||
function schnorrGetPublicKey(privateKey: Hex): Uint8Array {
|
function schnorrGetPublicKey(privateKey: Hex): Uint8Array {
|
||||||
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
|
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
|
/**
|
||||||
// auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous
|
* Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
|
||||||
|
* auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.
|
||||||
|
*/
|
||||||
function schnorrSign(
|
function schnorrSign(
|
||||||
message: Hex,
|
message: Hex,
|
||||||
privateKey: PrivKey,
|
privateKey: PrivKey,
|
||||||
auxRand: Hex = randomBytes(32)
|
auxRand: Hex = randomBytes(32)
|
||||||
): Uint8Array {
|
): Uint8Array {
|
||||||
if (message == null) throw new Error(`sign: Expected valid message, not "${message}"`);
|
const m = ensureBytes('message', message);
|
||||||
const m = ensureBytes(message); // checks for isWithinCurveOrder
|
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey); // checks for isWithinCurveOrder
|
||||||
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
|
const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array
|
||||||
const a = ensureBytes(auxRand, 32); // Auxiliary random data a: a 32-byte array
|
const t = numTo32b(d ^ bytesToNumberBE(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
||||||
const t = numTo32b(d ^ bytesToInt(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
|
||||||
const rand = taggedHash(TAGS.nonce, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
|
const k_ = modN(bytesToNumberBE(rand)); // Let k' = int(rand) mod n
|
||||||
const k_ = modN(bytesToInt(rand)); // Let k' = int(rand) mod n
|
|
||||||
if (k_ === _0n) throw new Error('sign failed: k is zero'); // Fail if k' = 0.
|
if (k_ === _0n) throw new Error('sign failed: k is zero'); // Fail if k' = 0.
|
||||||
const { point: R, bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
|
const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
|
||||||
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
|
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
|
||||||
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
|
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
|
||||||
sig.set(numTo32b(R.px), 0);
|
sig.set(rx, 0);
|
||||||
sig.set(numTo32b(modN(k + e * d)), 32);
|
sig.set(numTo32b(modN(k + e * d)), 32);
|
||||||
// If Verify(bytes(P), m, sig) (see below) returns failure, abort
|
// If Verify(bytes(P), m, sig) (see below) returns failure, abort
|
||||||
if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced');
|
if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced');
|
||||||
@@ -187,18 +178,20 @@ function schnorrSign(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies Schnorr signature synchronously.
|
* Verifies Schnorr signature.
|
||||||
|
* Will swallow errors & return false except for initial type validation of arguments.
|
||||||
*/
|
*/
|
||||||
function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {
|
function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {
|
||||||
|
const sig = ensureBytes('signature', signature, 64);
|
||||||
|
const m = ensureBytes('message', message);
|
||||||
|
const pub = ensureBytes('publicKey', publicKey, 32);
|
||||||
try {
|
try {
|
||||||
const P = lift_x(hex32ToInt(publicKey)); // P = lift_x(int(pk)); fail if that fails
|
const P = lift_x(bytesToNumberBE(pub)); // P = lift_x(int(pk)); fail if that fails
|
||||||
const sig = ensureBytes(signature, 64);
|
const r = bytesToNumberBE(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
||||||
const r = bytesToInt(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
|
||||||
if (!fe(r)) return false;
|
if (!fe(r)) return false;
|
||||||
const s = bytesToInt(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
|
const s = bytesToNumberBE(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
|
||||||
if (!ge(s)) return false;
|
if (!ge(s)) return false;
|
||||||
const m = ensureBytes(message);
|
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
|
||||||
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
|
|
||||||
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P
|
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P
|
||||||
if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false; // -eP == (n-e)P
|
if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false; // -eP == (n-e)P
|
||||||
return true; // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.
|
return true; // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.
|
||||||
@@ -212,11 +205,11 @@ export const schnorr = {
|
|||||||
sign: schnorrSign,
|
sign: schnorrSign,
|
||||||
verify: schnorrVerify,
|
verify: schnorrVerify,
|
||||||
utils: {
|
utils: {
|
||||||
getExtendedPublicKey: schnorrGetExtPubKey,
|
randomPrivateKey: secp256k1.utils.randomPrivateKey,
|
||||||
lift_x,
|
lift_x,
|
||||||
pointToBytes,
|
pointToBytes,
|
||||||
numberToBytesBE,
|
numberToBytesBE,
|
||||||
bytesToNumberBE: bytesToInt,
|
bytesToNumberBE,
|
||||||
taggedHash,
|
taggedHash,
|
||||||
mod,
|
mod,
|
||||||
},
|
},
|
||||||
@@ -259,7 +252,7 @@ const mapSWU = mapToCurveSimpleSWU(Fp, {
|
|||||||
B: BigInt('1771'),
|
B: BigInt('1771'),
|
||||||
Z: Fp.create(BigInt('-11')),
|
Z: Fp.create(BigInt('-11')),
|
||||||
});
|
});
|
||||||
const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
export const { hashToCurve, encodeToCurve } = htf.createHasher(
|
||||||
secp256k1.ProjectivePoint,
|
secp256k1.ProjectivePoint,
|
||||||
(scalars: bigint[]) => {
|
(scalars: bigint[]) => {
|
||||||
const { x, y } = mapSWU(Fp.create(scalars[0]));
|
const { x, y } = mapSWU(Fp.create(scalars[0]));
|
||||||
@@ -275,4 +268,3 @@ const { hashToCurve, encodeToCurve } = htf.hashToCurve(
|
|||||||
hash: sha256,
|
hash: sha256,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
export { hashToCurve, encodeToCurve };
|
|
||||||
|
|||||||
356
src/stark.ts
356
src/stark.ts
@@ -1,356 +0,0 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
||||||
import { keccak_256 } from '@noble/hashes/sha3';
|
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
|
||||||
import { weierstrass, ProjPointType } from './abstract/weierstrass.js';
|
|
||||||
import * as cutils from './abstract/utils.js';
|
|
||||||
import { Fp, mod, Field, validateField } from './abstract/modular.js';
|
|
||||||
import { getHash } from './_shortw_utils.js';
|
|
||||||
import * as poseidon from './abstract/poseidon.js';
|
|
||||||
import { utf8ToBytes } from '@noble/hashes/utils';
|
|
||||||
|
|
||||||
type ProjectivePoint = ProjPointType<bigint>;
|
|
||||||
// Stark-friendly elliptic curve
|
|
||||||
// https://docs.starkware.co/starkex/stark-curve.html
|
|
||||||
|
|
||||||
const CURVE_N = BigInt(
|
|
||||||
'3618502788666131213697322783095070105526743751716087489154079457884512865583'
|
|
||||||
);
|
|
||||||
const nBitLength = 252;
|
|
||||||
// Copy-pasted from weierstrass.ts
|
|
||||||
function bits2int(bytes: Uint8Array): bigint {
|
|
||||||
const delta = bytes.length * 8 - nBitLength;
|
|
||||||
const num = cutils.bytesToNumberBE(bytes);
|
|
||||||
return delta > 0 ? num >> BigInt(delta) : num;
|
|
||||||
}
|
|
||||||
function bits2int_modN(bytes: Uint8Array): bigint {
|
|
||||||
return mod(bits2int(bytes), CURVE_N);
|
|
||||||
}
|
|
||||||
export const starkCurve = weierstrass({
|
|
||||||
// Params: a, b
|
|
||||||
a: BigInt(1),
|
|
||||||
b: BigInt('3141592653589793238462643383279502884197169399375105820974944592307816406665'),
|
|
||||||
// Field over which we'll do calculations; 2n**251n + 17n * 2n**192n + 1n
|
|
||||||
// There is no efficient sqrt for field (P%4==1)
|
|
||||||
Fp: Fp(BigInt('0x800000000000011000000000000000000000000000000000000000000000001')),
|
|
||||||
// Curve order, total count of valid points in the field.
|
|
||||||
n: CURVE_N,
|
|
||||||
nBitLength: nBitLength, // len(bin(N).replace('0b',''))
|
|
||||||
// Base point (x, y) aka generator point
|
|
||||||
Gx: BigInt('874739451078007766457464989774322083649278607533249481151382481072868806602'),
|
|
||||||
Gy: BigInt('152666792071518830868575557812948353041420400780739481342941381225525861407'),
|
|
||||||
h: BigInt(1),
|
|
||||||
// Default options
|
|
||||||
lowS: false,
|
|
||||||
...getHash(sha256),
|
|
||||||
// Custom truncation routines for stark curve
|
|
||||||
bits2int: (bytes: Uint8Array): bigint => {
|
|
||||||
while (bytes[0] === 0) bytes = bytes.subarray(1);
|
|
||||||
return bits2int(bytes);
|
|
||||||
},
|
|
||||||
bits2int_modN: (bytes: Uint8Array): bigint => {
|
|
||||||
let hashS = cutils.bytesToNumberBE(bytes).toString(16);
|
|
||||||
if (hashS.length === 63) {
|
|
||||||
hashS += '0';
|
|
||||||
bytes = hexToBytes0x(hashS);
|
|
||||||
}
|
|
||||||
// Truncate zero bytes on left (compat with elliptic)
|
|
||||||
while (bytes[0] === 0) bytes = bytes.subarray(1);
|
|
||||||
return bits2int_modN(bytes);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Custom Starknet type conversion functions that can handle 0x and unpadded hex
|
|
||||||
function hexToBytes0x(hex: string): Uint8Array {
|
|
||||||
if (typeof hex !== 'string') {
|
|
||||||
throw new Error('hexToBytes: expected string, got ' + typeof hex);
|
|
||||||
}
|
|
||||||
hex = strip0x(hex);
|
|
||||||
if (hex.length & 1) hex = '0' + hex; // padding
|
|
||||||
if (hex.length % 2) throw new Error('hexToBytes: received invalid unpadded hex ' + hex.length);
|
|
||||||
const array = new Uint8Array(hex.length / 2);
|
|
||||||
for (let i = 0; i < array.length; i++) {
|
|
||||||
const j = i * 2;
|
|
||||||
const hexByte = hex.slice(j, j + 2);
|
|
||||||
const byte = Number.parseInt(hexByte, 16);
|
|
||||||
if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence');
|
|
||||||
array[i] = byte;
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
function hexToNumber0x(hex: string): bigint {
|
|
||||||
if (typeof hex !== 'string') {
|
|
||||||
throw new Error('hexToNumber: expected string, got ' + typeof hex);
|
|
||||||
}
|
|
||||||
// Big Endian
|
|
||||||
// TODO: strip vs no strip?
|
|
||||||
return BigInt(`0x${strip0x(hex)}`);
|
|
||||||
}
|
|
||||||
function bytesToNumber0x(bytes: Uint8Array): bigint {
|
|
||||||
return hexToNumber0x(cutils.bytesToHex(bytes));
|
|
||||||
}
|
|
||||||
function ensureBytes0x(hex: Hex): Uint8Array {
|
|
||||||
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
|
||||||
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
|
||||||
return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes0x(hex);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizePrivateKey(privKey: Hex) {
|
|
||||||
return cutils.bytesToHex(ensureBytes0x(privKey)).padStart(64, '0');
|
|
||||||
}
|
|
||||||
function getPublicKey0x(privKey: Hex, isCompressed = false) {
|
|
||||||
return starkCurve.getPublicKey(normalizePrivateKey(privKey), isCompressed);
|
|
||||||
}
|
|
||||||
function getSharedSecret0x(privKeyA: Hex, pubKeyB: Hex) {
|
|
||||||
return starkCurve.getSharedSecret(normalizePrivateKey(privKeyA), pubKeyB);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sign0x(msgHash: Hex, privKey: Hex, opts?: any) {
|
|
||||||
if (typeof privKey === 'string') privKey = strip0x(privKey).padStart(64, '0');
|
|
||||||
return starkCurve.sign(ensureBytes0x(msgHash), normalizePrivateKey(privKey), opts);
|
|
||||||
}
|
|
||||||
function verify0x(signature: Hex, msgHash: Hex, pubKey: Hex) {
|
|
||||||
const sig = signature instanceof Signature ? signature : ensureBytes0x(signature);
|
|
||||||
return starkCurve.verify(sig, ensureBytes0x(msgHash), ensureBytes0x(pubKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
const { CURVE, ProjectivePoint, Signature } = starkCurve;
|
|
||||||
export const utils = starkCurve.utils;
|
|
||||||
export {
|
|
||||||
CURVE,
|
|
||||||
Signature,
|
|
||||||
ProjectivePoint,
|
|
||||||
getPublicKey0x as getPublicKey,
|
|
||||||
getSharedSecret0x as getSharedSecret,
|
|
||||||
sign0x as sign,
|
|
||||||
verify0x as verify,
|
|
||||||
};
|
|
||||||
|
|
||||||
const stripLeadingZeros = (s: string) => s.replace(/^0+/gm, '');
|
|
||||||
export const bytesToHexEth = (uint8a: Uint8Array): string =>
|
|
||||||
`0x${stripLeadingZeros(cutils.bytesToHex(uint8a))}`;
|
|
||||||
export const strip0x = (hex: string) => hex.replace(/^0x/i, '');
|
|
||||||
export const numberToHexEth = (num: bigint | number) => `0x${num.toString(16)}`;
|
|
||||||
|
|
||||||
// We accept hex strings besides Uint8Array for simplicity
|
|
||||||
type Hex = Uint8Array | string;
|
|
||||||
|
|
||||||
// 1. seed generation
|
|
||||||
function hashKeyWithIndex(key: Uint8Array, index: number) {
|
|
||||||
let indexHex = cutils.numberToHexUnpadded(index);
|
|
||||||
if (indexHex.length & 1) indexHex = '0' + indexHex;
|
|
||||||
return sha256Num(cutils.concatBytes(key, hexToBytes0x(indexHex)));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function grindKey(seed: Hex) {
|
|
||||||
const _seed = ensureBytes0x(seed);
|
|
||||||
const sha256mask = 2n ** 256n;
|
|
||||||
|
|
||||||
const limit = sha256mask - mod(sha256mask, CURVE_N);
|
|
||||||
for (let i = 0; ; i++) {
|
|
||||||
const key = hashKeyWithIndex(_seed, i);
|
|
||||||
// key should be in [0, limit)
|
|
||||||
if (key < limit) return mod(key, CURVE_N).toString(16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStarkKey(privateKey: Hex) {
|
|
||||||
return bytesToHexEth(getPublicKey0x(privateKey, true).slice(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ethSigToPrivate(signature: string) {
|
|
||||||
signature = strip0x(signature.replace(/^0x/, ''));
|
|
||||||
if (signature.length !== 130) throw new Error('Wrong ethereum signature');
|
|
||||||
return grindKey(signature.substring(0, 64));
|
|
||||||
}
|
|
||||||
|
|
||||||
const MASK_31 = 2n ** 31n - 1n;
|
|
||||||
const int31 = (n: bigint) => Number(n & MASK_31);
|
|
||||||
export function getAccountPath(
|
|
||||||
layer: string,
|
|
||||||
application: string,
|
|
||||||
ethereumAddress: string,
|
|
||||||
index: number
|
|
||||||
) {
|
|
||||||
const layerNum = int31(sha256Num(layer));
|
|
||||||
const applicationNum = int31(sha256Num(application));
|
|
||||||
const eth = hexToNumber0x(ethereumAddress);
|
|
||||||
return `m/2645'/${layerNum}'/${applicationNum}'/${int31(eth)}'/${int31(eth >> 31n)}'/${index}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://docs.starkware.co/starkex/pedersen-hash-function.html
|
|
||||||
const PEDERSEN_POINTS_AFFINE = [
|
|
||||||
new ProjectivePoint(
|
|
||||||
2089986280348253421170679821480865132823066470938446095505822317253594081284n,
|
|
||||||
1713931329540660377023406109199410414810705867260802078187082345529207694986n,
|
|
||||||
1n
|
|
||||||
),
|
|
||||||
new ProjectivePoint(
|
|
||||||
996781205833008774514500082376783249102396023663454813447423147977397232763n,
|
|
||||||
1668503676786377725805489344771023921079126552019160156920634619255970485781n,
|
|
||||||
1n
|
|
||||||
),
|
|
||||||
new ProjectivePoint(
|
|
||||||
2251563274489750535117886426533222435294046428347329203627021249169616184184n,
|
|
||||||
1798716007562728905295480679789526322175868328062420237419143593021674992973n,
|
|
||||||
1n
|
|
||||||
),
|
|
||||||
new ProjectivePoint(
|
|
||||||
2138414695194151160943305727036575959195309218611738193261179310511854807447n,
|
|
||||||
113410276730064486255102093846540133784865286929052426931474106396135072156n,
|
|
||||||
1n
|
|
||||||
),
|
|
||||||
new ProjectivePoint(
|
|
||||||
2379962749567351885752724891227938183011949129833673362440656643086021394946n,
|
|
||||||
776496453633298175483985398648758586525933812536653089401905292063708816422n,
|
|
||||||
1n
|
|
||||||
),
|
|
||||||
];
|
|
||||||
// for (const p of PEDERSEN_POINTS) p._setWindowSize(8);
|
|
||||||
const PEDERSEN_POINTS = PEDERSEN_POINTS_AFFINE;
|
|
||||||
|
|
||||||
function pedersenPrecompute(p1: ProjectivePoint, p2: ProjectivePoint): ProjectivePoint[] {
|
|
||||||
const out: ProjectivePoint[] = [];
|
|
||||||
let p = p1;
|
|
||||||
for (let i = 0; i < 248; i++) {
|
|
||||||
out.push(p);
|
|
||||||
p = p.double();
|
|
||||||
}
|
|
||||||
// NOTE: we cannot use wNAF here, because last 4 bits will require full 248 bits multiplication
|
|
||||||
// We can add support for this to wNAF, but it will complicate wNAF.
|
|
||||||
p = p2;
|
|
||||||
for (let i = 0; i < 4; i++) {
|
|
||||||
out.push(p);
|
|
||||||
p = p.double();
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
const PEDERSEN_POINTS1 = pedersenPrecompute(PEDERSEN_POINTS[1], PEDERSEN_POINTS[2]);
|
|
||||||
const PEDERSEN_POINTS2 = pedersenPrecompute(PEDERSEN_POINTS[3], PEDERSEN_POINTS[4]);
|
|
||||||
|
|
||||||
type PedersenArg = Hex | bigint | number;
|
|
||||||
function pedersenArg(arg: PedersenArg): bigint {
|
|
||||||
let value: bigint;
|
|
||||||
if (typeof arg === 'bigint') value = arg;
|
|
||||||
else if (typeof arg === 'number') {
|
|
||||||
if (!Number.isSafeInteger(arg)) throw new Error(`Invalid pedersenArg: ${arg}`);
|
|
||||||
value = BigInt(arg);
|
|
||||||
} else value = bytesToNumber0x(ensureBytes0x(arg));
|
|
||||||
// [0..Fp)
|
|
||||||
if (!(0n <= value && value < starkCurve.CURVE.Fp.ORDER))
|
|
||||||
throw new Error(`PedersenArg should be 0 <= value < CURVE.P: ${value}`);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pedersenSingle(point: ProjectivePoint, value: PedersenArg, constants: ProjectivePoint[]) {
|
|
||||||
let x = pedersenArg(value);
|
|
||||||
for (let j = 0; j < 252; j++) {
|
|
||||||
const pt = constants[j];
|
|
||||||
if (pt.px === point.px) throw new Error('Same point');
|
|
||||||
if ((x & 1n) !== 0n) point = point.add(pt);
|
|
||||||
x >>= 1n;
|
|
||||||
}
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shift_point + x_low * P_0 + x_high * P1 + y_low * P2 + y_high * P3
|
|
||||||
export function pedersen(x: PedersenArg, y: PedersenArg) {
|
|
||||||
let point: ProjectivePoint = PEDERSEN_POINTS[0];
|
|
||||||
point = pedersenSingle(point, x, PEDERSEN_POINTS1);
|
|
||||||
point = pedersenSingle(point, y, PEDERSEN_POINTS2);
|
|
||||||
return bytesToHexEth(point.toRawBytes(true).slice(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hashChain(data: PedersenArg[], fn = pedersen) {
|
|
||||||
if (!Array.isArray(data) || data.length < 1)
|
|
||||||
throw new Error('data should be array of at least 1 element');
|
|
||||||
if (data.length === 1) return numberToHexEth(pedersenArg(data[0]));
|
|
||||||
return Array.from(data)
|
|
||||||
.reverse()
|
|
||||||
.reduce((acc, i) => fn(i, acc));
|
|
||||||
}
|
|
||||||
// Same as hashChain, but computes hash even for single element and order is not revesed
|
|
||||||
export const computeHashOnElements = (data: PedersenArg[], fn = pedersen) =>
|
|
||||||
[0, ...data, data.length].reduce((x, y) => fn(x, y));
|
|
||||||
|
|
||||||
const MASK_250 = cutils.bitMask(250);
|
|
||||||
export const keccak = (data: Uint8Array): bigint => bytesToNumber0x(keccak_256(data)) & MASK_250;
|
|
||||||
const sha256Num = (data: Uint8Array | string): bigint => cutils.bytesToNumberBE(sha256(data));
|
|
||||||
|
|
||||||
// Poseidon hash
|
|
||||||
export const Fp253 = Fp(
|
|
||||||
BigInt('14474011154664525231415395255581126252639794253786371766033694892385558855681')
|
|
||||||
); // 2^253 + 2^199 + 1
|
|
||||||
export const Fp251 = Fp(
|
|
||||||
BigInt('3618502788666131213697322783095070105623107215331596699973092056135872020481')
|
|
||||||
); // 2^251 + 17 * 2^192 + 1
|
|
||||||
|
|
||||||
function poseidonRoundConstant(Fp: Field<bigint>, name: string, idx: number) {
|
|
||||||
const val = Fp.fromBytes(sha256(utf8ToBytes(`${name}${idx}`)));
|
|
||||||
return Fp.create(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: doesn't check eiginvalues and possible can create unsafe matrix. But any filtration here will break compatibility with starknet
|
|
||||||
// Please use only if you really know what you doing.
|
|
||||||
// https://eprint.iacr.org/2019/458.pdf Section 2.3 (Avoiding Insecure Matrices)
|
|
||||||
export function _poseidonMDS(Fp: Field<bigint>, name: string, m: number, attempt = 0) {
|
|
||||||
const x_values: bigint[] = [];
|
|
||||||
const y_values: bigint[] = [];
|
|
||||||
for (let i = 0; i < m; i++) {
|
|
||||||
x_values.push(poseidonRoundConstant(Fp, `${name}x`, attempt * m + i));
|
|
||||||
y_values.push(poseidonRoundConstant(Fp, `${name}y`, attempt * m + i));
|
|
||||||
}
|
|
||||||
if (new Set([...x_values, ...y_values]).size !== 2 * m)
|
|
||||||
throw new Error('X and Y values are not distinct');
|
|
||||||
return x_values.map((x) => y_values.map((y) => Fp.inv(Fp.sub(x, y))));
|
|
||||||
}
|
|
||||||
|
|
||||||
const MDS_SMALL = [
|
|
||||||
[3, 1, 1],
|
|
||||||
[1, -1, 1],
|
|
||||||
[1, 1, -2],
|
|
||||||
].map((i) => i.map(BigInt));
|
|
||||||
|
|
||||||
export type PoseidonOpts = {
|
|
||||||
Fp: Field<bigint>;
|
|
||||||
rate: number;
|
|
||||||
capacity: number;
|
|
||||||
roundsFull: number;
|
|
||||||
roundsPartial: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function poseidonBasic(opts: PoseidonOpts, mds: bigint[][]) {
|
|
||||||
validateField(opts.Fp);
|
|
||||||
if (!Number.isSafeInteger(opts.rate) || !Number.isSafeInteger(opts.capacity))
|
|
||||||
throw new Error(`Wrong poseidon opts: ${opts}`);
|
|
||||||
const m = opts.rate + opts.capacity;
|
|
||||||
const rounds = opts.roundsFull + opts.roundsPartial;
|
|
||||||
const roundConstants = [];
|
|
||||||
for (let i = 0; i < rounds; i++) {
|
|
||||||
const row = [];
|
|
||||||
for (let j = 0; j < m; j++) row.push(poseidonRoundConstant(opts.Fp, 'Hades', m * i + j));
|
|
||||||
roundConstants.push(row);
|
|
||||||
}
|
|
||||||
return poseidon.poseidon({
|
|
||||||
...opts,
|
|
||||||
t: m,
|
|
||||||
sboxPower: 3,
|
|
||||||
reversePartialPowIdx: true, // Why?!
|
|
||||||
mds,
|
|
||||||
roundConstants,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function poseidonCreate(opts: PoseidonOpts, mdsAttempt = 0) {
|
|
||||||
const m = opts.rate + opts.capacity;
|
|
||||||
if (!Number.isSafeInteger(mdsAttempt)) throw new Error(`Wrong mdsAttempt=${mdsAttempt}`);
|
|
||||||
return poseidonBasic(opts, _poseidonMDS(opts.Fp, 'HadesMDS', m, mdsAttempt));
|
|
||||||
}
|
|
||||||
|
|
||||||
export const poseidonSmall = poseidonBasic(
|
|
||||||
{ Fp: Fp251, rate: 2, capacity: 1, roundsFull: 8, roundsPartial: 83 },
|
|
||||||
MDS_SMALL
|
|
||||||
);
|
|
||||||
|
|
||||||
export function poseidonHash(x: bigint, y: bigint, fn = poseidonSmall) {
|
|
||||||
return fn([x, y, 2n])[0];
|
|
||||||
}
|
|
||||||
44
test/_more-curves.helpers.js
Normal file
44
test/_more-curves.helpers.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
import { createCurve } from '../esm/_shortw_utils.js';
|
||||||
|
import { sha224, sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { Fp } from '../esm/abstract/modular.js';
|
||||||
|
|
||||||
|
// NIST secp192r1 aka P192
|
||||||
|
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1
|
||||||
|
export const P192 = createCurve(
|
||||||
|
{
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'),
|
||||||
|
b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'),
|
||||||
|
// Field over which we'll do calculations; 2n ** 192n - 2n ** 64n - 1n
|
||||||
|
Fp: Fp(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')),
|
||||||
|
// Curve order, total count of valid points in the field.
|
||||||
|
n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'),
|
||||||
|
Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'),
|
||||||
|
h: BigInt(1),
|
||||||
|
lowS: false,
|
||||||
|
},
|
||||||
|
sha256
|
||||||
|
);
|
||||||
|
export const secp192r1 = P192;
|
||||||
|
|
||||||
|
export const P224 = createCurve(
|
||||||
|
{
|
||||||
|
// Params: a, b
|
||||||
|
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
|
||||||
|
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
|
||||||
|
// Field over which we'll do calculations;
|
||||||
|
Fp: Fp(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),
|
||||||
|
// Curve order, total count of valid points in the field
|
||||||
|
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
|
||||||
|
// Base point (x, y) aka generator point
|
||||||
|
Gx: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
|
||||||
|
Gy: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34'),
|
||||||
|
h: BigInt(1),
|
||||||
|
lowS: false,
|
||||||
|
},
|
||||||
|
sha224
|
||||||
|
);
|
||||||
|
export const secp224r1 = P224;
|
||||||
103
test/_poseidon.helpers.js
Normal file
103
test/_poseidon.helpers.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
|
import { utf8ToBytes } from '@noble/hashes/utils';
|
||||||
|
import { Fp, validateField } from '../esm/abstract/modular.js';
|
||||||
|
import { poseidon } from '../esm/abstract/poseidon.js';
|
||||||
|
import * as u from '../esm/abstract/utils.js';
|
||||||
|
|
||||||
|
// Poseidon hash https://docs.starkware.co/starkex/stark-curve.html
|
||||||
|
export const Fp253 = Fp(
|
||||||
|
BigInt('14474011154664525231415395255581126252639794253786371766033694892385558855681')
|
||||||
|
); // 2^253 + 2^199 + 1
|
||||||
|
export const Fp251 = Fp(
|
||||||
|
BigInt('3618502788666131213697322783095070105623107215331596699973092056135872020481')
|
||||||
|
); // 2^251 + 17 * 2^192 + 1
|
||||||
|
|
||||||
|
function poseidonRoundConstant(Fp, name, idx) {
|
||||||
|
const val = Fp.fromBytes(sha256(utf8ToBytes(`${name}${idx}`)));
|
||||||
|
return Fp.create(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: doesn't check eiginvalues and possible can create unsafe matrix. But any filtration here will break compatibility with starknet
|
||||||
|
// Please use only if you really know what you doing.
|
||||||
|
// https://eprint.iacr.org/2019/458.pdf Section 2.3 (Avoiding Insecure Matrices)
|
||||||
|
export function _poseidonMDS(Fp, name, m, attempt = 0) {
|
||||||
|
const x_values = [];
|
||||||
|
const y_values = [];
|
||||||
|
for (let i = 0; i < m; i++) {
|
||||||
|
x_values.push(poseidonRoundConstant(Fp, `${name}x`, attempt * m + i));
|
||||||
|
y_values.push(poseidonRoundConstant(Fp, `${name}y`, attempt * m + i));
|
||||||
|
}
|
||||||
|
if (new Set([...x_values, ...y_values]).size !== 2 * m)
|
||||||
|
throw new Error('X and Y values are not distinct');
|
||||||
|
return x_values.map((x) => y_values.map((y) => Fp.inv(Fp.sub(x, y))));
|
||||||
|
}
|
||||||
|
|
||||||
|
const MDS_SMALL = [
|
||||||
|
[3, 1, 1],
|
||||||
|
[1, -1, 1],
|
||||||
|
[1, 1, -2],
|
||||||
|
].map((i) => i.map(BigInt));
|
||||||
|
|
||||||
|
export function poseidonBasic(opts, mds) {
|
||||||
|
validateField(opts.Fp);
|
||||||
|
if (!Number.isSafeInteger(opts.rate) || !Number.isSafeInteger(opts.capacity))
|
||||||
|
throw new Error(`Wrong poseidon opts: ${opts}`);
|
||||||
|
const m = opts.rate + opts.capacity;
|
||||||
|
const rounds = opts.roundsFull + opts.roundsPartial;
|
||||||
|
const roundConstants = [];
|
||||||
|
for (let i = 0; i < rounds; i++) {
|
||||||
|
const row = [];
|
||||||
|
for (let j = 0; j < m; j++) row.push(poseidonRoundConstant(opts.Fp, 'Hades', m * i + j));
|
||||||
|
roundConstants.push(row);
|
||||||
|
}
|
||||||
|
const res = poseidon({
|
||||||
|
...opts,
|
||||||
|
t: m,
|
||||||
|
sboxPower: 3,
|
||||||
|
reversePartialPowIdx: true, // Why?!
|
||||||
|
mds,
|
||||||
|
roundConstants,
|
||||||
|
});
|
||||||
|
res.m = m;
|
||||||
|
res.rate = opts.rate;
|
||||||
|
res.capacity = opts.capacity;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function poseidonCreate(opts, mdsAttempt = 0) {
|
||||||
|
const m = opts.rate + opts.capacity;
|
||||||
|
if (!Number.isSafeInteger(mdsAttempt)) throw new Error(`Wrong mdsAttempt=${mdsAttempt}`);
|
||||||
|
return poseidonBasic(opts, _poseidonMDS(opts.Fp, 'HadesMDS', m, mdsAttempt));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const poseidonSmall = poseidonBasic(
|
||||||
|
{ Fp: Fp251, rate: 2, capacity: 1, roundsFull: 8, roundsPartial: 83 },
|
||||||
|
MDS_SMALL
|
||||||
|
);
|
||||||
|
|
||||||
|
export function poseidonHash(x, y, fn = poseidonSmall) {
|
||||||
|
return fn([x, y, 2n])[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function poseidonHashFunc(x, y, fn = poseidonSmall) {
|
||||||
|
return u.numberToVarBytesBE(poseidonHash(u.bytesToNumberBE(x), u.bytesToNumberBE(y), fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function poseidonHashSingle(x, fn = poseidonSmall) {
|
||||||
|
return fn([x, 0n, 1n])[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function poseidonHashMany(values, fn = poseidonSmall) {
|
||||||
|
const { m, rate } = fn;
|
||||||
|
if (!Array.isArray(values)) throw new Error('bigint array expected in values');
|
||||||
|
const padded = Array.from(values); // copy
|
||||||
|
padded.push(1n);
|
||||||
|
while (padded.length % rate !== 0) padded.push(0n);
|
||||||
|
let state = new Array(m).fill(0n);
|
||||||
|
for (let i = 0; i < padded.length; i += rate) {
|
||||||
|
for (let j = 0; j < rate; j++) state[j] += padded[i + j];
|
||||||
|
state = fn(state);
|
||||||
|
}
|
||||||
|
return state[0];
|
||||||
|
}
|
||||||
@@ -1,22 +1,20 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
import { should, describe } from 'micro-should';
|
import { should, describe } from 'micro-should';
|
||||||
import * as fc from 'fast-check';
|
import * as fc from 'fast-check';
|
||||||
import * as mod from '../lib/esm/abstract/modular.js';
|
import * as mod from '../esm/abstract/modular.js';
|
||||||
import { bytesToHex as toHex } from '../lib/esm/abstract/utils.js';
|
import { bytesToHex as toHex } from '../esm/abstract/utils.js';
|
||||||
// Generic tests for all curves in package
|
// Generic tests for all curves in package
|
||||||
import { secp192r1 } from '../lib/esm/p192.js';
|
import { secp192r1, secp224r1 } from './_more-curves.helpers.js';
|
||||||
import { secp224r1 } from '../lib/esm/p224.js';
|
import { secp256r1 } from '../esm/p256.js';
|
||||||
import { secp256r1 } from '../lib/esm/p256.js';
|
import { secp384r1 } from '../esm/p384.js';
|
||||||
import { secp384r1 } from '../lib/esm/p384.js';
|
import { secp521r1 } from '../esm/p521.js';
|
||||||
import { secp521r1 } from '../lib/esm/p521.js';
|
import { secp256k1 } from '../esm/secp256k1.js';
|
||||||
import { secp256k1 } from '../lib/esm/secp256k1.js';
|
import { ed25519, ed25519ctx, ed25519ph, x25519 } from '../esm/ed25519.js';
|
||||||
import { ed25519, ed25519ctx, ed25519ph, x25519 } from '../lib/esm/ed25519.js';
|
import { ed448, ed448ph } from '../esm/ed448.js';
|
||||||
import { ed448, ed448ph } from '../lib/esm/ed448.js';
|
import { pallas, vesta } from '../esm/pasta.js';
|
||||||
import { starkCurve } from '../lib/esm/stark.js';
|
import { bn254 } from '../esm/bn.js';
|
||||||
import { pallas, vesta } from '../lib/esm/pasta.js';
|
import { jubjub } from '../esm/jubjub.js';
|
||||||
import { bn254 } from '../lib/esm/bn.js';
|
import { bls12_381 } from '../esm/bls12-381.js';
|
||||||
import { jubjub } from '../lib/esm/jubjub.js';
|
|
||||||
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
|
||||||
|
|
||||||
// Fields tests
|
// Fields tests
|
||||||
const FIELDS = {
|
const FIELDS = {
|
||||||
@@ -25,7 +23,6 @@ const FIELDS = {
|
|||||||
secp256r1: { Fp: [secp256r1.CURVE.Fp] },
|
secp256r1: { Fp: [secp256r1.CURVE.Fp] },
|
||||||
secp521r1: { Fp: [secp521r1.CURVE.Fp] },
|
secp521r1: { Fp: [secp521r1.CURVE.Fp] },
|
||||||
secp256k1: { Fp: [secp256k1.CURVE.Fp] },
|
secp256k1: { Fp: [secp256k1.CURVE.Fp] },
|
||||||
stark: { Fp: [starkCurve.CURVE.Fp] },
|
|
||||||
jubjub: { Fp: [jubjub.CURVE.Fp] },
|
jubjub: { Fp: [jubjub.CURVE.Fp] },
|
||||||
ed25519: { Fp: [ed25519.CURVE.Fp] },
|
ed25519: { Fp: [ed25519.CURVE.Fp] },
|
||||||
ed448: { Fp: [ed448.CURVE.Fp] },
|
ed448: { Fp: [ed448.CURVE.Fp] },
|
||||||
@@ -315,7 +312,6 @@ const CURVES = {
|
|||||||
secp256k1,
|
secp256k1,
|
||||||
ed25519, ed25519ctx, ed25519ph,
|
ed25519, ed25519ctx, ed25519ph,
|
||||||
ed448, ed448ph,
|
ed448, ed448ph,
|
||||||
starkCurve,
|
|
||||||
pallas, vesta,
|
pallas, vesta,
|
||||||
bn254,
|
bn254,
|
||||||
jubjub,
|
jubjub,
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
|
||||||
import { describe, should } from 'micro-should';
|
|
||||||
import { deepStrictEqual, notDeepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, notDeepStrictEqual, throws } from 'assert';
|
||||||
import { sha512 } from '@noble/hashes/sha512';
|
|
||||||
import * as fc from 'fast-check';
|
import * as fc from 'fast-check';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
|
import { describe, should } from 'micro-should';
|
||||||
|
import { wNAF } from '../esm/abstract/curve.js';
|
||||||
|
import { bytesToHex, utf8ToBytes } from '../esm/abstract/utils.js';
|
||||||
|
import { hash_to_field } from '../esm/abstract/hash-to-curve.js';
|
||||||
|
import { bls12_381 as bls } from '../esm/bls12-381.js';
|
||||||
|
|
||||||
import zkVectors from './bls12-381/zkcrypto/converted.json' assert { type: 'json' };
|
import zkVectors from './bls12-381/zkcrypto/converted.json' assert { type: 'json' };
|
||||||
import pairingVectors from './bls12-381/go_pairing_vectors/pairing.json' assert { type: 'json' };
|
import pairingVectors from './bls12-381/go_pairing_vectors/pairing.json' assert { type: 'json' };
|
||||||
import { wNAF } from '../lib/esm/abstract/curve.js';
|
|
||||||
const bls = bls12_381;
|
|
||||||
const { Fp2 } = bls;
|
|
||||||
const G1Point = bls.G1.ProjectivePoint;
|
|
||||||
const G2Point = bls.G2.ProjectivePoint;
|
|
||||||
const G1Aff = (x, y) => G1Point.fromAffine({ x, y });
|
|
||||||
|
|
||||||
const G2_VECTORS = readFileSync('./test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
|
const G2_VECTORS = readFileSync('./test/bls12-381/bls12-381-g2-test-vectors.txt', 'utf-8')
|
||||||
.trim()
|
.trim()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
@@ -28,7 +24,10 @@ const SCALAR_VECTORS = readFileSync('./test/bls12-381/bls12-381-scalar-test-vect
|
|||||||
const NUM_RUNS = Number(process.env.RUNS_COUNT || 10); // reduce to 1 to shorten test time
|
const NUM_RUNS = Number(process.env.RUNS_COUNT || 10); // reduce to 1 to shorten test time
|
||||||
fc.configureGlobal({ numRuns: NUM_RUNS });
|
fc.configureGlobal({ numRuns: NUM_RUNS });
|
||||||
|
|
||||||
// @ts-ignore
|
const { Fp2 } = bls;
|
||||||
|
const G1Point = bls.G1.ProjectivePoint;
|
||||||
|
const G2Point = bls.G2.ProjectivePoint;
|
||||||
|
const G1Aff = (x, y) => G1Point.fromAffine({ x, y });
|
||||||
const CURVE_ORDER = bls.CURVE.r;
|
const CURVE_ORDER = bls.CURVE.r;
|
||||||
|
|
||||||
const FC_MSG = fc.hexaString({ minLength: 64, maxLength: 64 });
|
const FC_MSG = fc.hexaString({ minLength: 64, maxLength: 64 });
|
||||||
@@ -851,20 +850,20 @@ describe('bls12-381/basic', () => {
|
|||||||
for (let vector of G2_VECTORS) {
|
for (let vector of G2_VECTORS) {
|
||||||
const [priv, msg, expected] = vector;
|
const [priv, msg, expected] = vector;
|
||||||
const sig = bls.sign(msg, priv);
|
const sig = bls.sign(msg, priv);
|
||||||
deepStrictEqual(bls.utils.bytesToHex(sig), expected);
|
deepStrictEqual(bytesToHex(sig), expected);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
should(`produce correct scalars (${SCALAR_VECTORS.length} vectors)`, () => {
|
should(`produce correct scalars (${SCALAR_VECTORS.length} vectors)`, () => {
|
||||||
const options = {
|
const options = {
|
||||||
p: bls.CURVE.r,
|
p: bls.CURVE.r,
|
||||||
m: 1,
|
m: 1,
|
||||||
expand: false,
|
expand: undefined,
|
||||||
};
|
};
|
||||||
for (let vector of SCALAR_VECTORS) {
|
for (let vector of SCALAR_VECTORS) {
|
||||||
const [okmAscii, expectedHex] = vector;
|
const [okmAscii, expectedHex] = vector;
|
||||||
const expected = BigInt('0x' + expectedHex);
|
const expected = BigInt('0x' + expectedHex);
|
||||||
const okm = new Uint8Array(okmAscii.split('').map((c) => c.charCodeAt(0)));
|
const okm = utf8ToBytes(okmAscii);
|
||||||
const scalars = bls.utils.hashToField(okm, 1, options);
|
const scalars = hash_to_field(okm, 1, Object.assign({}, bls.CURVE.htfDefaults, options));
|
||||||
deepStrictEqual(scalars[0][0], expected);
|
deepStrictEqual(scalars[0][0], expected);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -973,25 +972,25 @@ describe('hash-to-curve', () => {
|
|||||||
// Point G1
|
// Point G1
|
||||||
const VECTORS_G1 = [
|
const VECTORS_G1 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'0576730ab036cbac1d95b38dca905586f28d0a59048db4e8778782d89bff856ddef89277ead5a21e2975c4a6e3d8c79e' +
|
'0576730ab036cbac1d95b38dca905586f28d0a59048db4e8778782d89bff856ddef89277ead5a21e2975c4a6e3d8c79e' +
|
||||||
'1273e568bebf1864393c517f999b87c1eaa1b8432f95aea8160cd981b5b05d8cd4a7cf00103b6ef87f728e4b547dd7ae',
|
'1273e568bebf1864393c517f999b87c1eaa1b8432f95aea8160cd981b5b05d8cd4a7cf00103b6ef87f728e4b547dd7ae',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'061daf0cc00d8912dac1d4cf5a7c32fca97f8b3bf3f805121888e5eb89f77f9a9f406569027ac6d0e61b1229f42c43d6' +
|
'061daf0cc00d8912dac1d4cf5a7c32fca97f8b3bf3f805121888e5eb89f77f9a9f406569027ac6d0e61b1229f42c43d6' +
|
||||||
'0de1601e5ba02cb637c1d35266f5700acee9850796dc88e860d022d7b9e7e3dce5950952e97861e5bb16d215c87f030d',
|
'0de1601e5ba02cb637c1d35266f5700acee9850796dc88e860d022d7b9e7e3dce5950952e97861e5bb16d215c87f030d',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'0fb3455436843e76079c7cf3dfef75e5a104dfe257a29a850c145568d500ad31ccfe79be9ae0ea31a722548070cf98cd' +
|
'0fb3455436843e76079c7cf3dfef75e5a104dfe257a29a850c145568d500ad31ccfe79be9ae0ea31a722548070cf98cd' +
|
||||||
'177989f7e2c751658df1b26943ee829d3ebcf131d8f805571712f3a7527ee5334ecff8a97fc2a50cea86f5e6212e9a57',
|
'177989f7e2c751658df1b26943ee829d3ebcf131d8f805571712f3a7527ee5334ecff8a97fc2a50cea86f5e6212e9a57',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@@ -1002,7 +1001,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_G1.length; i++) {
|
for (let i = 0; i < VECTORS_G1.length; i++) {
|
||||||
const t = VECTORS_G1[i];
|
const t = VECTORS_G1[i];
|
||||||
should(`hashToCurve/G1 Killic (${i})`, () => {
|
should(`hashToCurve/G1 Killic (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G1.hashToCurve(t.msg, {
|
const p = bls.G1.hashToCurve(t.msg, {
|
||||||
DST: 'BLS12381G1_XMD:SHA-256_SSWU_RO_TESTGEN',
|
DST: 'BLS12381G1_XMD:SHA-256_SSWU_RO_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@@ -1011,25 +1010,25 @@ describe('hash-to-curve', () => {
|
|||||||
|
|
||||||
const VECTORS_ENCODE_G1 = [
|
const VECTORS_ENCODE_G1 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c' +
|
'1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c' +
|
||||||
'0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5',
|
'0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6' +
|
'179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6' +
|
||||||
'0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4',
|
'0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af' +
|
'15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af' +
|
||||||
'0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788',
|
'0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@@ -1040,7 +1039,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_ENCODE_G1.length; i++) {
|
for (let i = 0; i < VECTORS_ENCODE_G1.length; i++) {
|
||||||
const t = VECTORS_ENCODE_G1[i];
|
const t = VECTORS_ENCODE_G1[i];
|
||||||
should(`hashToCurve/G1 (Killic, encodeToCurve) (${i})`, () => {
|
should(`hashToCurve/G1 (Killic, encodeToCurve) (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G1.encodeToCurve(t.msg, {
|
const p = bls.G1.encodeToCurve(t.msg, {
|
||||||
DST: 'BLS12381G1_XMD:SHA-256_SSWU_NU_TESTGEN',
|
DST: 'BLS12381G1_XMD:SHA-256_SSWU_NU_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@@ -1049,7 +1048,7 @@ describe('hash-to-curve', () => {
|
|||||||
// Point G2
|
// Point G2
|
||||||
const VECTORS_G2 = [
|
const VECTORS_G2 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'0fbdae26f9f9586a46d4b0b70390d09064ef2afe5c99348438a3c7d9756471e015cb534204c1b6824617a85024c772dc' +
|
'0fbdae26f9f9586a46d4b0b70390d09064ef2afe5c99348438a3c7d9756471e015cb534204c1b6824617a85024c772dc' +
|
||||||
'0a650bd36ae7455cb3fe5d8bb1310594551456f5c6593aec9ee0c03d2f6cb693bd2c5e99d4e23cbaec767609314f51d3' +
|
'0a650bd36ae7455cb3fe5d8bb1310594551456f5c6593aec9ee0c03d2f6cb693bd2c5e99d4e23cbaec767609314f51d3' +
|
||||||
@@ -1057,7 +1056,7 @@ describe('hash-to-curve', () => {
|
|||||||
'0d8d49e7737d8f9fc5cef7c4b8817633103faf2613016cb86a1f3fc29968fe2413e232d9208d2d74a89bf7a48ac36f83',
|
'0d8d49e7737d8f9fc5cef7c4b8817633103faf2613016cb86a1f3fc29968fe2413e232d9208d2d74a89bf7a48ac36f83',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'03578447618463deb106b60e609c6f7cc446dc6035f84a72801ba17c94cd800583b493b948eff0033f09086fdd7f6175' +
|
'03578447618463deb106b60e609c6f7cc446dc6035f84a72801ba17c94cd800583b493b948eff0033f09086fdd7f6175' +
|
||||||
'1953ce6d4267939c7360756d9cca8eb34aac4633ef35369a7dc249445069888e7d1b3f9d2e75fbd468fbcbba7110ea02' +
|
'1953ce6d4267939c7360756d9cca8eb34aac4633ef35369a7dc249445069888e7d1b3f9d2e75fbd468fbcbba7110ea02' +
|
||||||
@@ -1065,7 +1064,7 @@ describe('hash-to-curve', () => {
|
|||||||
'0882ab045b8fe4d7d557ebb59a63a35ac9f3d312581b509af0f8eaa2960cbc5e1e36bb969b6e22980b5cbdd0787fcf4e',
|
'0882ab045b8fe4d7d557ebb59a63a35ac9f3d312581b509af0f8eaa2960cbc5e1e36bb969b6e22980b5cbdd0787fcf4e',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'195fad48982e186ce3c5c82133aefc9b26d55979b6f530992a8849d4263ec5d57f7a181553c8799bcc83da44847bdc8d' +
|
'195fad48982e186ce3c5c82133aefc9b26d55979b6f530992a8849d4263ec5d57f7a181553c8799bcc83da44847bdc8d' +
|
||||||
'17b461fc3b96a30c2408958cbfa5f5927b6063a8ad199d5ebf2d7cdeffa9c20c85487204804fab53f950b2f87db365aa' +
|
'17b461fc3b96a30c2408958cbfa5f5927b6063a8ad199d5ebf2d7cdeffa9c20c85487204804fab53f950b2f87db365aa' +
|
||||||
@@ -1073,7 +1072,7 @@ describe('hash-to-curve', () => {
|
|||||||
'174a3473a3af2d0302b9065e895ca4adba4ece6ce0b41148ba597001abb152f852dd9a96fb45c9de0a43d944746f833e',
|
'174a3473a3af2d0302b9065e895ca4adba4ece6ce0b41148ba597001abb152f852dd9a96fb45c9de0a43d944746f833e',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@@ -1086,7 +1085,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_G2.length; i++) {
|
for (let i = 0; i < VECTORS_G2.length; i++) {
|
||||||
const t = VECTORS_G2[i];
|
const t = VECTORS_G2[i];
|
||||||
should(`hashToCurve/G2 Killic (${i})`, () => {
|
should(`hashToCurve/G2 Killic (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G2.hashToCurve(t.msg, {
|
const p = bls.G2.hashToCurve(t.msg, {
|
||||||
DST: 'BLS12381G2_XMD:SHA-256_SSWU_RO_TESTGEN',
|
DST: 'BLS12381G2_XMD:SHA-256_SSWU_RO_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@@ -1095,7 +1094,7 @@ describe('hash-to-curve', () => {
|
|||||||
|
|
||||||
const VECTORS_ENCODE_G2 = [
|
const VECTORS_ENCODE_G2 = [
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(''),
|
msg: utf8ToBytes(''),
|
||||||
expected:
|
expected:
|
||||||
'0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8' +
|
'0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8' +
|
||||||
'027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d' +
|
'027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d' +
|
||||||
@@ -1103,7 +1102,7 @@ describe('hash-to-curve', () => {
|
|||||||
'053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7',
|
'053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abc'),
|
msg: utf8ToBytes('abc'),
|
||||||
expected:
|
expected:
|
||||||
'18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778' +
|
'18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778' +
|
||||||
'09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b' +
|
'09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b' +
|
||||||
@@ -1111,7 +1110,7 @@ describe('hash-to-curve', () => {
|
|||||||
'02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811',
|
'02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes('abcdef0123456789'),
|
msg: utf8ToBytes('abcdef0123456789'),
|
||||||
expected:
|
expected:
|
||||||
'19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163' +
|
'19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163' +
|
||||||
'149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7' +
|
'149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7' +
|
||||||
@@ -1119,7 +1118,7 @@ describe('hash-to-curve', () => {
|
|||||||
'04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551',
|
'04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: bls.utils.stringToBytes(
|
msg: utf8ToBytes(
|
||||||
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
'a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||||
),
|
),
|
||||||
expected:
|
expected:
|
||||||
@@ -1132,7 +1131,7 @@ describe('hash-to-curve', () => {
|
|||||||
for (let i = 0; i < VECTORS_ENCODE_G2.length; i++) {
|
for (let i = 0; i < VECTORS_ENCODE_G2.length; i++) {
|
||||||
const t = VECTORS_ENCODE_G2[i];
|
const t = VECTORS_ENCODE_G2[i];
|
||||||
should(`hashToCurve/G2 (Killic, encodeToCurve) (${i})`, () => {
|
should(`hashToCurve/G2 (Killic, encodeToCurve) (${i})`, () => {
|
||||||
const p = bls.hashToCurve.G2.encodeToCurve(t.msg, {
|
const p = bls.G2.encodeToCurve(t.msg, {
|
||||||
DST: 'BLS12381G2_XMD:SHA-256_SSWU_NU_TESTGEN',
|
DST: 'BLS12381G2_XMD:SHA-256_SSWU_NU_TESTGEN',
|
||||||
});
|
});
|
||||||
deepStrictEqual(p.toHex(false), t.expected);
|
deepStrictEqual(p.toHex(false), t.expected);
|
||||||
@@ -1265,7 +1264,7 @@ describe('bls12-381 deterministic', () => {
|
|||||||
should('Killic based/Pairing', () => {
|
should('Killic based/Pairing', () => {
|
||||||
const t = bls.pairing(G1Point.BASE, G2Point.BASE);
|
const t = bls.pairing(G1Point.BASE, G2Point.BASE);
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
bls.utils.bytesToHex(Fp12.toBytes(t)),
|
bytesToHex(Fp12.toBytes(t)),
|
||||||
killicHex([
|
killicHex([
|
||||||
'0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631',
|
'0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631',
|
||||||
'04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef',
|
'04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef',
|
||||||
@@ -1287,7 +1286,7 @@ describe('bls12-381 deterministic', () => {
|
|||||||
let p2 = G2Point.BASE;
|
let p2 = G2Point.BASE;
|
||||||
for (let v of pairingVectors) {
|
for (let v of pairingVectors) {
|
||||||
deepStrictEqual(
|
deepStrictEqual(
|
||||||
bls.utils.bytesToHex(Fp12.toBytes(bls.pairing(p1, p2))),
|
bytesToHex(Fp12.toBytes(bls.pairing(p1, p2))),
|
||||||
// Reverse order
|
// Reverse order
|
||||||
v.match(/.{96}/g).reverse().join('')
|
v.match(/.{96}/g).reverse().join('')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { sha512 } from '@noble/hashes/sha512';
|
|||||||
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
|
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
|
||||||
import { deepStrictEqual, strictEqual, throws } from 'assert';
|
import { deepStrictEqual, strictEqual, throws } from 'assert';
|
||||||
import { describe, should } from 'micro-should';
|
import { describe, should } from 'micro-should';
|
||||||
import { numberToBytesLE } from '../lib/esm/abstract/utils.js';
|
import { bytesToNumberLE, numberToBytesLE } from '../esm/abstract/utils.js';
|
||||||
import { default as x25519vectors } from './wycheproof/x25519_test.json' assert { type: 'json' };
|
import { default as x25519vectors } from './wycheproof/x25519_test.json' assert { type: 'json' };
|
||||||
import { ed25519ctx, ed25519ph, RistrettoPoint, x25519 } from '../lib/esm/ed25519.js';
|
import { ed25519ctx, ed25519ph, RistrettoPoint, x25519 } from '../esm/ed25519.js';
|
||||||
|
|
||||||
// const ed = ed25519;
|
// const ed = ed25519;
|
||||||
const hex = bytesToHex;
|
const hex = bytesToHex;
|
||||||
@@ -97,7 +97,7 @@ should('X25519 base point', () => {
|
|||||||
const { y } = ed25519ph.ExtendedPoint.BASE;
|
const { y } = ed25519ph.ExtendedPoint.BASE;
|
||||||
const { Fp } = ed25519ph.CURVE;
|
const { Fp } = ed25519ph.CURVE;
|
||||||
const u = Fp.create((y + 1n) * Fp.inv(1n - y));
|
const u = Fp.create((y + 1n) * Fp.inv(1n - y));
|
||||||
deepStrictEqual(hex(numberToBytesLE(u, 32)), x25519.Gu);
|
deepStrictEqual(numberToBytesLE(u, 32), x25519.GuBytes);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('RFC7748', () => {
|
describe('RFC7748', () => {
|
||||||
@@ -128,7 +128,7 @@ describe('RFC7748', () => {
|
|||||||
for (let i = 0; i < rfc7748Iter.length; i++) {
|
for (let i = 0; i < rfc7748Iter.length; i++) {
|
||||||
const { scalar, iters } = rfc7748Iter[i];
|
const { scalar, iters } = rfc7748Iter[i];
|
||||||
should(`scalarMult iteration (${i})`, () => {
|
should(`scalarMult iteration (${i})`, () => {
|
||||||
let k = x25519.Gu;
|
let k = x25519.GuBytes;
|
||||||
for (let i = 0, u = k; i < iters; i++) [k, u] = [x25519.scalarMult(k, u), k];
|
for (let i = 0, u = k; i < iters; i++) [k, u] = [x25519.scalarMult(k, u), k];
|
||||||
deepStrictEqual(hex(k), scalar);
|
deepStrictEqual(hex(k), scalar);
|
||||||
});
|
});
|
||||||
@@ -281,10 +281,23 @@ describe('ristretto255', () => {
|
|||||||
deepStrictEqual(point.toHex(), encodedHashToPoints[i]);
|
deepStrictEqual(point.toHex(), encodedHashToPoints[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
should('have proper equality testing', () => {
|
||||||
|
const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
|
||||||
|
const bytes255ToNumberLE = (bytes) =>
|
||||||
|
ed25519ctx.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
|
||||||
|
|
||||||
|
const priv = new Uint8Array([
|
||||||
|
198, 101, 65, 165, 93, 120, 37, 238, 16, 133, 10, 35, 253, 243, 161, 246, 229, 135, 12, 137,
|
||||||
|
202, 114, 222, 139, 146, 123, 4, 125, 152, 173, 1, 7,
|
||||||
|
]);
|
||||||
|
const pub = RistrettoPoint.BASE.multiply(bytes255ToNumberLE(priv));
|
||||||
|
deepStrictEqual(pub.equals(RistrettoPoint.ZERO), false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ESM is broken.
|
// ESM is broken.
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
|
import { assert } from 'console';
|
||||||
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
||||||
should.run();
|
should.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { ed25519, ED25519_TORSION_SUBGROUP } from '../lib/esm/ed25519.js';
|
export { ed25519, ED25519_TORSION_SUBGROUP } from '../esm/ed25519.js';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
import { describe, should } from 'micro-should';
|
import { describe, should } from 'micro-should';
|
||||||
import * as fc from 'fast-check';
|
import * as fc from 'fast-check';
|
||||||
import { ed448, ed448ph, x448 } from '../lib/esm/ed448.js';
|
import { ed448, ed448ph, x448 } from '../esm/ed448.js';
|
||||||
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
|
import { hexToBytes, bytesToHex, randomBytes } from '@noble/hashes/utils';
|
||||||
import { numberToBytesLE } from '../lib/esm/abstract/utils.js';
|
import { numberToBytesLE } from '../esm/abstract/utils.js';
|
||||||
import { default as ed448vectors } from './wycheproof/ed448_test.json' assert { type: 'json' };
|
import { default as ed448vectors } from './wycheproof/ed448_test.json' assert { type: 'json' };
|
||||||
import { default as x448vectors } from './wycheproof/x448_test.json' assert { type: 'json' };
|
import { default as x448vectors } from './wycheproof/x448_test.json' assert { type: 'json' };
|
||||||
|
|
||||||
@@ -509,7 +509,7 @@ describe('ed448', () => {
|
|||||||
for (let i = 0; i < rfc7748Iter.length; i++) {
|
for (let i = 0; i < rfc7748Iter.length; i++) {
|
||||||
const { scalar, iters } = rfc7748Iter[i];
|
const { scalar, iters } = rfc7748Iter[i];
|
||||||
should(`RFC7748: scalarMult iteration (${i})`, () => {
|
should(`RFC7748: scalarMult iteration (${i})`, () => {
|
||||||
let k = x448.Gu;
|
let k = x448.GuBytes;
|
||||||
for (let i = 0, u = k; i < iters; i++) [k, u] = [x448.scalarMult(k, u), k];
|
for (let i = 0, u = k; i < iters; i++) [k, u] = [x448.scalarMult(k, u), k];
|
||||||
deepStrictEqual(hex(k), scalar);
|
deepStrictEqual(hex(k), scalar);
|
||||||
});
|
});
|
||||||
@@ -664,7 +664,7 @@ describe('ed448', () => {
|
|||||||
// const invX = Fp.invert(x * x); // x²
|
// const invX = Fp.invert(x * x); // x²
|
||||||
const u = Fp.div(Fp.create(y * y), Fp.create(x * x)); // (y²/x²)
|
const u = Fp.div(Fp.create(y * y), Fp.create(x * x)); // (y²/x²)
|
||||||
// const u = Fp.create(y * y * invX);
|
// const u = Fp.create(y * y * invX);
|
||||||
deepStrictEqual(hex(numberToBytesLE(u, 56)), x448.Gu);
|
deepStrictEqual(numberToBytesLE(u, 56), x448.GuBytes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,18 +5,15 @@ import { bytesToHex } from '@noble/hashes/utils';
|
|||||||
import { sha256 } from '@noble/hashes/sha256';
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
import { sha512 } from '@noble/hashes/sha512';
|
import { sha512 } from '@noble/hashes/sha512';
|
||||||
import { shake128, shake256 } from '@noble/hashes/sha3';
|
import { shake128, shake256 } from '@noble/hashes/sha3';
|
||||||
import * as secp256r1 from '../lib/esm/p256.js';
|
import * as secp256r1 from '../esm/p256.js';
|
||||||
import * as secp384r1 from '../lib/esm/p384.js';
|
import * as secp384r1 from '../esm/p384.js';
|
||||||
import * as secp521r1 from '../lib/esm/p521.js';
|
import * as secp521r1 from '../esm/p521.js';
|
||||||
import * as ed25519 from '../lib/esm/ed25519.js';
|
import * as ed25519 from '../esm/ed25519.js';
|
||||||
import * as ed448 from '../lib/esm/ed448.js';
|
import * as ed448 from '../esm/ed448.js';
|
||||||
import * as secp256k1 from '../lib/esm/secp256k1.js';
|
import * as secp256k1 from '../esm/secp256k1.js';
|
||||||
import { bls12_381 } from '../lib/esm/bls12-381.js';
|
import { bls12_381 } from '../esm/bls12-381.js';
|
||||||
import {
|
import { expand_message_xmd, expand_message_xof } from '../esm/abstract/hash-to-curve.js';
|
||||||
stringToBytes,
|
import { utf8ToBytes } from '../esm/abstract/utils.js';
|
||||||
expand_message_xmd,
|
|
||||||
expand_message_xof,
|
|
||||||
} from '../lib/esm/abstract/hash-to-curve.js';
|
|
||||||
// XMD
|
// XMD
|
||||||
import { default as xmd_sha256_38 } from './hash-to-curve/expand_message_xmd_SHA256_38.json' assert { type: 'json' };
|
import { default as xmd_sha256_38 } from './hash-to-curve/expand_message_xmd_SHA256_38.json' assert { type: 'json' };
|
||||||
import { default as xmd_sha256_256 } from './hash-to-curve/expand_message_xmd_SHA256_256.json' assert { type: 'json' };
|
import { default as xmd_sha256_256 } from './hash-to-curve/expand_message_xmd_SHA256_256.json' assert { type: 'json' };
|
||||||
@@ -56,9 +53,9 @@ function testExpandXMD(hash, vectors) {
|
|||||||
const t = vectors.tests[i];
|
const t = vectors.tests[i];
|
||||||
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
should(`${vectors.hash}/${vectors.DST.length}/${i}`, () => {
|
||||||
const p = expand_message_xmd(
|
const p = expand_message_xmd(
|
||||||
stringToBytes(t.msg),
|
utf8ToBytes(t.msg),
|
||||||
stringToBytes(vectors.DST),
|
utf8ToBytes(vectors.DST),
|
||||||
t.len_in_bytes,
|
Number.parseInt(t.len_in_bytes),
|
||||||
hash
|
hash
|
||||||
);
|
);
|
||||||
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
deepStrictEqual(bytesToHex(p), t.uniform_bytes);
|
||||||
@@ -79,9 +76,9 @@ function testExpandXOF(hash, vectors) {
|
|||||||
const t = vectors.tests[i];
|
const t = vectors.tests[i];
|
||||||
should(`${i}`, () => {
|
should(`${i}`, () => {
|
||||||
const p = expand_message_xof(
|
const p = expand_message_xof(
|
||||||
stringToBytes(t.msg),
|
utf8ToBytes(t.msg),
|
||||||
stringToBytes(vectors.DST),
|
utf8ToBytes(vectors.DST),
|
||||||
+t.len_in_bytes,
|
Number.parseInt(t.len_in_bytes),
|
||||||
vectors.k,
|
vectors.k,
|
||||||
hash
|
hash
|
||||||
);
|
);
|
||||||
@@ -112,7 +109,7 @@ function testCurve(curve, ro, nu) {
|
|||||||
const t = ro.vectors[i];
|
const t = ro.vectors[i];
|
||||||
should(`(${i})`, () => {
|
should(`(${i})`, () => {
|
||||||
const p = curve
|
const p = curve
|
||||||
.hashToCurve(stringToBytes(t.msg), {
|
.hashToCurve(utf8ToBytes(t.msg), {
|
||||||
DST: ro.dst,
|
DST: ro.dst,
|
||||||
})
|
})
|
||||||
.toAffine();
|
.toAffine();
|
||||||
@@ -126,7 +123,7 @@ function testCurve(curve, ro, nu) {
|
|||||||
const t = nu.vectors[i];
|
const t = nu.vectors[i];
|
||||||
should(`(${i})`, () => {
|
should(`(${i})`, () => {
|
||||||
const p = curve
|
const p = curve
|
||||||
.encodeToCurve(stringToBytes(t.msg), {
|
.encodeToCurve(utf8ToBytes(t.msg), {
|
||||||
DST: nu.dst,
|
DST: nu.dst,
|
||||||
})
|
})
|
||||||
.toAffine();
|
.toAffine();
|
||||||
@@ -140,8 +137,8 @@ function testCurve(curve, ro, nu) {
|
|||||||
testCurve(secp256r1, p256_ro, p256_nu);
|
testCurve(secp256r1, p256_ro, p256_nu);
|
||||||
testCurve(secp384r1, p384_ro, p384_nu);
|
testCurve(secp384r1, p384_ro, p384_nu);
|
||||||
testCurve(secp521r1, p521_ro, p521_nu);
|
testCurve(secp521r1, p521_ro, p521_nu);
|
||||||
testCurve(bls12_381.hashToCurve.G1, g1_ro, g1_nu);
|
testCurve(bls12_381.G1, g1_ro, g1_nu);
|
||||||
testCurve(bls12_381.hashToCurve.G2, g2_ro, g2_nu);
|
testCurve(bls12_381.G2, g2_ro, g2_nu);
|
||||||
testCurve(secp256k1, secp256k1_ro, secp256k1_nu);
|
testCurve(secp256k1, secp256k1_ro, secp256k1_nu);
|
||||||
testCurve(ed25519, ed25519_ro, ed25519_nu);
|
testCurve(ed25519, ed25519_ro, ed25519_nu);
|
||||||
testCurve(ed448, ed448_ro, ed448_nu);
|
testCurve(ed448, ed448_ro, ed448_nu);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import './ed448.test.js';
|
|||||||
import './ed25519.test.js';
|
import './ed25519.test.js';
|
||||||
import './secp256k1.test.js';
|
import './secp256k1.test.js';
|
||||||
import './secp256k1-schnorr.test.js';
|
import './secp256k1-schnorr.test.js';
|
||||||
import './stark/index.test.js';
|
|
||||||
import './jubjub.test.js';
|
import './jubjub.test.js';
|
||||||
import './bls12-381.test.js';
|
import './bls12-381.test.js';
|
||||||
import './hash-to-curve.test.js';
|
import './hash-to-curve.test.js';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { jubjub, findGroupHash } from '../lib/esm/jubjub.js';
|
import { jubjub, findGroupHash } from '../esm/jubjub.js';
|
||||||
import { describe, should } from 'micro-should';
|
import { describe, should } from 'micro-should';
|
||||||
import { deepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
const Point = jubjub.ExtendedPoint;
|
const Point = jubjub.ExtendedPoint;
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual } from 'assert';
|
||||||
import { describe, should } from 'micro-should';
|
import { describe, should } from 'micro-should';
|
||||||
import { secp192r1, P192 } from '../lib/esm/p192.js';
|
import { secp192r1, secp224r1, P192, P224 } from './_more-curves.helpers.js';
|
||||||
import { secp224r1, P224 } from '../lib/esm/p224.js';
|
import { secp256r1, P256 } from '../esm/p256.js';
|
||||||
import { secp256r1, P256 } from '../lib/esm/p256.js';
|
import { secp384r1, P384 } from '../esm/p384.js';
|
||||||
import { secp384r1, P384 } from '../lib/esm/p384.js';
|
import { secp521r1, P521 } from '../esm/p521.js';
|
||||||
import { secp521r1, P521 } from '../lib/esm/p521.js';
|
import { secp256k1 } from '../esm/secp256k1.js';
|
||||||
import { secp256k1 } from '../lib/esm/secp256k1.js';
|
import { hexToBytes, bytesToHex } from '../esm/abstract/utils.js';
|
||||||
import { hexToBytes, bytesToHex } from '../lib/esm/abstract/utils.js';
|
|
||||||
import { default as ecdsa } from './wycheproof/ecdsa_test.json' assert { type: 'json' };
|
import { default as ecdsa } from './wycheproof/ecdsa_test.json' assert { type: 'json' };
|
||||||
import { default as ecdh } from './wycheproof/ecdh_test.json' assert { type: 'json' };
|
import { default as ecdh } from './wycheproof/ecdh_test.json' assert { type: 'json' };
|
||||||
import { default as rfc6979 } from './fixtures/rfc6979.json' assert { type: 'json' };
|
import { default as rfc6979 } from './fixtures/rfc6979.json' assert { type: 'json' };
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
import { deepStrictEqual, throws } from 'assert';
|
||||||
import { should, describe } from 'micro-should';
|
import { should, describe } from 'micro-should';
|
||||||
import * as poseidon from '../lib/esm/abstract/poseidon.js';
|
import * as poseidon from '../esm/abstract/poseidon.js';
|
||||||
import * as stark from '../lib/esm/stark.js';
|
import * as stark from './_poseidon.helpers.js';
|
||||||
import * as mod from '../lib/esm/abstract/modular.js';
|
import * as mod from '../esm/abstract/modular.js';
|
||||||
import { default as pvectors } from './vectors/poseidon.json' assert { type: 'json' };
|
import { default as pvectors } from './vectors/poseidon.json' assert { type: 'json' };
|
||||||
const { st1, st2, st3, st4 } = pvectors;
|
const { st1, st2, st3, st4 } = pvectors;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { deepStrictEqual, throws } from 'assert';
|
|||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { should, describe } from 'micro-should';
|
import { should, describe } from 'micro-should';
|
||||||
import { bytesToHex as hex } from '@noble/hashes/utils';
|
import { bytesToHex as hex } from '@noble/hashes/utils';
|
||||||
import { schnorr } from '../lib/esm/secp256k1.js';
|
import { schnorr } from '../esm/secp256k1.js';
|
||||||
const schCsv = readFileSync('./test/vectors/schnorr.csv', 'utf-8');
|
const schCsv = readFileSync('./test/vectors/schnorr.csv', 'utf-8');
|
||||||
|
|
||||||
describe('schnorr.sign()', () => {
|
describe('schnorr.sign()', () => {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export { secp256k1 as secp } from '../lib/esm/secp256k1.js';
|
export { secp256k1 as secp } from '../esm/secp256k1.js';
|
||||||
import { secp256k1 as _secp } from '../lib/esm/secp256k1.js';
|
import { secp256k1 as _secp } from '../esm/secp256k1.js';
|
||||||
export { bytesToNumberBE, numberToBytesBE } from '../lib/esm/abstract/utils.js';
|
export { bytesToNumberBE, numberToBytesBE } from '../esm/abstract/utils.js';
|
||||||
export { mod } from '../lib/esm/abstract/modular.js';
|
export { mod } from '../esm/abstract/modular.js';
|
||||||
export const sigFromDER = (der) => {
|
export const sigFromDER = (der) => {
|
||||||
return _secp.Signature.fromDER(der);
|
return _secp.Signature.fromDER(der);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,201 +0,0 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
|
||||||
import { describe, should } from 'micro-should';
|
|
||||||
import * as starknet from '../../lib/esm/stark.js';
|
|
||||||
import { default as issue2 } from './fixtures/issue2.json' assert { type: 'json' };
|
|
||||||
import * as bip32 from '@scure/bip32';
|
|
||||||
import * as bip39 from '@scure/bip39';
|
|
||||||
|
|
||||||
describe('starknet basic', () => {
|
|
||||||
should('Basic elliptic sanity check', () => {
|
|
||||||
const g1 = starknet.ProjectivePoint.BASE;
|
|
||||||
deepStrictEqual(
|
|
||||||
g1.toAffine().x.toString(16),
|
|
||||||
'1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
g1.toAffine().y.toString(16),
|
|
||||||
'5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f'
|
|
||||||
);
|
|
||||||
const g2 = g1.double();
|
|
||||||
deepStrictEqual(
|
|
||||||
g2.toAffine().x.toString(16),
|
|
||||||
'759ca09377679ecd535a81e83039658bf40959283187c654c5416f439403cf5'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
g2.toAffine().y.toString(16),
|
|
||||||
'6f524a3400e7708d5c01a28598ad272e7455aa88778b19f93b562d7a9646c41'
|
|
||||||
);
|
|
||||||
const g3 = g2.add(g1);
|
|
||||||
deepStrictEqual(
|
|
||||||
g3.toAffine().x.toString(16),
|
|
||||||
'411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
g3.toAffine().y.toString(16),
|
|
||||||
'7e1b3ebac08924d2c26f409549191fcf94f3bf6f301ed3553e22dfb802f0686'
|
|
||||||
);
|
|
||||||
const g32 = g1.multiply(3n);
|
|
||||||
deepStrictEqual(
|
|
||||||
g32.toAffine().x.toString(16),
|
|
||||||
'411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
g32.toAffine().y.toString(16),
|
|
||||||
'7e1b3ebac08924d2c26f409549191fcf94f3bf6f301ed3553e22dfb802f0686'
|
|
||||||
);
|
|
||||||
const minus1 = g1.multiply(starknet.CURVE.n - 1n);
|
|
||||||
deepStrictEqual(
|
|
||||||
minus1.toAffine().x.toString(16),
|
|
||||||
'1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
minus1.toAffine().y.toString(16),
|
|
||||||
'7a997f9f55b68e04841b7fe20b9139d21ac132ee541bc5cd78cfff3c91723e2'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Pedersen', () => {
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.pedersen(2, 3),
|
|
||||||
'0x5774fa77b3d843ae9167abd61cf80365a9b2b02218fc2f628494b5bdc9b33b8'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.pedersen(1, 2),
|
|
||||||
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.pedersen(3, 4),
|
|
||||||
'0x262697b88544f733e5c6907c3e1763131e9f14c51ee7951258abbfb29415fbf'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Hash chain', () => {
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.hashChain([1, 2, 3]),
|
|
||||||
'0x5d9d62d4040b977c3f8d2389d494e4e89a96a8b45c44b1368f1cc6ec5418915'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Pedersen hash edgecases', () => {
|
|
||||||
// >>> pedersen_hash(0,0)
|
|
||||||
const zero = '0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804';
|
|
||||||
deepStrictEqual(starknet.pedersen(0, 0), zero);
|
|
||||||
deepStrictEqual(starknet.pedersen(0n, 0n), zero);
|
|
||||||
deepStrictEqual(starknet.pedersen('0', '0'), zero);
|
|
||||||
deepStrictEqual(starknet.pedersen('0x0', '0x0'), zero);
|
|
||||||
// >>> pedersen_hash(3618502788666131213697322783095070105623107215331596699973092056135872020475,3618502788666131213697322783095070105623107215331596699973092056135872020475)
|
|
||||||
// 3226051580231087455100099637526672350308978851161639703631919449959447036451
|
|
||||||
const big = 3618502788666131213697322783095070105623107215331596699973092056135872020475n;
|
|
||||||
const bigExp = '0x721e167a36655994e88efa865e2ed8a0488d36db4d988fec043cda755728223';
|
|
||||||
deepStrictEqual(starknet.pedersen(big, big), bigExp);
|
|
||||||
// >= FIELD
|
|
||||||
const big2 = 36185027886661312136973227830950701056231072153315966999730920561358720204751n;
|
|
||||||
throws(() => starknet.pedersen(big2, big2), 'big2');
|
|
||||||
|
|
||||||
// FIELD -1
|
|
||||||
const big3 = 3618502788666131213697322783095070105623107215331596699973092056135872020480n;
|
|
||||||
const big3exp = '0x7258fccaf3371fad51b117471d9d888a1786c5694c3e6099160477b593a576e';
|
|
||||||
deepStrictEqual(starknet.pedersen(big3, big3), big3exp, 'big3');
|
|
||||||
// FIELD
|
|
||||||
const big4 = 3618502788666131213697322783095070105623107215331596699973092056135872020481n;
|
|
||||||
throws(() => starknet.pedersen(big4, big4), 'big4');
|
|
||||||
throws(() => starknet.pedersen(-1, -1), 'neg');
|
|
||||||
throws(() => starknet.pedersen(false, false), 'false');
|
|
||||||
throws(() => starknet.pedersen(true, true), 'true');
|
|
||||||
throws(() => starknet.pedersen(10.1, 10.1), 'float');
|
|
||||||
});
|
|
||||||
|
|
||||||
should('hashChain edgecases', () => {
|
|
||||||
deepStrictEqual(starknet.hashChain([32312321312321312312312321n]), '0x1aba6672c014b4838cc201');
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.hashChain([1n, 2n]),
|
|
||||||
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.hashChain([1, 2]),
|
|
||||||
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
|
|
||||||
);
|
|
||||||
throws(() => starknet.hashChain([]));
|
|
||||||
throws(() => starknet.hashChain('123'));
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.hashChain([1, 2]),
|
|
||||||
'0x5bb9440e27889a364bcb678b1f679ecd1347acdedcbf36e83494f857cc58026'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Pedersen hash, issue #2', () => {
|
|
||||||
// Verified with starnet.js
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.computeHashOnElements(issue2),
|
|
||||||
'0x22064462ea33a6ce5272a295e0f551c5da3834f80d8444e7a4df68190b1bc42'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.computeHashOnElements([]),
|
|
||||||
'0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.computeHashOnElements([1]),
|
|
||||||
'0x78d74f61aeaa8286418fd34b3a12a610445eba11d00ecc82ecac2542d55f7a4'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
should('Seed derivation (example)', () => {
|
|
||||||
const layer = 'starkex';
|
|
||||||
const application = 'starkdeployement';
|
|
||||||
const mnemonic =
|
|
||||||
'range mountain blast problem vibrant void vivid doctor cluster enough melody ' +
|
|
||||||
'salt layer language laptop boat major space monkey unit glimpse pause change vibrant';
|
|
||||||
const ethAddress = '0xa4864d977b944315389d1765ffa7e66F74ee8cd7';
|
|
||||||
const hdKey = bip32.HDKey.fromMasterSeed(bip39.mnemonicToSeedSync(mnemonic)).derive(
|
|
||||||
starknet.getAccountPath(layer, application, ethAddress, 0)
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.grindKey(hdKey.privateKey),
|
|
||||||
'6cf0a8bf113352eb863157a45c5e5567abb34f8d32cddafd2c22aa803f4892c'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Compressed keys', () => {
|
|
||||||
const G = starknet.ProjectivePoint.BASE;
|
|
||||||
const half = starknet.CURVE.n / 2n;
|
|
||||||
const last = starknet.CURVE.n;
|
|
||||||
const vectors = [
|
|
||||||
1n,
|
|
||||||
2n,
|
|
||||||
3n,
|
|
||||||
4n,
|
|
||||||
5n,
|
|
||||||
half - 5n,
|
|
||||||
half - 4n,
|
|
||||||
half - 3n,
|
|
||||||
half - 2n,
|
|
||||||
half - 1n,
|
|
||||||
half,
|
|
||||||
half + 1n,
|
|
||||||
half + 2n,
|
|
||||||
half + 3n,
|
|
||||||
half + 4n,
|
|
||||||
half + 5n,
|
|
||||||
last - 5n,
|
|
||||||
last - 4n,
|
|
||||||
last - 3n,
|
|
||||||
last - 2n,
|
|
||||||
last - 1n,
|
|
||||||
].map((i) => G.multiply(i));
|
|
||||||
const fixPoint = (pt) => pt.toAffine();
|
|
||||||
for (const v of vectors) {
|
|
||||||
const uncompressed = v.toHex();
|
|
||||||
const compressed = v.toHex(true);
|
|
||||||
const exp = fixPoint(v);
|
|
||||||
deepStrictEqual(fixPoint(starknet.ProjectivePoint.fromHex(uncompressed)), exp);
|
|
||||||
deepStrictEqual(fixPoint(starknet.ProjectivePoint.fromHex(compressed)), exp);
|
|
||||||
deepStrictEqual(starknet.ProjectivePoint.fromHex(compressed).toHex(), uncompressed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// ESM is broken.
|
|
||||||
import url from 'url';
|
|
||||||
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
|
||||||
should.run();
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import * as microStark from '../../../lib/esm/stark.js';
|
|
||||||
import * as starkwareCrypto from '@starkware-industries/starkware-crypto-utils';
|
|
||||||
import * as bench from 'micro-bmark';
|
|
||||||
const { run, mark } = bench; // or bench.mark
|
|
||||||
|
|
||||||
const privateKey = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
|
|
||||||
const msgHash = 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47';
|
|
||||||
const keyPair = starkwareCrypto.default.ec.keyFromPrivate(privateKey, 'hex');
|
|
||||||
const publicKeyStark = starkwareCrypto.default.ec.keyFromPublic(
|
|
||||||
keyPair.getPublic(true, 'hex'),
|
|
||||||
'hex'
|
|
||||||
);
|
|
||||||
const publicKeyMicro = microStark.getPublicKey(privateKey);
|
|
||||||
|
|
||||||
const FNS = {
|
|
||||||
pedersenHash: {
|
|
||||||
samples: 250,
|
|
||||||
starkware: () =>
|
|
||||||
starkwareCrypto.default.pedersen([
|
|
||||||
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
|
|
||||||
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a',
|
|
||||||
]),
|
|
||||||
'micro-starknet': () =>
|
|
||||||
microStark.pedersen(
|
|
||||||
'3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
|
|
||||||
'208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a'
|
|
||||||
),
|
|
||||||
},
|
|
||||||
signVerify: {
|
|
||||||
samples: 500,
|
|
||||||
starkware: () =>
|
|
||||||
starkwareCrypto.default.verify(
|
|
||||||
publicKeyStark,
|
|
||||||
msgHash,
|
|
||||||
starkwareCrypto.default.sign(keyPair, msgHash)
|
|
||||||
),
|
|
||||||
'micro-starknet': () =>
|
|
||||||
microStark.verify(microStark.sign(msgHash, privateKey), msgHash, publicKeyMicro),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const main = () =>
|
|
||||||
run(async () => {
|
|
||||||
for (let [k, libs] of Object.entries(FNS)) {
|
|
||||||
console.log(`==== ${k} ====`);
|
|
||||||
for (const [lib, fn] of Object.entries(libs)) {
|
|
||||||
if (lib === 'samples') continue;
|
|
||||||
let title = `${k} (${lib})`;
|
|
||||||
await mark(title, libs.samples, () => fn());
|
|
||||||
}
|
|
||||||
console.log();
|
|
||||||
}
|
|
||||||
// Log current RAM
|
|
||||||
bench.logMem();
|
|
||||||
});
|
|
||||||
|
|
||||||
main();
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "benchmark",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "benchmarks",
|
|
||||||
"main": "index.js",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"bench": "node index.js"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"@starkware-industries/starkware-crypto-utils": "^0.0.2",
|
|
||||||
"micro-bmark": "0.2.0",
|
|
||||||
"micro-should": "0.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"0x1": "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca",
|
|
||||||
"0x2": "0x759ca09377679ecd535a81e83039658bf40959283187c654c5416f439403cf5",
|
|
||||||
"0x3": "0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20",
|
|
||||||
"0x4": "0xa7da05a4d664859ccd6e567b935cdfbfe3018c7771cb980892ef38878ae9bc",
|
|
||||||
"0x5": "0x788435d61046d3eec54d77d25bd194525f4fa26ebe6575536bc6f656656b74c",
|
|
||||||
"0x6": "0x1efc3d7c9649900fcbd03f578a8248d095bc4b6a13b3c25f9886ef971ff96fa",
|
|
||||||
"0x7": "0x743829e0a179f8afe223fc8112dfc8d024ab6b235fd42283c4f5970259ce7b7",
|
|
||||||
"0x8": "0x6eeee2b0c71d681692559735e08a2c3ba04e7347c0c18d4d49b83bb89771591",
|
|
||||||
"0x9": "0x216b4f076ff47e03a05032d1c6ee17933d8de8b2b4c43eb5ad5a7e1b25d3849",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000000": "0x5c79074e7f7b834c12c81a9bb0d46691a5e7517767a849d9d98cb84e2176ed2",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000001": "0x1c4f24e3bd16db0e2457bc005a9d61965105a535554c6b338871e34cb8e2d3a",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000002": "0xdfbb89b39288a9ddacf3942b4481b04d4fa2f8ed3c424757981cc6357f27ac",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000003": "0x41bef28265fd750b102f4f2d1e0231de7f4a33900a214f191a63d4fec4e72f4",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000004": "0x24de66eb164797d4b414e81ded0cfa1a592ef0a9363ebbcb440d4d03cb18af1",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000005": "0x5efb18c3bc9b69003746acc85fb6ee0cfbdc6adfb982f089cc63e1e5495daad",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000006": "0x10dc71f00918a8ebfe4085c834d41dd22b251b9f81eef8b9a4fab77e7e1afe9",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000007": "0x4267ebfd379b1c8caae73febc5920b0c95bd6f9f3536f47c5ddad1259c332ff",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000008": "0x6da515118c8e01fd5b2e96b814ee95bad7d60be4d2ba6b47e0d283f579d9671",
|
|
||||||
"0x800000000000000000000000000000000000000000000000000000000000009": "0x7a5b4797f4e56ed1473876bc2693fbe3f2fef7e050717cbae924ff23d426052",
|
|
||||||
"0x2e9c99d8382fa004dcbbee720aef8a97002de0e991f6a8344e6dc636a71b59e": "0x1ff6803ae740e7e596504ac5c6afbea472e53679361e214f12be0155b13e25d",
|
|
||||||
"0x8620458785138df8722214e073a91b8f55076ea78197cf41007692dd27fd90": "0x5967da40b90d7ca1e36dc4024381d7d4b403c6ac1a0ab358b0743984934a805",
|
|
||||||
"0x1b920e7dfb49ba5ada673882af5342e7448d3e9335e0ac37feb6280cd7289ce": "0x78c7ab46333968fbde3201cf512c1eeb5529360259072c459a158dee4449b57",
|
|
||||||
"0x704170dbfd5dc63caef69d2ce6dfc2b2dbb2af6e75851242bbe79fb6e62a118": "0x534bd8d6ebe4bb2f6992e2d7c19ef3146247e10c2849f357e44eddd283b2af6",
|
|
||||||
"0x4b58bf4228f39550eca59b5c96a0cb606036cc9495eef9a546f24f01b1b7829": "0x1097a8c5a46d94596f1c8e70ca66941f2bb11e3c8d4fd58fdc4589f09965be8",
|
|
||||||
"0x2e93226c90fb7a2381a24e940a94b98433e3553dcbf745d3f54d62963c75604": "0x369f0e8c8e984f244290267393a004dba435a4df091767ad5063fece7b1884c",
|
|
||||||
"0x4615f94598cd756ad1a551d7e57fd725916adfd0054eb773ceb482eef87d0b2": "0x1ee5b8d612102a2408cde59ce52a6498d2e38fe8789bb26d400dea310684ec9",
|
|
||||||
"0x6ade54b7debd7ca1d4e8e932f9545f8fa4024d73be1efcc86df86367fc333f8": "0x37de3bf52412b2fb9b0030d232ca9dd921cd8f71fd67975cdc62546826e121",
|
|
||||||
"0x618e7467dd24c2a3449c4df640439c12cdd0f8ea779afcee6e252b2cf494354": "0x71c2b578c432f2d305d3808bb645ecc46dd670cb43d4f4a076f75ccbff74fbc",
|
|
||||||
"0x7eae185e1f41ec76d214d763f0592f194933622a9dd5f3d52d0209f71619c1a": "0x2b0160052e70176e5b0ff2a6eff90896ae07b732fc27219e36e077735abd57e",
|
|
||||||
"0x178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F": "0x1895a6a77ae14e7987b9cb51329a5adfb17bd8e7c638f92d6892d76e51cebcf"
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
{
|
|
||||||
"private_key": "0x3c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc",
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"hash": "0x1",
|
|
||||||
"r": "3162358736122783857144396205516927012128897537504463716197279730251407200037",
|
|
||||||
"s": "1447067116407676619871126378936374427636662490882969509559888874644844560850"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "0x11",
|
|
||||||
"r": "2282960348362869237018441985726545922711140064809058182483721438101695251648",
|
|
||||||
"s": "2905868291002627709651322791912000820756370440695830310841564989426104902684"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0x223",
|
|
||||||
"r": "2851492577225522862152785068304516872062840835882746625971400995051610132955",
|
|
||||||
"s": "2227464623243182122770469099770977514100002325017609907274766387592987135410"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0x9999",
|
|
||||||
"r": "3551214266795401081823453828727326248401688527835302880992409448142527576296",
|
|
||||||
"s": "2580950807716503852408066180369610390914312729170066679103651110985466032285"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0x387e76d1667c4454bfb835144120583af836f8e32a516765497d23eabe16b3f",
|
|
||||||
"r": "3518448914047769356425227827389998721396724764083236823647519654917215164512",
|
|
||||||
"s": "3042321032945513635364267149196358883053166552342928199041742035443537684462"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0x3a7e76d1697c4455bfb835144120283af236f8e32a516765497d23eabe16b2",
|
|
||||||
"r": "2261926635950780594216378185339927576862772034098248230433352748057295357217",
|
|
||||||
"s": "2708700003762962638306717009307430364534544393269844487939098184375356178572"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0xfa5f0cd1ebff93c9e6474379a213ba111f9e42f2f1cb361b0327e0737203",
|
|
||||||
"r": "3016953906936760149710218073693613509330129567629289734816320774638425763370",
|
|
||||||
"s": "306146275372136078470081798635201810092238376869367156373203048583896337506"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0x4c1e9550e66958296d11b60f8e8e7f7ae99dd0cfa6bd5fa652c1a6c87d4e2cc",
|
|
||||||
"r": "3562728603055564208884290243634917206833465920158600288670177317979301056463",
|
|
||||||
"s": "1958799632261808501999574190111106370256896588537275453140683641951899459876"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"hash": "0x6362b40c218fb4c8a8bd42ca482145e8513b78e00faa0de76a98ba14fc37ae8",
|
|
||||||
"r": "3485557127492692423490706790022678621438670833185864153640824729109010175518",
|
|
||||||
"s": "897592218067946175671768586886915961592526001156186496738437723857225288280"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import './basic.test.js';
|
|
||||||
import './stark.test.js';
|
|
||||||
import './property.test.js';
|
|
||||||
import './poseidon.test.js';
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
|
||||||
import { describe, should } from 'micro-should';
|
|
||||||
import * as starknet from '../../lib/esm/stark.js';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
|
|
||||||
function parseTest(path) {
|
|
||||||
let data = fs.readFileSync(path, 'ascii');
|
|
||||||
// Remove whitespaces
|
|
||||||
data = data.replace(/[ |\t]/g, '');
|
|
||||||
const pattern =
|
|
||||||
'Rate=(\\d+)\n' +
|
|
||||||
'Capacity=(\\d+)\n' +
|
|
||||||
'FullRounds=(\\d+)\n' +
|
|
||||||
'PartialRounds=(\\d+)\n' +
|
|
||||||
'MDS=\\[(.+)\\]\n' +
|
|
||||||
'RoundKeys=\\(?\n?\\[\n?(.+)\n?\\]\n?\\)?';
|
|
||||||
const r = data.match(new RegExp(pattern, 'ms'));
|
|
||||||
|
|
||||||
function parseArray(s) {
|
|
||||||
// Remove new lines
|
|
||||||
s = s.replace(/\n/gms, '');
|
|
||||||
return s.match(/(\[.+?\])/g).map((i) =>
|
|
||||||
i
|
|
||||||
.replace(/^\[(.+)\]$/, '$1')
|
|
||||||
.split(',')
|
|
||||||
.filter((i) => !!i)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const res = {
|
|
||||||
rate: +r[1],
|
|
||||||
capacity: +r[2],
|
|
||||||
roundsFull: +r[3],
|
|
||||||
roundsPartial: +r[4],
|
|
||||||
MDS: parseArray(r[5]).map((i) => i.map((j) => BigInt(j))),
|
|
||||||
roundConstants: parseArray(r[6]).map((i) => i.map((j) => BigInt(j))),
|
|
||||||
};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapPoseidon(parsed) {
|
|
||||||
return starknet.poseidonBasic(
|
|
||||||
{
|
|
||||||
Fp: starknet.Fp251,
|
|
||||||
rate: parsed.rate,
|
|
||||||
capacity: parsed.capacity,
|
|
||||||
roundsFull: parsed.roundsFull,
|
|
||||||
roundsPartial: parsed.roundsPartial,
|
|
||||||
},
|
|
||||||
parsed.MDS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsed = {
|
|
||||||
poseidon3: parseTest('./test/stark/poseidon/poseidon3.txt'),
|
|
||||||
poseidon4: parseTest('./test/stark/poseidon/poseidon4.txt'),
|
|
||||||
poseidon5: parseTest('./test/stark/poseidon/poseidon5.txt'),
|
|
||||||
poseidon9: parseTest('./test/stark/poseidon/poseidon9.txt'),
|
|
||||||
};
|
|
||||||
|
|
||||||
function poseidonTest(name, parsed) {
|
|
||||||
should(`${name}`, () => {
|
|
||||||
const fn = mapPoseidon(parsed);
|
|
||||||
deepStrictEqual(fn.roundConstants, parsed.roundConstants);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('poseidon txt vectors', () => {
|
|
||||||
poseidonTest('poseidon3', parsed.poseidon3);
|
|
||||||
poseidonTest('poseidon4', parsed.poseidon4);
|
|
||||||
poseidonTest('poseidon5', parsed.poseidon5);
|
|
||||||
poseidonTest('poseidon9', parsed.poseidon9);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Poseidon examples', () => {
|
|
||||||
const p3 = mapPoseidon(parsed.poseidon3);
|
|
||||||
deepStrictEqual(p3([0n, 0n, 0n]), [
|
|
||||||
3446325744004048536138401612021367625846492093718951375866996507163446763827n,
|
|
||||||
1590252087433376791875644726012779423683501236913937337746052470473806035332n,
|
|
||||||
867921192302518434283879514999422690776342565400001269945778456016268852423n,
|
|
||||||
]);
|
|
||||||
const p4 = mapPoseidon(parsed.poseidon4);
|
|
||||||
deepStrictEqual(p4([0n, 0n, 0n, 0n]), [
|
|
||||||
535071095200566880914603862188010633478042591441142518549720701573192347548n,
|
|
||||||
3567335813488551850156302853280844225974867890860330236555401145692518003968n,
|
|
||||||
229995103310401763929738317978722680640995513996113588430855556460153357543n,
|
|
||||||
3513983790849716360905369754287999509206472929684378838050290392634812839312n,
|
|
||||||
]);
|
|
||||||
const p5 = mapPoseidon(parsed.poseidon5);
|
|
||||||
deepStrictEqual(p5([0n, 0n, 0n, 0n, 0n]), [
|
|
||||||
2337689130971531876049206831496963607805116499042700598724344149414565980684n,
|
|
||||||
3230969295497815870174763682436655274044379544854667759151474216427142025631n,
|
|
||||||
3297330512217530111610698859408044542971696143761201570393504997742535648562n,
|
|
||||||
2585480844700786541432072704002477919020588246983274666988914431019064343941n,
|
|
||||||
3595308260654382824623573767385493361624474708214823462901432822513585995028n,
|
|
||||||
]);
|
|
||||||
const p9 = mapPoseidon(parsed.poseidon9);
|
|
||||||
deepStrictEqual(p9([0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n]), [
|
|
||||||
1534116856660032929112709488204491699743182428465681149262739677337223235050n,
|
|
||||||
1710856073207389764546990138116985223517553616229641666885337928044617114700n,
|
|
||||||
3165864635055638516987240200217592641540231237468651257819894959934472989427n,
|
|
||||||
1003007637710164252047715558598366312649052908276423203724288341354608811559n,
|
|
||||||
68117303579957054409211824649914588822081700129416361923518488718489651489n,
|
|
||||||
1123395637839379807713801282868237406546107732595903195840754789810160564711n,
|
|
||||||
478590974834311070537087181212389392308746075734019180430422247431982932503n,
|
|
||||||
835322726024358888065061514739954009068852229059154336727219387089732433787n,
|
|
||||||
3129703030204995742174502162918848446737407262178341733578946634564864233056n,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ESM is broken.
|
|
||||||
import url from 'url';
|
|
||||||
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
|
||||||
should.run();
|
|
||||||
}
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# StarkWare's Poseidon Hash
|
|
||||||
|
|
||||||
[Poseidon](https://www.poseidon-hash.info/) is a family of hash functions designed for being very efficient as algebraic circuits.
|
|
||||||
As such, they may be very useful in ZK proving systems such as STARKs and others.
|
|
||||||
|
|
||||||
This repository provides the official parameters of StarkWare's Poseidon hash implementations.
|
|
||||||
|
|
||||||
All the instances are over the prime field:
|
|
||||||
p = 2^251 + 17 * 2^192 + 1 = 3618502788666131213697322783095070105623107215331596699973092056135872020481
|
|
||||||
|
|
||||||
A few examples hash results with the different parameters:
|
|
||||||
|
|
||||||
```
|
|
||||||
Poseidon3([0,0,0]) = [3446325744004048536138401612021367625846492093718951375866996507163446763827,
|
|
||||||
1590252087433376791875644726012779423683501236913937337746052470473806035332,
|
|
||||||
867921192302518434283879514999422690776342565400001269945778456016268852423]
|
|
||||||
Poseidon4([0,0,0,0]) = [535071095200566880914603862188010633478042591441142518549720701573192347548,
|
|
||||||
3567335813488551850156302853280844225974867890860330236555401145692518003968,
|
|
||||||
229995103310401763929738317978722680640995513996113588430855556460153357543,
|
|
||||||
3513983790849716360905369754287999509206472929684378838050290392634812839312]
|
|
||||||
Poseidon5([0,0,0,0,0]) = [2337689130971531876049206831496963607805116499042700598724344149414565980684,
|
|
||||||
3230969295497815870174763682436655274044379544854667759151474216427142025631,
|
|
||||||
3297330512217530111610698859408044542971696143761201570393504997742535648562,
|
|
||||||
2585480844700786541432072704002477919020588246983274666988914431019064343941,
|
|
||||||
3595308260654382824623573767385493361624474708214823462901432822513585995028]
|
|
||||||
Poseidon9([0,0,0,0,0,0,0,0,0]) = [1534116856660032929112709488204491699743182428465681149262739677337223235050,
|
|
||||||
1710856073207389764546990138116985223517553616229641666885337928044617114700,
|
|
||||||
3165864635055638516987240200217592641540231237468651257819894959934472989427,
|
|
||||||
1003007637710164252047715558598366312649052908276423203724288341354608811559,
|
|
||||||
68117303579957054409211824649914588822081700129416361923518488718489651489,
|
|
||||||
1123395637839379807713801282868237406546107732595903195840754789810160564711,
|
|
||||||
478590974834311070537087181212389392308746075734019180430422247431982932503,
|
|
||||||
835322726024358888065061514739954009068852229059154336727219387089732433787,
|
|
||||||
3129703030204995742174502162918848446737407262178341733578946634564864233056]
|
|
||||||
```
|
|
||||||
@@ -1,462 +0,0 @@
|
|||||||
Rate = 2
|
|
||||||
Capacity = 1
|
|
||||||
FullRounds = 8
|
|
||||||
PartialRounds = 83
|
|
||||||
MDS = [[3, 1, 1], [1, -1, 1], [1, 1, -2]]
|
|
||||||
RoundKeys = [
|
|
||||||
[
|
|
||||||
2950795762459345168613727575620414179244544320470208355568817838579231751791,
|
|
||||||
1587446564224215276866294500450702039420286416111469274423465069420553242820,
|
|
||||||
1645965921169490687904413452218868659025437693527479459426157555728339600137,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2782373324549879794752287702905278018819686065818504085638398966973694145741,
|
|
||||||
3409172630025222641379726933524480516420204828329395644967085131392375707302,
|
|
||||||
2379053116496905638239090788901387719228422033660130943198035907032739387135,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2570819397480941104144008784293466051718826502582588529995520356691856497111,
|
|
||||||
3546220846133880637977653625763703334841539452343273304410918449202580719746,
|
|
||||||
2720682389492889709700489490056111332164748138023159726590726667539759963454,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1899653471897224903834726250400246354200311275092866725547887381599836519005,
|
|
||||||
2369443697923857319844855392163763375394720104106200469525915896159690979559,
|
|
||||||
2354174693689535854311272135513626412848402744119855553970180659094265527996,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2404084503073127963385083467393598147276436640877011103379112521338973185443,
|
|
||||||
950320777137731763811524327595514151340412860090489448295239456547370725376,
|
|
||||||
2121140748740143694053732746913428481442990369183417228688865837805149503386,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2372065044800422557577242066480215868569521938346032514014152523102053709709,
|
|
||||||
2618497439310693947058545060953893433487994458443568169824149550389484489896,
|
|
||||||
3518297267402065742048564133910509847197496119850246255805075095266319996916,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
340529752683340505065238931581518232901634742162506851191464448040657139775,
|
|
||||||
1954876811294863748406056845662382214841467408616109501720437541211031966538,
|
|
||||||
813813157354633930267029888722341725864333883175521358739311868164460385261,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
71901595776070443337150458310956362034911936706490730914901986556638720031,
|
|
||||||
2789761472166115462625363403490399263810962093264318361008954888847594113421,
|
|
||||||
2628791615374802560074754031104384456692791616314774034906110098358135152410,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3617032588734559635167557152518265808024917503198278888820567553943986939719,
|
|
||||||
2624012360209966117322788103333497793082705816015202046036057821340914061980,
|
|
||||||
149101987103211771991327927827692640556911620408176100290586418839323044234,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1039927963829140138166373450440320262590862908847727961488297105916489431045,
|
|
||||||
2213946951050724449162431068646025833746639391992751674082854766704900195669,
|
|
||||||
2792724903541814965769131737117981991997031078369482697195201969174353468597,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3212031629728871219804596347439383805499808476303618848198208101593976279441,
|
|
||||||
3343514080098703935339621028041191631325798327656683100151836206557453199613,
|
|
||||||
614054702436541219556958850933730254992710988573177298270089989048553060199,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
148148081026449726283933484730968827750202042869875329032965774667206931170,
|
|
||||||
1158283532103191908366672518396366136968613180867652172211392033571980848414,
|
|
||||||
1032400527342371389481069504520755916075559110755235773196747439146396688513,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
806900704622005851310078578853499250941978435851598088619290797134710613736,
|
|
||||||
462498083559902778091095573017508352472262817904991134671058825705968404510,
|
|
||||||
1003580119810278869589347418043095667699674425582646347949349245557449452503,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
619074932220101074089137133998298830285661916867732916607601635248249357793,
|
|
||||||
2635090520059500019661864086615522409798872905401305311748231832709078452746,
|
|
||||||
978252636251682252755279071140187792306115352460774007308726210405257135181,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1766912167973123409669091967764158892111310474906691336473559256218048677083,
|
|
||||||
1663265127259512472182980890707014969235283233442916350121860684522654120381,
|
|
||||||
3532407621206959585000336211742670185380751515636605428496206887841428074250,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2507023127157093845256722098502856938353143387711652912931112668310034975446,
|
|
||||||
3321152907858462102434883844787153373036767230808678981306827073335525034593,
|
|
||||||
3039253036806065280643845548147711477270022154459620569428286684179698125661,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
103480338868480851881924519768416587261556021758163719199282794248762465380,
|
|
||||||
2394049781357087698434751577708655768465803975478348134669006211289636928495,
|
|
||||||
2660531560345476340796109810821127229446538730404600368347902087220064379579,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3603166934034556203649050570865466556260359798872408576857928196141785055563,
|
|
||||||
1553799760191949768532188139643704561532896296986025007089826672890485412324,
|
|
||||||
2744284717053657689091306578463476341218866418732695211367062598446038965164,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
320745764922149897598257794663594419839885234101078803811049904310835548856,
|
|
||||||
979382242100682161589753881721708883681034024104145498709287731138044566302,
|
|
||||||
1860426855810549882740147175136418997351054138609396651615467358416651354991,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
336173081054369235994909356892506146234495707857220254489443629387613956145,
|
|
||||||
1632470326779699229772327605759783482411227247311431865655466227711078175883,
|
|
||||||
921958250077481394074960433988881176409497663777043304881055317463712938502,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3034358982193370602048539901033542101022185309652879937418114324899281842797,
|
|
||||||
25626282149517463867572353922222474817434101087272320606729439087234878607,
|
|
||||||
3002662261401575565838149305485737102400501329139562227180277188790091853682,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2939684373453383817196521641512509179310654199629514917426341354023324109367,
|
|
||||||
1076484609897998179434851570277297233169621096172424141759873688902355505136,
|
|
||||||
2575095284833160494841112025725243274091830284746697961080467506739203605049,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3565075264617591783581665711620369529657840830498005563542124551465195621851,
|
|
||||||
2197016502533303822395077038351174326125210255869204501838837289716363437993,
|
|
||||||
331415322883530754594261416546036195982886300052707474899691116664327869405,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1935011233711290003793244296594669823169522055520303479680359990463281661839,
|
|
||||||
3495901467168087413996941216661589517270845976538454329511167073314577412322,
|
|
||||||
954195417117133246453562983448451025087661597543338750600301835944144520375,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1271840477709992894995746871435810599280944810893784031132923384456797925777,
|
|
||||||
2565310762274337662754531859505158700827688964841878141121196528015826671847,
|
|
||||||
3365022288251637014588279139038152521653896670895105540140002607272936852513,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1660592021628965529963974299647026602622092163312666588591285654477111176051,
|
|
||||||
970104372286014048279296575474974982288801187216974504035759997141059513421,
|
|
||||||
2617024574317953753849168721871770134225690844968986289121504184985993971227,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
999899815343607746071464113462778273556695659506865124478430189024755832262,
|
|
||||||
2228536129413411161615629030408828764980855956560026807518714080003644769896,
|
|
||||||
2701953891198001564547196795777701119629537795442025393867364730330476403227,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
837078355588159388741598313782044128527494922918203556465116291436461597853,
|
|
||||||
2121749601840466143704862369657561429793951309962582099604848281796392359214,
|
|
||||||
771812260179247428733132708063116523892339056677915387749121983038690154755,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3317336423132806446086732225036532603224267214833263122557471741829060578219,
|
|
||||||
481570067997721834712647566896657604857788523050900222145547508314620762046,
|
|
||||||
242195042559343964206291740270858862066153636168162642380846129622127460192,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2855462178889999218204481481614105202770810647859867354506557827319138379686,
|
|
||||||
3525521107148375040131784770413887305850308357895464453970651672160034885202,
|
|
||||||
1320839531502392535964065058804908871811967681250362364246430459003920305799,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2514191518588387125173345107242226637171897291221681115249521904869763202419,
|
|
||||||
2798335750958827619666318316247381695117827718387653874070218127140615157902,
|
|
||||||
2808467767967035643407948058486565877867906577474361783201337540214875566395,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3551834385992706206273955480294669176699286104229279436819137165202231595747,
|
|
||||||
1219439673853113792340300173186247996249367102884530407862469123523013083971,
|
|
||||||
761519904537984520554247997444508040636526566551719396202550009393012691157,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3355402549169351700500518865338783382387571349497391475317206324155237401353,
|
|
||||||
199541098009731541347317515995192175813554789571447733944970283654592727138,
|
|
||||||
192100490643078165121235261796864975568292640203635147901612231594408079071,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1187019357602953326192019968809486933768550466167033084944727938441427050581,
|
|
||||||
189525349641911362389041124808934468936759383310282010671081989585219065700,
|
|
||||||
2831653363992091308880573627558515686245403755586311978724025292003353336665,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2052859812632218952608271535089179639890275494426396974475479657192657094698,
|
|
||||||
1670756178709659908159049531058853320846231785448204274277900022176591811072,
|
|
||||||
3538757242013734574731807289786598937548399719866320954894004830207085723125,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
710549042741321081781917034337800036872214466705318638023070812391485261299,
|
|
||||||
2345013122330545298606028187653996682275206910242635100920038943391319595180,
|
|
||||||
3528369671971445493932880023233332035122954362711876290904323783426765912206,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1167120829038120978297497195837406760848728897181138760506162680655977700764,
|
|
||||||
3073243357129146594530765548901087443775563058893907738967898816092270628884,
|
|
||||||
378514724418106317738164464176041649567501099164061863402473942795977719726,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
333391138410406330127594722511180398159664250722328578952158227406762627796,
|
|
||||||
1727570175639917398410201375510924114487348765559913502662122372848626931905,
|
|
||||||
968312190621809249603425066974405725769739606059422769908547372904403793174,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
360659316299446405855194688051178331671817370423873014757323462844775818348,
|
|
||||||
1386580151907705298970465943238806620109618995410132218037375811184684929291,
|
|
||||||
3604888328937389309031638299660239238400230206645344173700074923133890528967,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2496185632263372962152518155651824899299616724241852816983268163379540137546,
|
|
||||||
486538168871046887467737983064272608432052269868418721234810979756540672990,
|
|
||||||
1558415498960552213241704009433360128041672577274390114589014204605400783336,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3512058327686147326577190314835092911156317204978509183234511559551181053926,
|
|
||||||
2235429387083113882635494090887463486491842634403047716936833563914243946191,
|
|
||||||
1290896777143878193192832813769470418518651727840187056683408155503813799882,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1143310336918357319571079551779316654556781203013096026972411429993634080835,
|
|
||||||
3235435208525081966062419599803346573407862428113723170955762956243193422118,
|
|
||||||
1293239921425673430660897025143433077974838969258268884994339615096356996604,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
236252269127612784685426260840574970698541177557674806964960352572864382971,
|
|
||||||
1733907592497266237374827232200506798207318263912423249709509725341212026275,
|
|
||||||
302004309771755665128395814807589350526779835595021835389022325987048089868,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3018926838139221755384801385583867283206879023218491758435446265703006270945,
|
|
||||||
39701437664873825906031098349904330565195980985885489447836580931425171297,
|
|
||||||
908381723021746969965674308809436059628307487140174335882627549095646509778,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
219062858908229855064136253265968615354041842047384625689776811853821594358,
|
|
||||||
1283129863776453589317845316917890202859466483456216900835390291449830275503,
|
|
||||||
418512623547417594896140369190919231877873410935689672661226540908900544012,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1792181590047131972851015200157890246436013346535432437041535789841136268632,
|
|
||||||
370546432987510607338044736824316856592558876687225326692366316978098770516,
|
|
||||||
3323437805230586112013581113386626899534419826098235300155664022709435756946,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
910076621742039763058481476739499965761942516177975130656340375573185415877,
|
|
||||||
1762188042455633427137702520675816545396284185254002959309669405982213803405,
|
|
||||||
2186362253913140345102191078329764107619534641234549431429008219905315900520,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2230647725927681765419218738218528849146504088716182944327179019215826045083,
|
|
||||||
1069243907556644434301190076451112491469636357133398376850435321160857761825,
|
|
||||||
2695241469149243992683268025359863087303400907336026926662328156934068747593,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1361519681544413849831669554199151294308350560528931040264950307931824877035,
|
|
||||||
1339116632207878730171031743761550901312154740800549632983325427035029084904,
|
|
||||||
790593524918851401449292693473498591068920069246127392274811084156907468875,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2723400368331924254840192318398326090089058735091724263333980290765736363637,
|
|
||||||
3457180265095920471443772463283225391927927225993685928066766687141729456030,
|
|
||||||
1483675376954327086153452545475557749815683871577400883707749788555424847954,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2926303836265506736227240325795090239680154099205721426928300056982414025239,
|
|
||||||
543969119775473768170832347411484329362572550684421616624136244239799475526,
|
|
||||||
237401230683847084256617415614300816373730178313253487575312839074042461932,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
844568412840391587862072008674263874021460074878949862892685736454654414423,
|
|
||||||
151922054871708336050647150237534498235916969120198637893731715254687336644,
|
|
||||||
1299332034710622815055321547569101119597030148120309411086203580212105652312,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
487046922649899823989594814663418784068895385009696501386459462815688122993,
|
|
||||||
1104883249092599185744249485896585912845784382683240114120846423960548576851,
|
|
||||||
1458388705536282069567179348797334876446380557083422364875248475157495514484,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
850248109622750774031817200193861444623975329881731864752464222442574976566,
|
|
||||||
2885843173858536690032695698009109793537724845140477446409245651176355435722,
|
|
||||||
3027068551635372249579348422266406787688980506275086097330568993357835463816,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3231892723647447539926175383213338123506134054432701323145045438168976970994,
|
|
||||||
1719080830641935421242626784132692936776388194122314954558418655725251172826,
|
|
||||||
1172253756541066126131022537343350498482225068791630219494878195815226839450,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1619232269633026603732619978083169293258272967781186544174521481891163985093,
|
|
||||||
3495680684841853175973173610562400042003100419811771341346135531754869014567,
|
|
||||||
1576161515913099892951745452471618612307857113799539794680346855318958552758,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2618326122974253423403350731396350223238201817594761152626832144510903048529,
|
|
||||||
2696245132758436974032479782852265185094623165224532063951287925001108567649,
|
|
||||||
930116505665110070247395429730201844026054810856263733273443066419816003444,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2786389174502246248523918824488629229455088716707062764363111940462137404076,
|
|
||||||
1555260846425735320214671887347115247546042526197895180675436886484523605116,
|
|
||||||
2306241912153325247392671742757902161446877415586158295423293240351799505917,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
411529621724849932999694270803131456243889635467661223241617477462914950626,
|
|
||||||
1542495485262286701469125140275904136434075186064076910329015697714211835205,
|
|
||||||
1853045663799041100600825096887578544265580718909350942241802897995488264551,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2963055259497271220202739837493041799968576111953080503132045092194513937286,
|
|
||||||
2303806870349915764285872605046527036748108533406243381676768310692344456050,
|
|
||||||
2622104986201990620910286730213140904984256464479840856728424375142929278875,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2369987021925266811581727383184031736927816625797282287927222602539037105864,
|
|
||||||
285070227712021899602056480426671736057274017903028992288878116056674401781,
|
|
||||||
3034087076179360957800568733595959058628497428787907887933697691951454610691,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
469095854351700119980323115747590868855368701825706298740201488006320881056,
|
|
||||||
360001976264385426746283365024817520563236378289230404095383746911725100012,
|
|
||||||
3438709327109021347267562000879503009590697221730578667498351600602230296178,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
63573904800572228121671659287593650438456772568903228287754075619928214969,
|
|
||||||
3470881855042989871434874691030920672110111605547839662680968354703074556970,
|
|
||||||
724559311507950497340993415408274803001166693839947519425501269424891465492,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
880409284677518997550768549487344416321062350742831373397603704465823658986,
|
|
||||||
6876255662475867703077362872097208259197756317287339941435193538565586230,
|
|
||||||
2701916445133770775447884812906226786217969545216086200932273680400909154638,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
425152119158711585559310064242720816611629181537672850898056934507216982586,
|
|
||||||
1475552998258917706756737045704649573088377604240716286977690565239187213744,
|
|
||||||
2413772448122400684309006716414417978370152271397082147158000439863002593561,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
392160855822256520519339260245328807036619920858503984710539815951012864164,
|
|
||||||
1075036996503791536261050742318169965707018400307026402939804424927087093987,
|
|
||||||
2176439430328703902070742432016450246365760303014562857296722712989275658921,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1413865976587623331051814207977382826721471106513581745229680113383908569693,
|
|
||||||
4879283427490523253696177116563427032332223531862961281430108575019551814,
|
|
||||||
3392583297537374046875199552977614390492290683707960975137418536812266544902,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3600854486849487646325182927019642276644093512133907046667282144129939150983,
|
|
||||||
2779924664161372134024229593301361846129279572186444474616319283535189797834,
|
|
||||||
2722699960903170449291146429799738181514821447014433304730310678334403972040,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
819109815049226540285781191874507704729062681836086010078910930707209464699,
|
|
||||||
3046121243742768013822760785918001632929744274211027071381357122228091333823,
|
|
||||||
1339019590803056172509793134119156250729668216522001157582155155947567682278,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1933279639657506214789316403763326578443023901555983256955812717638093967201,
|
|
||||||
2138221547112520744699126051903811860205771600821672121643894708182292213541,
|
|
||||||
2694713515543641924097704224170357995809887124438248292930846280951601597065,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2471734202930133750093618989223585244499567111661178960753938272334153710615,
|
|
||||||
504903761112092757611047718215309856203214372330635774577409639907729993533,
|
|
||||||
1943979703748281357156510253941035712048221353507135074336243405478613241290,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
684525210957572142559049112233609445802004614280157992196913315652663518936,
|
|
||||||
1705585400798782397786453706717059483604368413512485532079242223503960814508,
|
|
||||||
192429517716023021556170942988476050278432319516032402725586427701913624665,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1586493702243128040549584165333371192888583026298039652930372758731750166765,
|
|
||||||
686072673323546915014972146032384917012218151266600268450347114036285993377,
|
|
||||||
3464340397998075738891129996710075228740496767934137465519455338004332839215,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2805249176617071054530589390406083958753103601524808155663551392362371834663,
|
|
||||||
667746464250968521164727418691487653339733392025160477655836902744186489526,
|
|
||||||
1131527712905109997177270289411406385352032457456054589588342450404257139778,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1908969485750011212309284349900149072003218505891252313183123635318886241171,
|
|
||||||
1025257076985551890132050019084873267454083056307650830147063480409707787695,
|
|
||||||
2153175291918371429502545470578981828372846236838301412119329786849737957977,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3410257749736714576487217882785226905621212230027780855361670645857085424384,
|
|
||||||
3442969106887588154491488961893254739289120695377621434680934888062399029952,
|
|
||||||
3029953900235731770255937704976720759948880815387104275525268727341390470237,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
85453456084781138713939104192561924536933417707871501802199311333127894466,
|
|
||||||
2730629666577257820220329078741301754580009106438115341296453318350676425129,
|
|
||||||
178242450661072967256438102630920745430303027840919213764087927763335940415,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2844589222514708695700541363167856718216388819406388706818431442998498677557,
|
|
||||||
3547876269219141094308889387292091231377253967587961309624916269569559952944,
|
|
||||||
2525005406762984211707203144785482908331876505006839217175334833739957826850,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3096397013555211396701910432830904669391580557191845136003938801598654871345,
|
|
||||||
574424067119200181933992948252007230348512600107123873197603373898923821490,
|
|
||||||
1714030696055067278349157346067719307863507310709155690164546226450579547098,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2339895272202694698739231405357972261413383527237194045718815176814132612501,
|
|
||||||
3562501318971895161271663840954705079797767042115717360959659475564651685069,
|
|
||||||
69069358687197963617161747606993436483967992689488259107924379545671193749,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2614502738369008850475068874731531583863538486212691941619835266611116051561,
|
|
||||||
655247349763023251625727726218660142895322325659927266813592114640858573566,
|
|
||||||
2305235672527595714255517865498269719545193172975330668070873705108690670678,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
926416070297755413261159098243058134401665060349723804040714357642180531931,
|
|
||||||
866523735635840246543516964237513287099659681479228450791071595433217821460,
|
|
||||||
2284334068466681424919271582037156124891004191915573957556691163266198707693,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1812588309302477291425732810913354633465435706480768615104211305579383928792,
|
|
||||||
2836899808619013605432050476764608707770404125005720004551836441247917488507,
|
|
||||||
2989087789022865112405242078196235025698647423649950459911546051695688370523,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
68056284404189102136488263779598243992465747932368669388126367131855404486,
|
|
||||||
505425339250887519581119854377342241317528319745596963584548343662758204398,
|
|
||||||
2118963546856545068961709089296976921067035227488975882615462246481055679215,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2253872596319969096156004495313034590996995209785432485705134570745135149681,
|
|
||||||
1625090409149943603241183848936692198923183279116014478406452426158572703264,
|
|
||||||
179139838844452470348634657368199622305888473747024389514258107503778442495,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1567067018147735642071130442904093290030432522257811793540290101391210410341,
|
|
||||||
2737301854006865242314806979738760349397411136469975337509958305470398783585,
|
|
||||||
3002738216460904473515791428798860225499078134627026021350799206894618186256,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
374029488099466837453096950537275565120689146401077127482884887409712315162,
|
|
||||||
973403256517481077805460710540468856199855789930951602150773500862180885363,
|
|
||||||
2691967457038172130555117632010860984519926022632800605713473799739632878867,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3515906794910381201365530594248181418811879320679684239326734893975752012109,
|
|
||||||
148057579455448384062325089530558091463206199724854022070244924642222283388,
|
|
||||||
1541588700238272710315890873051237741033408846596322948443180470429851502842,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
147013865879011936545137344076637170977925826031496203944786839068852795297,
|
|
||||||
2630278389304735265620281704608245039972003761509102213752997636382302839857,
|
|
||||||
1359048670759642844930007747955701205155822111403150159614453244477853867621,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2438984569205812336319229336885480537793786558293523767186829418969842616677,
|
|
||||||
2137792255841525507649318539501906353254503076308308692873313199435029594138,
|
|
||||||
2262318076430740712267739371170174514379142884859595360065535117601097652755,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2792703718581084537295613508201818489836796608902614779596544185252826291584,
|
|
||||||
2294173715793292812015960640392421991604150133581218254866878921346561546149,
|
|
||||||
2770011224727997178743274791849308200493823127651418989170761007078565678171,
|
|
||||||
],
|
|
||||||
]
|
|
||||||
@@ -1,559 +0,0 @@
|
|||||||
Rate = 3
|
|
||||||
Capacity = 1
|
|
||||||
FullRounds = 8
|
|
||||||
PartialRounds = 84
|
|
||||||
MDS = [[2, 1, 1, 1], [1, 1, 1, 1], [1, 1, 0, 1], [1, 1, 1, -1]]
|
|
||||||
RoundKeys = [
|
|
||||||
[
|
|
||||||
2950795762459345168613727575620414179244544320470208355568817838579231751791,
|
|
||||||
1587446564224215276866294500450702039420286416111469274423465069420553242820,
|
|
||||||
1645965921169490687904413452218868659025437693527479459426157555728339600137,
|
|
||||||
2782373324549879794752287702905278018819686065818504085638398966973694145741,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3409172630025222641379726933524480516420204828329395644967085131392375707302,
|
|
||||||
2379053116496905638239090788901387719228422033660130943198035907032739387135,
|
|
||||||
2570819397480941104144008784293466051718826502582588529995520356691856497111,
|
|
||||||
3546220846133880637977653625763703334841539452343273304410918449202580719746,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2720682389492889709700489490056111332164748138023159726590726667539759963454,
|
|
||||||
1899653471897224903834726250400246354200311275092866725547887381599836519005,
|
|
||||||
2369443697923857319844855392163763375394720104106200469525915896159690979559,
|
|
||||||
2354174693689535854311272135513626412848402744119855553970180659094265527996,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2404084503073127963385083467393598147276436640877011103379112521338973185443,
|
|
||||||
950320777137731763811524327595514151340412860090489448295239456547370725376,
|
|
||||||
2121140748740143694053732746913428481442990369183417228688865837805149503386,
|
|
||||||
2372065044800422557577242066480215868569521938346032514014152523102053709709,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2618497439310693947058545060953893433487994458443568169824149550389484489896,
|
|
||||||
3518297267402065742048564133910509847197496119850246255805075095266319996916,
|
|
||||||
340529752683340505065238931581518232901634742162506851191464448040657139775,
|
|
||||||
1954876811294863748406056845662382214841467408616109501720437541211031966538,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
813813157354633930267029888722341725864333883175521358739311868164460385261,
|
|
||||||
71901595776070443337150458310956362034911936706490730914901986556638720031,
|
|
||||||
2789761472166115462625363403490399263810962093264318361008954888847594113421,
|
|
||||||
2628791615374802560074754031104384456692791616314774034906110098358135152410,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3617032588734559635167557152518265808024917503198278888820567553943986939719,
|
|
||||||
2624012360209966117322788103333497793082705816015202046036057821340914061980,
|
|
||||||
149101987103211771991327927827692640556911620408176100290586418839323044234,
|
|
||||||
1039927963829140138166373450440320262590862908847727961488297105916489431045,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2213946951050724449162431068646025833746639391992751674082854766704900195669,
|
|
||||||
2792724903541814965769131737117981991997031078369482697195201969174353468597,
|
|
||||||
3212031629728871219804596347439383805499808476303618848198208101593976279441,
|
|
||||||
3343514080098703935339621028041191631325798327656683100151836206557453199613,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
614054702436541219556958850933730254992710988573177298270089989048553060199,
|
|
||||||
148148081026449726283933484730968827750202042869875329032965774667206931170,
|
|
||||||
1158283532103191908366672518396366136968613180867652172211392033571980848414,
|
|
||||||
1032400527342371389481069504520755916075559110755235773196747439146396688513,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
806900704622005851310078578853499250941978435851598088619290797134710613736,
|
|
||||||
462498083559902778091095573017508352472262817904991134671058825705968404510,
|
|
||||||
1003580119810278869589347418043095667699674425582646347949349245557449452503,
|
|
||||||
619074932220101074089137133998298830285661916867732916607601635248249357793,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2635090520059500019661864086615522409798872905401305311748231832709078452746,
|
|
||||||
978252636251682252755279071140187792306115352460774007308726210405257135181,
|
|
||||||
1766912167973123409669091967764158892111310474906691336473559256218048677083,
|
|
||||||
1663265127259512472182980890707014969235283233442916350121860684522654120381,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3532407621206959585000336211742670185380751515636605428496206887841428074250,
|
|
||||||
2507023127157093845256722098502856938353143387711652912931112668310034975446,
|
|
||||||
3321152907858462102434883844787153373036767230808678981306827073335525034593,
|
|
||||||
3039253036806065280643845548147711477270022154459620569428286684179698125661,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
103480338868480851881924519768416587261556021758163719199282794248762465380,
|
|
||||||
2394049781357087698434751577708655768465803975478348134669006211289636928495,
|
|
||||||
2660531560345476340796109810821127229446538730404600368347902087220064379579,
|
|
||||||
3603166934034556203649050570865466556260359798872408576857928196141785055563,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1553799760191949768532188139643704561532896296986025007089826672890485412324,
|
|
||||||
2744284717053657689091306578463476341218866418732695211367062598446038965164,
|
|
||||||
320745764922149897598257794663594419839885234101078803811049904310835548856,
|
|
||||||
979382242100682161589753881721708883681034024104145498709287731138044566302,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1860426855810549882740147175136418997351054138609396651615467358416651354991,
|
|
||||||
336173081054369235994909356892506146234495707857220254489443629387613956145,
|
|
||||||
1632470326779699229772327605759783482411227247311431865655466227711078175883,
|
|
||||||
921958250077481394074960433988881176409497663777043304881055317463712938502,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3034358982193370602048539901033542101022185309652879937418114324899281842797,
|
|
||||||
25626282149517463867572353922222474817434101087272320606729439087234878607,
|
|
||||||
3002662261401575565838149305485737102400501329139562227180277188790091853682,
|
|
||||||
2939684373453383817196521641512509179310654199629514917426341354023324109367,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1076484609897998179434851570277297233169621096172424141759873688902355505136,
|
|
||||||
2575095284833160494841112025725243274091830284746697961080467506739203605049,
|
|
||||||
3565075264617591783581665711620369529657840830498005563542124551465195621851,
|
|
||||||
2197016502533303822395077038351174326125210255869204501838837289716363437993,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
331415322883530754594261416546036195982886300052707474899691116664327869405,
|
|
||||||
1935011233711290003793244296594669823169522055520303479680359990463281661839,
|
|
||||||
3495901467168087413996941216661589517270845976538454329511167073314577412322,
|
|
||||||
954195417117133246453562983448451025087661597543338750600301835944144520375,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1271840477709992894995746871435810599280944810893784031132923384456797925777,
|
|
||||||
2565310762274337662754531859505158700827688964841878141121196528015826671847,
|
|
||||||
3365022288251637014588279139038152521653896670895105540140002607272936852513,
|
|
||||||
1660592021628965529963974299647026602622092163312666588591285654477111176051,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
970104372286014048279296575474974982288801187216974504035759997141059513421,
|
|
||||||
2617024574317953753849168721871770134225690844968986289121504184985993971227,
|
|
||||||
999899815343607746071464113462778273556695659506865124478430189024755832262,
|
|
||||||
2228536129413411161615629030408828764980855956560026807518714080003644769896,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2701953891198001564547196795777701119629537795442025393867364730330476403227,
|
|
||||||
837078355588159388741598313782044128527494922918203556465116291436461597853,
|
|
||||||
2121749601840466143704862369657561429793951309962582099604848281796392359214,
|
|
||||||
771812260179247428733132708063116523892339056677915387749121983038690154755,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3317336423132806446086732225036532603224267214833263122557471741829060578219,
|
|
||||||
481570067997721834712647566896657604857788523050900222145547508314620762046,
|
|
||||||
242195042559343964206291740270858862066153636168162642380846129622127460192,
|
|
||||||
2855462178889999218204481481614105202770810647859867354506557827319138379686,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3525521107148375040131784770413887305850308357895464453970651672160034885202,
|
|
||||||
1320839531502392535964065058804908871811967681250362364246430459003920305799,
|
|
||||||
2514191518588387125173345107242226637171897291221681115249521904869763202419,
|
|
||||||
2798335750958827619666318316247381695117827718387653874070218127140615157902,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2808467767967035643407948058486565877867906577474361783201337540214875566395,
|
|
||||||
3551834385992706206273955480294669176699286104229279436819137165202231595747,
|
|
||||||
1219439673853113792340300173186247996249367102884530407862469123523013083971,
|
|
||||||
761519904537984520554247997444508040636526566551719396202550009393012691157,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3355402549169351700500518865338783382387571349497391475317206324155237401353,
|
|
||||||
199541098009731541347317515995192175813554789571447733944970283654592727138,
|
|
||||||
192100490643078165121235261796864975568292640203635147901612231594408079071,
|
|
||||||
1187019357602953326192019968809486933768550466167033084944727938441427050581,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
189525349641911362389041124808934468936759383310282010671081989585219065700,
|
|
||||||
2831653363992091308880573627558515686245403755586311978724025292003353336665,
|
|
||||||
2052859812632218952608271535089179639890275494426396974475479657192657094698,
|
|
||||||
1670756178709659908159049531058853320846231785448204274277900022176591811072,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3538757242013734574731807289786598937548399719866320954894004830207085723125,
|
|
||||||
710549042741321081781917034337800036872214466705318638023070812391485261299,
|
|
||||||
2345013122330545298606028187653996682275206910242635100920038943391319595180,
|
|
||||||
3528369671971445493932880023233332035122954362711876290904323783426765912206,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1167120829038120978297497195837406760848728897181138760506162680655977700764,
|
|
||||||
3073243357129146594530765548901087443775563058893907738967898816092270628884,
|
|
||||||
378514724418106317738164464176041649567501099164061863402473942795977719726,
|
|
||||||
333391138410406330127594722511180398159664250722328578952158227406762627796,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1727570175639917398410201375510924114487348765559913502662122372848626931905,
|
|
||||||
968312190621809249603425066974405725769739606059422769908547372904403793174,
|
|
||||||
360659316299446405855194688051178331671817370423873014757323462844775818348,
|
|
||||||
1386580151907705298970465943238806620109618995410132218037375811184684929291,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3604888328937389309031638299660239238400230206645344173700074923133890528967,
|
|
||||||
2496185632263372962152518155651824899299616724241852816983268163379540137546,
|
|
||||||
486538168871046887467737983064272608432052269868418721234810979756540672990,
|
|
||||||
1558415498960552213241704009433360128041672577274390114589014204605400783336,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3512058327686147326577190314835092911156317204978509183234511559551181053926,
|
|
||||||
2235429387083113882635494090887463486491842634403047716936833563914243946191,
|
|
||||||
1290896777143878193192832813769470418518651727840187056683408155503813799882,
|
|
||||||
1143310336918357319571079551779316654556781203013096026972411429993634080835,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3235435208525081966062419599803346573407862428113723170955762956243193422118,
|
|
||||||
1293239921425673430660897025143433077974838969258268884994339615096356996604,
|
|
||||||
236252269127612784685426260840574970698541177557674806964960352572864382971,
|
|
||||||
1733907592497266237374827232200506798207318263912423249709509725341212026275,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
302004309771755665128395814807589350526779835595021835389022325987048089868,
|
|
||||||
3018926838139221755384801385583867283206879023218491758435446265703006270945,
|
|
||||||
39701437664873825906031098349904330565195980985885489447836580931425171297,
|
|
||||||
908381723021746969965674308809436059628307487140174335882627549095646509778,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
219062858908229855064136253265968615354041842047384625689776811853821594358,
|
|
||||||
1283129863776453589317845316917890202859466483456216900835390291449830275503,
|
|
||||||
418512623547417594896140369190919231877873410935689672661226540908900544012,
|
|
||||||
1792181590047131972851015200157890246436013346535432437041535789841136268632,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
370546432987510607338044736824316856592558876687225326692366316978098770516,
|
|
||||||
3323437805230586112013581113386626899534419826098235300155664022709435756946,
|
|
||||||
910076621742039763058481476739499965761942516177975130656340375573185415877,
|
|
||||||
1762188042455633427137702520675816545396284185254002959309669405982213803405,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2186362253913140345102191078329764107619534641234549431429008219905315900520,
|
|
||||||
2230647725927681765419218738218528849146504088716182944327179019215826045083,
|
|
||||||
1069243907556644434301190076451112491469636357133398376850435321160857761825,
|
|
||||||
2695241469149243992683268025359863087303400907336026926662328156934068747593,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1361519681544413849831669554199151294308350560528931040264950307931824877035,
|
|
||||||
1339116632207878730171031743761550901312154740800549632983325427035029084904,
|
|
||||||
790593524918851401449292693473498591068920069246127392274811084156907468875,
|
|
||||||
2723400368331924254840192318398326090089058735091724263333980290765736363637,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3457180265095920471443772463283225391927927225993685928066766687141729456030,
|
|
||||||
1483675376954327086153452545475557749815683871577400883707749788555424847954,
|
|
||||||
2926303836265506736227240325795090239680154099205721426928300056982414025239,
|
|
||||||
543969119775473768170832347411484329362572550684421616624136244239799475526,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
237401230683847084256617415614300816373730178313253487575312839074042461932,
|
|
||||||
844568412840391587862072008674263874021460074878949862892685736454654414423,
|
|
||||||
151922054871708336050647150237534498235916969120198637893731715254687336644,
|
|
||||||
1299332034710622815055321547569101119597030148120309411086203580212105652312,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
487046922649899823989594814663418784068895385009696501386459462815688122993,
|
|
||||||
1104883249092599185744249485896585912845784382683240114120846423960548576851,
|
|
||||||
1458388705536282069567179348797334876446380557083422364875248475157495514484,
|
|
||||||
850248109622750774031817200193861444623975329881731864752464222442574976566,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2885843173858536690032695698009109793537724845140477446409245651176355435722,
|
|
||||||
3027068551635372249579348422266406787688980506275086097330568993357835463816,
|
|
||||||
3231892723647447539926175383213338123506134054432701323145045438168976970994,
|
|
||||||
1719080830641935421242626784132692936776388194122314954558418655725251172826,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1172253756541066126131022537343350498482225068791630219494878195815226839450,
|
|
||||||
1619232269633026603732619978083169293258272967781186544174521481891163985093,
|
|
||||||
3495680684841853175973173610562400042003100419811771341346135531754869014567,
|
|
||||||
1576161515913099892951745452471618612307857113799539794680346855318958552758,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2618326122974253423403350731396350223238201817594761152626832144510903048529,
|
|
||||||
2696245132758436974032479782852265185094623165224532063951287925001108567649,
|
|
||||||
930116505665110070247395429730201844026054810856263733273443066419816003444,
|
|
||||||
2786389174502246248523918824488629229455088716707062764363111940462137404076,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1555260846425735320214671887347115247546042526197895180675436886484523605116,
|
|
||||||
2306241912153325247392671742757902161446877415586158295423293240351799505917,
|
|
||||||
411529621724849932999694270803131456243889635467661223241617477462914950626,
|
|
||||||
1542495485262286701469125140275904136434075186064076910329015697714211835205,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1853045663799041100600825096887578544265580718909350942241802897995488264551,
|
|
||||||
2963055259497271220202739837493041799968576111953080503132045092194513937286,
|
|
||||||
2303806870349915764285872605046527036748108533406243381676768310692344456050,
|
|
||||||
2622104986201990620910286730213140904984256464479840856728424375142929278875,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2369987021925266811581727383184031736927816625797282287927222602539037105864,
|
|
||||||
285070227712021899602056480426671736057274017903028992288878116056674401781,
|
|
||||||
3034087076179360957800568733595959058628497428787907887933697691951454610691,
|
|
||||||
469095854351700119980323115747590868855368701825706298740201488006320881056,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
360001976264385426746283365024817520563236378289230404095383746911725100012,
|
|
||||||
3438709327109021347267562000879503009590697221730578667498351600602230296178,
|
|
||||||
63573904800572228121671659287593650438456772568903228287754075619928214969,
|
|
||||||
3470881855042989871434874691030920672110111605547839662680968354703074556970,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
724559311507950497340993415408274803001166693839947519425501269424891465492,
|
|
||||||
880409284677518997550768549487344416321062350742831373397603704465823658986,
|
|
||||||
6876255662475867703077362872097208259197756317287339941435193538565586230,
|
|
||||||
2701916445133770775447884812906226786217969545216086200932273680400909154638,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
425152119158711585559310064242720816611629181537672850898056934507216982586,
|
|
||||||
1475552998258917706756737045704649573088377604240716286977690565239187213744,
|
|
||||||
2413772448122400684309006716414417978370152271397082147158000439863002593561,
|
|
||||||
392160855822256520519339260245328807036619920858503984710539815951012864164,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1075036996503791536261050742318169965707018400307026402939804424927087093987,
|
|
||||||
2176439430328703902070742432016450246365760303014562857296722712989275658921,
|
|
||||||
1413865976587623331051814207977382826721471106513581745229680113383908569693,
|
|
||||||
4879283427490523253696177116563427032332223531862961281430108575019551814,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3392583297537374046875199552977614390492290683707960975137418536812266544902,
|
|
||||||
3600854486849487646325182927019642276644093512133907046667282144129939150983,
|
|
||||||
2779924664161372134024229593301361846129279572186444474616319283535189797834,
|
|
||||||
2722699960903170449291146429799738181514821447014433304730310678334403972040,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
819109815049226540285781191874507704729062681836086010078910930707209464699,
|
|
||||||
3046121243742768013822760785918001632929744274211027071381357122228091333823,
|
|
||||||
1339019590803056172509793134119156250729668216522001157582155155947567682278,
|
|
||||||
1933279639657506214789316403763326578443023901555983256955812717638093967201,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2138221547112520744699126051903811860205771600821672121643894708182292213541,
|
|
||||||
2694713515543641924097704224170357995809887124438248292930846280951601597065,
|
|
||||||
2471734202930133750093618989223585244499567111661178960753938272334153710615,
|
|
||||||
504903761112092757611047718215309856203214372330635774577409639907729993533,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1943979703748281357156510253941035712048221353507135074336243405478613241290,
|
|
||||||
684525210957572142559049112233609445802004614280157992196913315652663518936,
|
|
||||||
1705585400798782397786453706717059483604368413512485532079242223503960814508,
|
|
||||||
192429517716023021556170942988476050278432319516032402725586427701913624665,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1586493702243128040549584165333371192888583026298039652930372758731750166765,
|
|
||||||
686072673323546915014972146032384917012218151266600268450347114036285993377,
|
|
||||||
3464340397998075738891129996710075228740496767934137465519455338004332839215,
|
|
||||||
2805249176617071054530589390406083958753103601524808155663551392362371834663,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
667746464250968521164727418691487653339733392025160477655836902744186489526,
|
|
||||||
1131527712905109997177270289411406385352032457456054589588342450404257139778,
|
|
||||||
1908969485750011212309284349900149072003218505891252313183123635318886241171,
|
|
||||||
1025257076985551890132050019084873267454083056307650830147063480409707787695,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2153175291918371429502545470578981828372846236838301412119329786849737957977,
|
|
||||||
3410257749736714576487217882785226905621212230027780855361670645857085424384,
|
|
||||||
3442969106887588154491488961893254739289120695377621434680934888062399029952,
|
|
||||||
3029953900235731770255937704976720759948880815387104275525268727341390470237,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
85453456084781138713939104192561924536933417707871501802199311333127894466,
|
|
||||||
2730629666577257820220329078741301754580009106438115341296453318350676425129,
|
|
||||||
178242450661072967256438102630920745430303027840919213764087927763335940415,
|
|
||||||
2844589222514708695700541363167856718216388819406388706818431442998498677557,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3547876269219141094308889387292091231377253967587961309624916269569559952944,
|
|
||||||
2525005406762984211707203144785482908331876505006839217175334833739957826850,
|
|
||||||
3096397013555211396701910432830904669391580557191845136003938801598654871345,
|
|
||||||
574424067119200181933992948252007230348512600107123873197603373898923821490,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1714030696055067278349157346067719307863507310709155690164546226450579547098,
|
|
||||||
2339895272202694698739231405357972261413383527237194045718815176814132612501,
|
|
||||||
3562501318971895161271663840954705079797767042115717360959659475564651685069,
|
|
||||||
69069358687197963617161747606993436483967992689488259107924379545671193749,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2614502738369008850475068874731531583863538486212691941619835266611116051561,
|
|
||||||
655247349763023251625727726218660142895322325659927266813592114640858573566,
|
|
||||||
2305235672527595714255517865498269719545193172975330668070873705108690670678,
|
|
||||||
926416070297755413261159098243058134401665060349723804040714357642180531931,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
866523735635840246543516964237513287099659681479228450791071595433217821460,
|
|
||||||
2284334068466681424919271582037156124891004191915573957556691163266198707693,
|
|
||||||
1812588309302477291425732810913354633465435706480768615104211305579383928792,
|
|
||||||
2836899808619013605432050476764608707770404125005720004551836441247917488507,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2989087789022865112405242078196235025698647423649950459911546051695688370523,
|
|
||||||
68056284404189102136488263779598243992465747932368669388126367131855404486,
|
|
||||||
505425339250887519581119854377342241317528319745596963584548343662758204398,
|
|
||||||
2118963546856545068961709089296976921067035227488975882615462246481055679215,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2253872596319969096156004495313034590996995209785432485705134570745135149681,
|
|
||||||
1625090409149943603241183848936692198923183279116014478406452426158572703264,
|
|
||||||
179139838844452470348634657368199622305888473747024389514258107503778442495,
|
|
||||||
1567067018147735642071130442904093290030432522257811793540290101391210410341,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2737301854006865242314806979738760349397411136469975337509958305470398783585,
|
|
||||||
3002738216460904473515791428798860225499078134627026021350799206894618186256,
|
|
||||||
374029488099466837453096950537275565120689146401077127482884887409712315162,
|
|
||||||
973403256517481077805460710540468856199855789930951602150773500862180885363,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2691967457038172130555117632010860984519926022632800605713473799739632878867,
|
|
||||||
3515906794910381201365530594248181418811879320679684239326734893975752012109,
|
|
||||||
148057579455448384062325089530558091463206199724854022070244924642222283388,
|
|
||||||
1541588700238272710315890873051237741033408846596322948443180470429851502842,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
147013865879011936545137344076637170977925826031496203944786839068852795297,
|
|
||||||
2630278389304735265620281704608245039972003761509102213752997636382302839857,
|
|
||||||
1359048670759642844930007747955701205155822111403150159614453244477853867621,
|
|
||||||
2438984569205812336319229336885480537793786558293523767186829418969842616677,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2137792255841525507649318539501906353254503076308308692873313199435029594138,
|
|
||||||
2262318076430740712267739371170174514379142884859595360065535117601097652755,
|
|
||||||
2792703718581084537295613508201818489836796608902614779596544185252826291584,
|
|
||||||
2294173715793292812015960640392421991604150133581218254866878921346561546149,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2770011224727997178743274791849308200493823127651418989170761007078565678171,
|
|
||||||
3321642244537785916275181932172303118112488081726311374164578600576901819844,
|
|
||||||
3522708517589950573320671158134804505970724681591943826922697952040487655044,
|
|
||||||
3417974441436557992524691506735790206623600049454586729879955931972546347402,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
175039333145381316571259690443853067809784261609912638686739799135919647022,
|
|
||||||
1930713062131033273316869231148248962041053029742760224583505092759642967464,
|
|
||||||
2971452932574554603554350185069538580257636405419430340233233400633251319042,
|
|
||||||
2774781903758215341037075610938953949868289195845367046186588750871862784919,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
666516874137869653699423537799457099346460194092311952417454613224504932738,
|
|
||||||
1900462225013533249140457703727169176351786259991305560412832202759625668041,
|
|
||||||
2665631186082687279121709429531834469477679375137509769347092380798929714377,
|
|
||||||
837840745988147279235494664091280091563355097569199320366973125128366540061,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3391544118305848781823721719916289805455110924839794510205940718821197620955,
|
|
||||||
2888553035909938253628892138500390690221493345071933642853222968481016605919,
|
|
||||||
3386241569867597612447901482685846444743718781330869478721963580925825915450,
|
|
||||||
1205126220630896984850042596877918177217334376800874965105642874206963597698,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3590072615491710252422997155203204584659171612188004116415640739580250394190,
|
|
||||||
692469013329617220154003334549812915100479873898898958632988703738125356983,
|
|
||||||
1623178235190707102808841905143937367808788834203621005714003335195182126335,
|
|
||||||
1972826180775011489122426045504602288576507493792470102803637471568052321297,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3415141329098504418158191749675997877417539760075593313736376750580696083073,
|
|
||||||
587811537889727046473915684463981273175495137461951211739526104349163747811,
|
|
||||||
2523982964351069134084525951849317400231659428055762640605248929856135518199,
|
|
||||||
2686176526711834950207666047281383173339057216783586039351834948812568447629,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
983144446441739425577690449774542566745526459152966545642451764143532586964,
|
|
||||||
171558252019175695567663688494555626159399786667979998273792882504784080805,
|
|
||||||
332337623010057542760158225837623039780806442976079546879646069338600179518,
|
|
||||||
1264669683963885571544813806669118319675288608634733888843804451222546848295,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2426165115815723668018318268486497504249785449504758403912155206515511627681,
|
|
||||||
11387399609384288947733630450855186629703576293221897150193655994854764608,
|
|
||||||
2541728569046079092074077754414781968906176513081761690404588216304985421091,
|
|
||||||
47685947554980329431290582269851186106577733250761848107645535357326439312,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
472176388418187405374813530639596064799362505024895746833751173199773896628,
|
|
||||||
2764298116617383397920343358525617195195060562266243809245480210157942112738,
|
|
||||||
486863835068754002670800862273365477867695879270721744227071001883208334054,
|
|
||||||
2973492686137102577527656941792991264994301121122130295965761350095846874635,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
178385615141132702906181473263873416748818415607305319148067639744074654009,
|
|
||||||
533624640096756667052211553746016402543259206286603356120804827761339634127,
|
|
||||||
819406716720171922688026098737835227857400444543748198788964759773510472096,
|
|
||||||
531851793767260921861217458033110066464894334064526987603936107947006031387,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3269709072483585277009748181134917746036523619604017812342933951952104134829,
|
|
||||||
838191718603413598040249006803464503100808192944407407147899973659013630611,
|
|
||||||
1574561296941310904780257598780779812250055948216417844567262310524022037406,
|
|
||||||
551394354289003977607664358739006072556227894953233419144430578080352094737,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
445076790942318675726839050057337819004979443030540904213920669247413907302,
|
|
||||||
1963946696292687224902912968478695543164747600779913024040878700455222386521,
|
|
||||||
484284614181963381509745298932402076252103342403432879800905151752488144767,
|
|
||||||
2240507606126946994415203252302826782042951346966859379502140796364876543253,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3237135638753992982179886898758938279897590886053928839613434762582576319619,
|
|
||||||
2334333034701915027889533058426879447140084891006486138782876488162658230991,
|
|
||||||
14411091399844539897439754491034751977136685514851444574462584316609631592,
|
|
||||||
1264480371592407258420308876448697804787923638319277097663041109464608464284,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
671929312763821646360589403212798993954209530574443543917757335777610372144,
|
|
||||||
2513909805455654095962542944994577107405216428214873444765576238504714067396,
|
|
||||||
870121102846043786263357605823753628974859886859187558617096145653709171231,
|
|
||||||
399132620893316356411986266679786708905730068946836982293484206366500277754,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2855046250836680633532995284655778407402587437073106249445470889390454667586,
|
|
||||||
2063679741125384345396981490971605710211281905716315529671473143278849561151,
|
|
||||||
1433753212258929925682201698758056443128516570551146995210728194816988328337,
|
|
||||||
3334984763425011856632257855270507440816274246647423607159847074739331865077,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
337911293622078184850923533628334646725451591671907148383867096651211846605,
|
|
||||||
559587005295238702015018022040357402231957131094636365177008701077975941644,
|
|
||||||
885963059604819264377490633589388189646118257469490919900554134369512794660,
|
|
||||||
1957748763518471091057032383332840331641373304981058387824598000170709016333,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3175295982155056798972302481564899381103533409383494814704562889625572018450,
|
|
||||||
498987160612401618114584726510347771865331516606886613019084323862447372555,
|
|
||||||
947374835104260364630171441676101001841507588423166778786886198914150312958,
|
|
||||||
906933977754491302438795274167251538820934378773708095543613756654712689280,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2170116291766863179909957030577284618726490893598499117272497866180009722894,
|
|
||||||
1801335399574515889082584621772588704763181408217893911806726119813067220453,
|
|
||||||
1942500232535842474530840356353427989892065499159260166135596750084681859966,
|
|
||||||
62936080219825306823124060587235998278756755377419521154040408253893795176,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3091993939935137795359769774909373279950941171574748645375255810204590357753,
|
|
||||||
1283528386884634267663661033944552098742115012555712906773586466375284501324,
|
|
||||||
1581820717639229420476069802992937438655873471854930764425841549067913106065,
|
|
||||||
2301986095388751633126546121528329200085681648876910655269533407603441046514,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2850003828037698751961753862613545302539465803982364898225617297398939302949,
|
|
||||||
48024691078494936445046366770271288984930221238071705874025261821606393528,
|
|
||||||
1482336297033144958942154923925185950152551534403871620222916667536030875354,
|
|
||||||
3081177564717719643771186007689458633949181485535169123213511264603782950049,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3315701127039521853279746297714590495201061397709680410650043502532250578075,
|
|
||||||
3514407611000441301995070394422463400067690470546731164089622325748803106020,
|
|
||||||
368970178199930154322724953487299516224498421233447528815195701420122548537,
|
|
||||||
584353160413525267849669053228533951552602295860601556035386665117717227391,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
752038702160385294706011538400822066722189014251268673051846350397729870418,
|
|
||||||
3594041683498798688197194521326299097635429790757880308152971477196489335154,
|
|
||||||
1367902435756906062215608264424138718742854099315395230911274560900857414183,
|
|
||||||
1828549068951502746189364466794037234789986878381694857475972053743463890779,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
488172495141237210878388657234137733008417573114482400652274985829148564248,
|
|
||||||
962906242461930394022372340919543491337923491322497419797555620396501785566,
|
|
||||||
2275418085010046236619290386129138234541669589549771944697082317642065048898,
|
|
||||||
1966395064658902622886154686288219600816893261614483533899715888994623208964,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3496095878293416917311185659829821476802828534554531050412634978086916288609,
|
|
||||||
3368478822390537245916137403277928093536087427951052230723275731232142463388,
|
|
||||||
3397410259276620127103231993277518800970669191016277541098821699302368873803,
|
|
||||||
2662600899665871010006649609856695263727220473364611552472965243032255906029,
|
|
||||||
],
|
|
||||||
]
|
|
||||||
@@ -1,651 +0,0 @@
|
|||||||
Rate = 4
|
|
||||||
Capacity = 1
|
|
||||||
FullRounds = 8
|
|
||||||
PartialRounds = 84
|
|
||||||
MDS = [[3, 1, 1, 1, 1], [1, 2, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, -1, 1], [1, 1, 1, 1, -2]]
|
|
||||||
RoundKeys = [
|
|
||||||
[
|
|
||||||
2950795762459345168613727575620414179244544320470208355568817838579231751791,
|
|
||||||
1587446564224215276866294500450702039420286416111469274423465069420553242820,
|
|
||||||
1645965921169490687904413452218868659025437693527479459426157555728339600137,
|
|
||||||
2782373324549879794752287702905278018819686065818504085638398966973694145741,
|
|
||||||
3409172630025222641379726933524480516420204828329395644967085131392375707302,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2379053116496905638239090788901387719228422033660130943198035907032739387135,
|
|
||||||
2570819397480941104144008784293466051718826502582588529995520356691856497111,
|
|
||||||
3546220846133880637977653625763703334841539452343273304410918449202580719746,
|
|
||||||
2720682389492889709700489490056111332164748138023159726590726667539759963454,
|
|
||||||
1899653471897224903834726250400246354200311275092866725547887381599836519005,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2369443697923857319844855392163763375394720104106200469525915896159690979559,
|
|
||||||
2354174693689535854311272135513626412848402744119855553970180659094265527996,
|
|
||||||
2404084503073127963385083467393598147276436640877011103379112521338973185443,
|
|
||||||
950320777137731763811524327595514151340412860090489448295239456547370725376,
|
|
||||||
2121140748740143694053732746913428481442990369183417228688865837805149503386,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2372065044800422557577242066480215868569521938346032514014152523102053709709,
|
|
||||||
2618497439310693947058545060953893433487994458443568169824149550389484489896,
|
|
||||||
3518297267402065742048564133910509847197496119850246255805075095266319996916,
|
|
||||||
340529752683340505065238931581518232901634742162506851191464448040657139775,
|
|
||||||
1954876811294863748406056845662382214841467408616109501720437541211031966538,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
813813157354633930267029888722341725864333883175521358739311868164460385261,
|
|
||||||
71901595776070443337150458310956362034911936706490730914901986556638720031,
|
|
||||||
2789761472166115462625363403490399263810962093264318361008954888847594113421,
|
|
||||||
2628791615374802560074754031104384456692791616314774034906110098358135152410,
|
|
||||||
3617032588734559635167557152518265808024917503198278888820567553943986939719,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2624012360209966117322788103333497793082705816015202046036057821340914061980,
|
|
||||||
149101987103211771991327927827692640556911620408176100290586418839323044234,
|
|
||||||
1039927963829140138166373450440320262590862908847727961488297105916489431045,
|
|
||||||
2213946951050724449162431068646025833746639391992751674082854766704900195669,
|
|
||||||
2792724903541814965769131737117981991997031078369482697195201969174353468597,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3212031629728871219804596347439383805499808476303618848198208101593976279441,
|
|
||||||
3343514080098703935339621028041191631325798327656683100151836206557453199613,
|
|
||||||
614054702436541219556958850933730254992710988573177298270089989048553060199,
|
|
||||||
148148081026449726283933484730968827750202042869875329032965774667206931170,
|
|
||||||
1158283532103191908366672518396366136968613180867652172211392033571980848414,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1032400527342371389481069504520755916075559110755235773196747439146396688513,
|
|
||||||
806900704622005851310078578853499250941978435851598088619290797134710613736,
|
|
||||||
462498083559902778091095573017508352472262817904991134671058825705968404510,
|
|
||||||
1003580119810278869589347418043095667699674425582646347949349245557449452503,
|
|
||||||
619074932220101074089137133998298830285661916867732916607601635248249357793,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2635090520059500019661864086615522409798872905401305311748231832709078452746,
|
|
||||||
978252636251682252755279071140187792306115352460774007308726210405257135181,
|
|
||||||
1766912167973123409669091967764158892111310474906691336473559256218048677083,
|
|
||||||
1663265127259512472182980890707014969235283233442916350121860684522654120381,
|
|
||||||
3532407621206959585000336211742670185380751515636605428496206887841428074250,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2507023127157093845256722098502856938353143387711652912931112668310034975446,
|
|
||||||
3321152907858462102434883844787153373036767230808678981306827073335525034593,
|
|
||||||
3039253036806065280643845548147711477270022154459620569428286684179698125661,
|
|
||||||
103480338868480851881924519768416587261556021758163719199282794248762465380,
|
|
||||||
2394049781357087698434751577708655768465803975478348134669006211289636928495,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2660531560345476340796109810821127229446538730404600368347902087220064379579,
|
|
||||||
3603166934034556203649050570865466556260359798872408576857928196141785055563,
|
|
||||||
1553799760191949768532188139643704561532896296986025007089826672890485412324,
|
|
||||||
2744284717053657689091306578463476341218866418732695211367062598446038965164,
|
|
||||||
320745764922149897598257794663594419839885234101078803811049904310835548856,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
979382242100682161589753881721708883681034024104145498709287731138044566302,
|
|
||||||
1860426855810549882740147175136418997351054138609396651615467358416651354991,
|
|
||||||
336173081054369235994909356892506146234495707857220254489443629387613956145,
|
|
||||||
1632470326779699229772327605759783482411227247311431865655466227711078175883,
|
|
||||||
921958250077481394074960433988881176409497663777043304881055317463712938502,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3034358982193370602048539901033542101022185309652879937418114324899281842797,
|
|
||||||
25626282149517463867572353922222474817434101087272320606729439087234878607,
|
|
||||||
3002662261401575565838149305485737102400501329139562227180277188790091853682,
|
|
||||||
2939684373453383817196521641512509179310654199629514917426341354023324109367,
|
|
||||||
1076484609897998179434851570277297233169621096172424141759873688902355505136,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2575095284833160494841112025725243274091830284746697961080467506739203605049,
|
|
||||||
3565075264617591783581665711620369529657840830498005563542124551465195621851,
|
|
||||||
2197016502533303822395077038351174326125210255869204501838837289716363437993,
|
|
||||||
331415322883530754594261416546036195982886300052707474899691116664327869405,
|
|
||||||
1935011233711290003793244296594669823169522055520303479680359990463281661839,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3495901467168087413996941216661589517270845976538454329511167073314577412322,
|
|
||||||
954195417117133246453562983448451025087661597543338750600301835944144520375,
|
|
||||||
1271840477709992894995746871435810599280944810893784031132923384456797925777,
|
|
||||||
2565310762274337662754531859505158700827688964841878141121196528015826671847,
|
|
||||||
3365022288251637014588279139038152521653896670895105540140002607272936852513,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1660592021628965529963974299647026602622092163312666588591285654477111176051,
|
|
||||||
970104372286014048279296575474974982288801187216974504035759997141059513421,
|
|
||||||
2617024574317953753849168721871770134225690844968986289121504184985993971227,
|
|
||||||
999899815343607746071464113462778273556695659506865124478430189024755832262,
|
|
||||||
2228536129413411161615629030408828764980855956560026807518714080003644769896,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2701953891198001564547196795777701119629537795442025393867364730330476403227,
|
|
||||||
837078355588159388741598313782044128527494922918203556465116291436461597853,
|
|
||||||
2121749601840466143704862369657561429793951309962582099604848281796392359214,
|
|
||||||
771812260179247428733132708063116523892339056677915387749121983038690154755,
|
|
||||||
3317336423132806446086732225036532603224267214833263122557471741829060578219,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
481570067997721834712647566896657604857788523050900222145547508314620762046,
|
|
||||||
242195042559343964206291740270858862066153636168162642380846129622127460192,
|
|
||||||
2855462178889999218204481481614105202770810647859867354506557827319138379686,
|
|
||||||
3525521107148375040131784770413887305850308357895464453970651672160034885202,
|
|
||||||
1320839531502392535964065058804908871811967681250362364246430459003920305799,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2514191518588387125173345107242226637171897291221681115249521904869763202419,
|
|
||||||
2798335750958827619666318316247381695117827718387653874070218127140615157902,
|
|
||||||
2808467767967035643407948058486565877867906577474361783201337540214875566395,
|
|
||||||
3551834385992706206273955480294669176699286104229279436819137165202231595747,
|
|
||||||
1219439673853113792340300173186247996249367102884530407862469123523013083971,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
761519904537984520554247997444508040636526566551719396202550009393012691157,
|
|
||||||
3355402549169351700500518865338783382387571349497391475317206324155237401353,
|
|
||||||
199541098009731541347317515995192175813554789571447733944970283654592727138,
|
|
||||||
192100490643078165121235261796864975568292640203635147901612231594408079071,
|
|
||||||
1187019357602953326192019968809486933768550466167033084944727938441427050581,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
189525349641911362389041124808934468936759383310282010671081989585219065700,
|
|
||||||
2831653363992091308880573627558515686245403755586311978724025292003353336665,
|
|
||||||
2052859812632218952608271535089179639890275494426396974475479657192657094698,
|
|
||||||
1670756178709659908159049531058853320846231785448204274277900022176591811072,
|
|
||||||
3538757242013734574731807289786598937548399719866320954894004830207085723125,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
710549042741321081781917034337800036872214466705318638023070812391485261299,
|
|
||||||
2345013122330545298606028187653996682275206910242635100920038943391319595180,
|
|
||||||
3528369671971445493932880023233332035122954362711876290904323783426765912206,
|
|
||||||
1167120829038120978297497195837406760848728897181138760506162680655977700764,
|
|
||||||
3073243357129146594530765548901087443775563058893907738967898816092270628884,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
378514724418106317738164464176041649567501099164061863402473942795977719726,
|
|
||||||
333391138410406330127594722511180398159664250722328578952158227406762627796,
|
|
||||||
1727570175639917398410201375510924114487348765559913502662122372848626931905,
|
|
||||||
968312190621809249603425066974405725769739606059422769908547372904403793174,
|
|
||||||
360659316299446405855194688051178331671817370423873014757323462844775818348,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1386580151907705298970465943238806620109618995410132218037375811184684929291,
|
|
||||||
3604888328937389309031638299660239238400230206645344173700074923133890528967,
|
|
||||||
2496185632263372962152518155651824899299616724241852816983268163379540137546,
|
|
||||||
486538168871046887467737983064272608432052269868418721234810979756540672990,
|
|
||||||
1558415498960552213241704009433360128041672577274390114589014204605400783336,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3512058327686147326577190314835092911156317204978509183234511559551181053926,
|
|
||||||
2235429387083113882635494090887463486491842634403047716936833563914243946191,
|
|
||||||
1290896777143878193192832813769470418518651727840187056683408155503813799882,
|
|
||||||
1143310336918357319571079551779316654556781203013096026972411429993634080835,
|
|
||||||
3235435208525081966062419599803346573407862428113723170955762956243193422118,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1293239921425673430660897025143433077974838969258268884994339615096356996604,
|
|
||||||
236252269127612784685426260840574970698541177557674806964960352572864382971,
|
|
||||||
1733907592497266237374827232200506798207318263912423249709509725341212026275,
|
|
||||||
302004309771755665128395814807589350526779835595021835389022325987048089868,
|
|
||||||
3018926838139221755384801385583867283206879023218491758435446265703006270945,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
39701437664873825906031098349904330565195980985885489447836580931425171297,
|
|
||||||
908381723021746969965674308809436059628307487140174335882627549095646509778,
|
|
||||||
219062858908229855064136253265968615354041842047384625689776811853821594358,
|
|
||||||
1283129863776453589317845316917890202859466483456216900835390291449830275503,
|
|
||||||
418512623547417594896140369190919231877873410935689672661226540908900544012,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1792181590047131972851015200157890246436013346535432437041535789841136268632,
|
|
||||||
370546432987510607338044736824316856592558876687225326692366316978098770516,
|
|
||||||
3323437805230586112013581113386626899534419826098235300155664022709435756946,
|
|
||||||
910076621742039763058481476739499965761942516177975130656340375573185415877,
|
|
||||||
1762188042455633427137702520675816545396284185254002959309669405982213803405,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2186362253913140345102191078329764107619534641234549431429008219905315900520,
|
|
||||||
2230647725927681765419218738218528849146504088716182944327179019215826045083,
|
|
||||||
1069243907556644434301190076451112491469636357133398376850435321160857761825,
|
|
||||||
2695241469149243992683268025359863087303400907336026926662328156934068747593,
|
|
||||||
1361519681544413849831669554199151294308350560528931040264950307931824877035,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1339116632207878730171031743761550901312154740800549632983325427035029084904,
|
|
||||||
790593524918851401449292693473498591068920069246127392274811084156907468875,
|
|
||||||
2723400368331924254840192318398326090089058735091724263333980290765736363637,
|
|
||||||
3457180265095920471443772463283225391927927225993685928066766687141729456030,
|
|
||||||
1483675376954327086153452545475557749815683871577400883707749788555424847954,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2926303836265506736227240325795090239680154099205721426928300056982414025239,
|
|
||||||
543969119775473768170832347411484329362572550684421616624136244239799475526,
|
|
||||||
237401230683847084256617415614300816373730178313253487575312839074042461932,
|
|
||||||
844568412840391587862072008674263874021460074878949862892685736454654414423,
|
|
||||||
151922054871708336050647150237534498235916969120198637893731715254687336644,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1299332034710622815055321547569101119597030148120309411086203580212105652312,
|
|
||||||
487046922649899823989594814663418784068895385009696501386459462815688122993,
|
|
||||||
1104883249092599185744249485896585912845784382683240114120846423960548576851,
|
|
||||||
1458388705536282069567179348797334876446380557083422364875248475157495514484,
|
|
||||||
850248109622750774031817200193861444623975329881731864752464222442574976566,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2885843173858536690032695698009109793537724845140477446409245651176355435722,
|
|
||||||
3027068551635372249579348422266406787688980506275086097330568993357835463816,
|
|
||||||
3231892723647447539926175383213338123506134054432701323145045438168976970994,
|
|
||||||
1719080830641935421242626784132692936776388194122314954558418655725251172826,
|
|
||||||
1172253756541066126131022537343350498482225068791630219494878195815226839450,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1619232269633026603732619978083169293258272967781186544174521481891163985093,
|
|
||||||
3495680684841853175973173610562400042003100419811771341346135531754869014567,
|
|
||||||
1576161515913099892951745452471618612307857113799539794680346855318958552758,
|
|
||||||
2618326122974253423403350731396350223238201817594761152626832144510903048529,
|
|
||||||
2696245132758436974032479782852265185094623165224532063951287925001108567649,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
930116505665110070247395429730201844026054810856263733273443066419816003444,
|
|
||||||
2786389174502246248523918824488629229455088716707062764363111940462137404076,
|
|
||||||
1555260846425735320214671887347115247546042526197895180675436886484523605116,
|
|
||||||
2306241912153325247392671742757902161446877415586158295423293240351799505917,
|
|
||||||
411529621724849932999694270803131456243889635467661223241617477462914950626,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1542495485262286701469125140275904136434075186064076910329015697714211835205,
|
|
||||||
1853045663799041100600825096887578544265580718909350942241802897995488264551,
|
|
||||||
2963055259497271220202739837493041799968576111953080503132045092194513937286,
|
|
||||||
2303806870349915764285872605046527036748108533406243381676768310692344456050,
|
|
||||||
2622104986201990620910286730213140904984256464479840856728424375142929278875,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2369987021925266811581727383184031736927816625797282287927222602539037105864,
|
|
||||||
285070227712021899602056480426671736057274017903028992288878116056674401781,
|
|
||||||
3034087076179360957800568733595959058628497428787907887933697691951454610691,
|
|
||||||
469095854351700119980323115747590868855368701825706298740201488006320881056,
|
|
||||||
360001976264385426746283365024817520563236378289230404095383746911725100012,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3438709327109021347267562000879503009590697221730578667498351600602230296178,
|
|
||||||
63573904800572228121671659287593650438456772568903228287754075619928214969,
|
|
||||||
3470881855042989871434874691030920672110111605547839662680968354703074556970,
|
|
||||||
724559311507950497340993415408274803001166693839947519425501269424891465492,
|
|
||||||
880409284677518997550768549487344416321062350742831373397603704465823658986,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
6876255662475867703077362872097208259197756317287339941435193538565586230,
|
|
||||||
2701916445133770775447884812906226786217969545216086200932273680400909154638,
|
|
||||||
425152119158711585559310064242720816611629181537672850898056934507216982586,
|
|
||||||
1475552998258917706756737045704649573088377604240716286977690565239187213744,
|
|
||||||
2413772448122400684309006716414417978370152271397082147158000439863002593561,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
392160855822256520519339260245328807036619920858503984710539815951012864164,
|
|
||||||
1075036996503791536261050742318169965707018400307026402939804424927087093987,
|
|
||||||
2176439430328703902070742432016450246365760303014562857296722712989275658921,
|
|
||||||
1413865976587623331051814207977382826721471106513581745229680113383908569693,
|
|
||||||
4879283427490523253696177116563427032332223531862961281430108575019551814,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3392583297537374046875199552977614390492290683707960975137418536812266544902,
|
|
||||||
3600854486849487646325182927019642276644093512133907046667282144129939150983,
|
|
||||||
2779924664161372134024229593301361846129279572186444474616319283535189797834,
|
|
||||||
2722699960903170449291146429799738181514821447014433304730310678334403972040,
|
|
||||||
819109815049226540285781191874507704729062681836086010078910930707209464699,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3046121243742768013822760785918001632929744274211027071381357122228091333823,
|
|
||||||
1339019590803056172509793134119156250729668216522001157582155155947567682278,
|
|
||||||
1933279639657506214789316403763326578443023901555983256955812717638093967201,
|
|
||||||
2138221547112520744699126051903811860205771600821672121643894708182292213541,
|
|
||||||
2694713515543641924097704224170357995809887124438248292930846280951601597065,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2471734202930133750093618989223585244499567111661178960753938272334153710615,
|
|
||||||
504903761112092757611047718215309856203214372330635774577409639907729993533,
|
|
||||||
1943979703748281357156510253941035712048221353507135074336243405478613241290,
|
|
||||||
684525210957572142559049112233609445802004614280157992196913315652663518936,
|
|
||||||
1705585400798782397786453706717059483604368413512485532079242223503960814508,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
192429517716023021556170942988476050278432319516032402725586427701913624665,
|
|
||||||
1586493702243128040549584165333371192888583026298039652930372758731750166765,
|
|
||||||
686072673323546915014972146032384917012218151266600268450347114036285993377,
|
|
||||||
3464340397998075738891129996710075228740496767934137465519455338004332839215,
|
|
||||||
2805249176617071054530589390406083958753103601524808155663551392362371834663,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
667746464250968521164727418691487653339733392025160477655836902744186489526,
|
|
||||||
1131527712905109997177270289411406385352032457456054589588342450404257139778,
|
|
||||||
1908969485750011212309284349900149072003218505891252313183123635318886241171,
|
|
||||||
1025257076985551890132050019084873267454083056307650830147063480409707787695,
|
|
||||||
2153175291918371429502545470578981828372846236838301412119329786849737957977,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3410257749736714576487217882785226905621212230027780855361670645857085424384,
|
|
||||||
3442969106887588154491488961893254739289120695377621434680934888062399029952,
|
|
||||||
3029953900235731770255937704976720759948880815387104275525268727341390470237,
|
|
||||||
85453456084781138713939104192561924536933417707871501802199311333127894466,
|
|
||||||
2730629666577257820220329078741301754580009106438115341296453318350676425129,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
178242450661072967256438102630920745430303027840919213764087927763335940415,
|
|
||||||
2844589222514708695700541363167856718216388819406388706818431442998498677557,
|
|
||||||
3547876269219141094308889387292091231377253967587961309624916269569559952944,
|
|
||||||
2525005406762984211707203144785482908331876505006839217175334833739957826850,
|
|
||||||
3096397013555211396701910432830904669391580557191845136003938801598654871345,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
574424067119200181933992948252007230348512600107123873197603373898923821490,
|
|
||||||
1714030696055067278349157346067719307863507310709155690164546226450579547098,
|
|
||||||
2339895272202694698739231405357972261413383527237194045718815176814132612501,
|
|
||||||
3562501318971895161271663840954705079797767042115717360959659475564651685069,
|
|
||||||
69069358687197963617161747606993436483967992689488259107924379545671193749,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2614502738369008850475068874731531583863538486212691941619835266611116051561,
|
|
||||||
655247349763023251625727726218660142895322325659927266813592114640858573566,
|
|
||||||
2305235672527595714255517865498269719545193172975330668070873705108690670678,
|
|
||||||
926416070297755413261159098243058134401665060349723804040714357642180531931,
|
|
||||||
866523735635840246543516964237513287099659681479228450791071595433217821460,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2284334068466681424919271582037156124891004191915573957556691163266198707693,
|
|
||||||
1812588309302477291425732810913354633465435706480768615104211305579383928792,
|
|
||||||
2836899808619013605432050476764608707770404125005720004551836441247917488507,
|
|
||||||
2989087789022865112405242078196235025698647423649950459911546051695688370523,
|
|
||||||
68056284404189102136488263779598243992465747932368669388126367131855404486,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
505425339250887519581119854377342241317528319745596963584548343662758204398,
|
|
||||||
2118963546856545068961709089296976921067035227488975882615462246481055679215,
|
|
||||||
2253872596319969096156004495313034590996995209785432485705134570745135149681,
|
|
||||||
1625090409149943603241183848936692198923183279116014478406452426158572703264,
|
|
||||||
179139838844452470348634657368199622305888473747024389514258107503778442495,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1567067018147735642071130442904093290030432522257811793540290101391210410341,
|
|
||||||
2737301854006865242314806979738760349397411136469975337509958305470398783585,
|
|
||||||
3002738216460904473515791428798860225499078134627026021350799206894618186256,
|
|
||||||
374029488099466837453096950537275565120689146401077127482884887409712315162,
|
|
||||||
973403256517481077805460710540468856199855789930951602150773500862180885363,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2691967457038172130555117632010860984519926022632800605713473799739632878867,
|
|
||||||
3515906794910381201365530594248181418811879320679684239326734893975752012109,
|
|
||||||
148057579455448384062325089530558091463206199724854022070244924642222283388,
|
|
||||||
1541588700238272710315890873051237741033408846596322948443180470429851502842,
|
|
||||||
147013865879011936545137344076637170977925826031496203944786839068852795297,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2630278389304735265620281704608245039972003761509102213752997636382302839857,
|
|
||||||
1359048670759642844930007747955701205155822111403150159614453244477853867621,
|
|
||||||
2438984569205812336319229336885480537793786558293523767186829418969842616677,
|
|
||||||
2137792255841525507649318539501906353254503076308308692873313199435029594138,
|
|
||||||
2262318076430740712267739371170174514379142884859595360065535117601097652755,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2792703718581084537295613508201818489836796608902614779596544185252826291584,
|
|
||||||
2294173715793292812015960640392421991604150133581218254866878921346561546149,
|
|
||||||
2770011224727997178743274791849308200493823127651418989170761007078565678171,
|
|
||||||
3321642244537785916275181932172303118112488081726311374164578600576901819844,
|
|
||||||
3522708517589950573320671158134804505970724681591943826922697952040487655044,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3417974441436557992524691506735790206623600049454586729879955931972546347402,
|
|
||||||
175039333145381316571259690443853067809784261609912638686739799135919647022,
|
|
||||||
1930713062131033273316869231148248962041053029742760224583505092759642967464,
|
|
||||||
2971452932574554603554350185069538580257636405419430340233233400633251319042,
|
|
||||||
2774781903758215341037075610938953949868289195845367046186588750871862784919,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
666516874137869653699423537799457099346460194092311952417454613224504932738,
|
|
||||||
1900462225013533249140457703727169176351786259991305560412832202759625668041,
|
|
||||||
2665631186082687279121709429531834469477679375137509769347092380798929714377,
|
|
||||||
837840745988147279235494664091280091563355097569199320366973125128366540061,
|
|
||||||
3391544118305848781823721719916289805455110924839794510205940718821197620955,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2888553035909938253628892138500390690221493345071933642853222968481016605919,
|
|
||||||
3386241569867597612447901482685846444743718781330869478721963580925825915450,
|
|
||||||
1205126220630896984850042596877918177217334376800874965105642874206963597698,
|
|
||||||
3590072615491710252422997155203204584659171612188004116415640739580250394190,
|
|
||||||
692469013329617220154003334549812915100479873898898958632988703738125356983,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1623178235190707102808841905143937367808788834203621005714003335195182126335,
|
|
||||||
1972826180775011489122426045504602288576507493792470102803637471568052321297,
|
|
||||||
3415141329098504418158191749675997877417539760075593313736376750580696083073,
|
|
||||||
587811537889727046473915684463981273175495137461951211739526104349163747811,
|
|
||||||
2523982964351069134084525951849317400231659428055762640605248929856135518199,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2686176526711834950207666047281383173339057216783586039351834948812568447629,
|
|
||||||
983144446441739425577690449774542566745526459152966545642451764143532586964,
|
|
||||||
171558252019175695567663688494555626159399786667979998273792882504784080805,
|
|
||||||
332337623010057542760158225837623039780806442976079546879646069338600179518,
|
|
||||||
1264669683963885571544813806669118319675288608634733888843804451222546848295,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2426165115815723668018318268486497504249785449504758403912155206515511627681,
|
|
||||||
11387399609384288947733630450855186629703576293221897150193655994854764608,
|
|
||||||
2541728569046079092074077754414781968906176513081761690404588216304985421091,
|
|
||||||
47685947554980329431290582269851186106577733250761848107645535357326439312,
|
|
||||||
472176388418187405374813530639596064799362505024895746833751173199773896628,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2764298116617383397920343358525617195195060562266243809245480210157942112738,
|
|
||||||
486863835068754002670800862273365477867695879270721744227071001883208334054,
|
|
||||||
2973492686137102577527656941792991264994301121122130295965761350095846874635,
|
|
||||||
178385615141132702906181473263873416748818415607305319148067639744074654009,
|
|
||||||
533624640096756667052211553746016402543259206286603356120804827761339634127,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
819406716720171922688026098737835227857400444543748198788964759773510472096,
|
|
||||||
531851793767260921861217458033110066464894334064526987603936107947006031387,
|
|
||||||
3269709072483585277009748181134917746036523619604017812342933951952104134829,
|
|
||||||
838191718603413598040249006803464503100808192944407407147899973659013630611,
|
|
||||||
1574561296941310904780257598780779812250055948216417844567262310524022037406,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
551394354289003977607664358739006072556227894953233419144430578080352094737,
|
|
||||||
445076790942318675726839050057337819004979443030540904213920669247413907302,
|
|
||||||
1963946696292687224902912968478695543164747600779913024040878700455222386521,
|
|
||||||
484284614181963381509745298932402076252103342403432879800905151752488144767,
|
|
||||||
2240507606126946994415203252302826782042951346966859379502140796364876543253,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3237135638753992982179886898758938279897590886053928839613434762582576319619,
|
|
||||||
2334333034701915027889533058426879447140084891006486138782876488162658230991,
|
|
||||||
14411091399844539897439754491034751977136685514851444574462584316609631592,
|
|
||||||
1264480371592407258420308876448697804787923638319277097663041109464608464284,
|
|
||||||
671929312763821646360589403212798993954209530574443543917757335777610372144,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2513909805455654095962542944994577107405216428214873444765576238504714067396,
|
|
||||||
870121102846043786263357605823753628974859886859187558617096145653709171231,
|
|
||||||
399132620893316356411986266679786708905730068946836982293484206366500277754,
|
|
||||||
2855046250836680633532995284655778407402587437073106249445470889390454667586,
|
|
||||||
2063679741125384345396981490971605710211281905716315529671473143278849561151,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1433753212258929925682201698758056443128516570551146995210728194816988328337,
|
|
||||||
3334984763425011856632257855270507440816274246647423607159847074739331865077,
|
|
||||||
337911293622078184850923533628334646725451591671907148383867096651211846605,
|
|
||||||
559587005295238702015018022040357402231957131094636365177008701077975941644,
|
|
||||||
885963059604819264377490633589388189646118257469490919900554134369512794660,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1957748763518471091057032383332840331641373304981058387824598000170709016333,
|
|
||||||
3175295982155056798972302481564899381103533409383494814704562889625572018450,
|
|
||||||
498987160612401618114584726510347771865331516606886613019084323862447372555,
|
|
||||||
947374835104260364630171441676101001841507588423166778786886198914150312958,
|
|
||||||
906933977754491302438795274167251538820934378773708095543613756654712689280,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2170116291766863179909957030577284618726490893598499117272497866180009722894,
|
|
||||||
1801335399574515889082584621772588704763181408217893911806726119813067220453,
|
|
||||||
1942500232535842474530840356353427989892065499159260166135596750084681859966,
|
|
||||||
62936080219825306823124060587235998278756755377419521154040408253893795176,
|
|
||||||
3091993939935137795359769774909373279950941171574748645375255810204590357753,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1283528386884634267663661033944552098742115012555712906773586466375284501324,
|
|
||||||
1581820717639229420476069802992937438655873471854930764425841549067913106065,
|
|
||||||
2301986095388751633126546121528329200085681648876910655269533407603441046514,
|
|
||||||
2850003828037698751961753862613545302539465803982364898225617297398939302949,
|
|
||||||
48024691078494936445046366770271288984930221238071705874025261821606393528,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1482336297033144958942154923925185950152551534403871620222916667536030875354,
|
|
||||||
3081177564717719643771186007689458633949181485535169123213511264603782950049,
|
|
||||||
3315701127039521853279746297714590495201061397709680410650043502532250578075,
|
|
||||||
3514407611000441301995070394422463400067690470546731164089622325748803106020,
|
|
||||||
368970178199930154322724953487299516224498421233447528815195701420122548537,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
584353160413525267849669053228533951552602295860601556035386665117717227391,
|
|
||||||
752038702160385294706011538400822066722189014251268673051846350397729870418,
|
|
||||||
3594041683498798688197194521326299097635429790757880308152971477196489335154,
|
|
||||||
1367902435756906062215608264424138718742854099315395230911274560900857414183,
|
|
||||||
1828549068951502746189364466794037234789986878381694857475972053743463890779,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
488172495141237210878388657234137733008417573114482400652274985829148564248,
|
|
||||||
962906242461930394022372340919543491337923491322497419797555620396501785566,
|
|
||||||
2275418085010046236619290386129138234541669589549771944697082317642065048898,
|
|
||||||
1966395064658902622886154686288219600816893261614483533899715888994623208964,
|
|
||||||
3496095878293416917311185659829821476802828534554531050412634978086916288609,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3368478822390537245916137403277928093536087427951052230723275731232142463388,
|
|
||||||
3397410259276620127103231993277518800970669191016277541098821699302368873803,
|
|
||||||
2662600899665871010006649609856695263727220473364611552472965243032255906029,
|
|
||||||
2854831720595596992200155718152374313555878203864206470581502555480894633975,
|
|
||||||
2417859092561967752135741161218626374900182454089059862468108240576782064037,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1064506915903089299531724594973601253341866933071158266140674053459433520889,
|
|
||||||
243845138053687262800349059300355289745206315347524675450796070948867090098,
|
|
||||||
1952653154963756062322124110012629666160000286707762177032475477295929736283,
|
|
||||||
2760979128531476595658428672038276216079708408852493051222686009638650156041,
|
|
||||||
3341178930260137001230946104398194306290005446746057811731360203227371301716,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1033242545866274439991875444609632860132556714736615395036273942261573810479,
|
|
||||||
3567973410830779135148598005871071456943945697865168835204985462698751038238,
|
|
||||||
23014034649293369426970379738102323014738017168969687350330825050016457105,
|
|
||||||
1146720508452451012445869043641390200263192255569203352823376998708972325392,
|
|
||||||
2553707028642376593497768606567528232999203496079990242456254686325586089356,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
269729857648436699208023125596593246149228245518586029792966091405383426269,
|
|
||||||
276912682886955358118649215147238115764108757952690361549816619060658800027,
|
|
||||||
2367180947887796341722261610916728725977893583923967218630363334645641817362,
|
|
||||||
2398694802751362950028137620758033447242325333923222365760836442417755445092,
|
|
||||||
984868389243025029364428136317275892280780834039611841422502834917752411391,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
861353329558771468244040268521983016756775808329676883407171471251365927595,
|
|
||||||
2498672969617384807617108262141800974986393948110233099680635130601163654234,
|
|
||||||
1336236634145657673540555267430353130305889434115514586892320600753700983325,
|
|
||||||
980337801407886250576371882962628290239239581416378379141354256717803603922,
|
|
||||||
2308558359523317875952657835109605515063994805873180719205156915762120497245,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2116737905426837141304542819940293184404010538896700217242374222514653607487,
|
|
||||||
2143995283326808680518644927890182524580312777400009071739277407358043120199,
|
|
||||||
3038758768133404431511594054950351369492648883179154555267474054094234927849,
|
|
||||||
981824005865625678985009911415023115269386212492064371040001594972137748141,
|
|
||||||
2427990511715778580869565219059895697855813782250850855111162965998948386792,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1987498156785173719076522405088076990979859292718600184358583152317049836167,
|
|
||||||
1633834915134208237423144264187482951766302060112099587851513525797020813799,
|
|
||||||
2895454976388515752029424688351979030650325184941524820409482023485820781526,
|
|
||||||
941019661238578826272324221721825852217063629464317974190162904813488515671,
|
|
||||||
2529926057929249454763690180607677568685011502604470585585763159431333258299,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2604831509257756199338105380847564711923112853239827243306562341166492672823,
|
|
||||||
2300475954087415591738767759767032267163723345312082546282694920273655145455,
|
|
||||||
1954000528502201000509342111010021527425422549437946241062907964768089317082,
|
|
||||||
1179936151696782249912570883839105595634344582873818018332922940963046083567,
|
|
||||||
3077707030301573630126144767923697288658782137457660869231140049571827937228,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1062324397142900251844488719868780667589966366756786302007970554437994421840,
|
|
||||||
353718609497993885193404630053532608155520921625518104461520254335222009911,
|
|
||||||
770557645309607171206012551080400276506165720184677119001983749356594531977,
|
|
||||||
3043628430985247363392058521341757139056029350680498644930013342982472853636,
|
|
||||||
1694968537785457252742656255724723357998402478572600479401200420305593921487,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
539865665379093791531434211889371819368504193082947002067781562776138072582,
|
|
||||||
3473466148775696692731190426971123680342615414200262605154732883324298196699,
|
|
||||||
482783534456196983135936103604928650836406142744767857356485953118411089098,
|
|
||||||
2389101033971236780034779577432189630800997581132154923233144722790749715251,
|
|
||||||
845264223568475649981141803833883014312596504303895519674002924871878791033,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3027004059915270231142566724881373969831662022738947178800901294120992473905,
|
|
||||||
2169574859350740480088697859610203373582027214052754592019828328614087431593,
|
|
||||||
3515527080764222354309565181793838292349410992793070639041305826153436624160,
|
|
||||||
1817926918350512904327755405973355211358017834277255662858654992240629698587,
|
|
||||||
1999148133619270973098477176176178514394558202995832714883251820350860287223,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1203131300029280096510929599113528018338088236684405405384757591977164161039,
|
|
||||||
336815403657101171302040383579077521911288747438919304948637997306314852594,
|
|
||||||
986661060847815533035934253464295060766339947679669645818832311132001095573,
|
|
||||||
2291116974939980228917916563988261327966840303336559854772343651559589512651,
|
|
||||||
3421243089992476528970346847858594146122972226790673723411896208702859892637,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1015505198663386486420800821559060487156096175034250154764824837183581949724,
|
|
||||||
1165880582987807286271819576391581724550686829511475839624601920297855380101,
|
|
||||||
904232961143172831178860280790910264843503022179578981166030973682571903458,
|
|
||||||
261322216292849827900157598748641385787016033372999683866859675894253115357,
|
|
||||||
3060676319159217735181388708455879854358158161989877552543698103915296690395,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1175560144527845912984609340783959238735643215413930887771084560168082442967,
|
|
||||||
2813871258576082360085006002528268796351819524936446195552260262614692343332,
|
|
||||||
1841341101531851399935829271555098629075809587212843292354556374386667658235,
|
|
||||||
3076135575511709688509914361447080149794919016880133063891720256749999834767,
|
|
||||||
753111801049754117414662684453226478940731922961768343984187479992842213733,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1405657437118503342762241742745888533114216548278983907019917904938403345580,
|
|
||||||
3111186124713876864436867307979940633543281080828379725576742174555539054855,
|
|
||||||
3404463650394703220454952017098727360005393139199301323890695570346564876407,
|
|
||||||
2024087816190101179456573591359233695334184711688920998987373624570170649371,
|
|
||||||
2770035625774572095496575568588054654502991645588385802705097377675051032967,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
437058215235292632621847481185406671372191763951486300610124033096831557414,
|
|
||||||
1345792773780982398809956395232061067669190682958320579442454533085407626029,
|
|
||||||
925357273912625669941681596445839316566672314870287993638671283923476231904,
|
|
||||||
3288133122086768300615066039539687885053110015077924175836976549020438910830,
|
|
||||||
666190075990703867784232802074474372379358766701681865975596503982238839889,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2664898601165892062970298960258838238925231697327906221693001926762280012052,
|
|
||||||
2075648691532387787722427044464731934171216054855867223374228487601569118337,
|
|
||||||
3173725544188532489243684991828985285646224157242834030308807120745121062293,
|
|
||||||
1517474443612606408422643323550409253700128234157734252330869178582583531320,
|
|
||||||
1593950878945144789965609248470060076911813704207225832606804796819386297511,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
141195541167651298813588829225208004611326987855926870823948793274702167509,
|
|
||||||
2990187949585642302497822222637786229364740008175968941859105979392907839776,
|
|
||||||
2893807105405820282316438050347503569385510241526138409321358916388308586443,
|
|
||||||
1379719211597875648759619903854862028510320482486109668868067715175935658353,
|
|
||||||
2702780364788282233075255946852944970202849869091427738791947810055591218061,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1825815734419326277729273926504439575157952821379179501821641713286627304656,
|
|
||||||
1481344458867016048625916723816339719872443766684158199301690902395849166360,
|
|
||||||
2014084774259125722186109781197998076881266739680534358898592778318128968629,
|
|
||||||
2612744185006548312909661512508122065214170543806989291921289897662387203493,
|
|
||||||
2486291022451231582267428921150634472835925206862678364689227838329114330247,
|
|
||||||
],
|
|
||||||
]
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,53 +0,0 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
|
||||||
import { describe, should } from 'micro-should';
|
|
||||||
import * as starknet from '../../lib/esm/stark.js';
|
|
||||||
import * as fc from 'fast-check';
|
|
||||||
|
|
||||||
const FC_BIGINT = fc.bigInt(1n + 1n, starknet.CURVE.n - 1n);
|
|
||||||
|
|
||||||
describe('starknet property', () => {
|
|
||||||
should('Point#toHex() roundtrip', () => {
|
|
||||||
fc.assert(
|
|
||||||
fc.property(FC_BIGINT, (x) => {
|
|
||||||
const point1 = starknet.ProjectivePoint.fromPrivateKey(x);
|
|
||||||
const hex = point1.toHex(true);
|
|
||||||
deepStrictEqual(starknet.ProjectivePoint.fromHex(hex).toHex(true), hex);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Signature.fromCompactHex() roundtrip', () => {
|
|
||||||
fc.assert(
|
|
||||||
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
|
|
||||||
const sig = new starknet.Signature(r, s);
|
|
||||||
deepStrictEqual(starknet.Signature.fromCompact(sig.toCompactHex()), sig);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Signature.fromDERHex() roundtrip', () => {
|
|
||||||
fc.assert(
|
|
||||||
fc.property(FC_BIGINT, FC_BIGINT, (r, s) => {
|
|
||||||
const sig = new starknet.Signature(r, s);
|
|
||||||
deepStrictEqual(starknet.Signature.fromDER(sig.toDERHex()), sig);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('verify()/should verify random signatures', () =>
|
|
||||||
fc.assert(
|
|
||||||
fc.property(FC_BIGINT, fc.hexaString({ minLength: 64, maxLength: 64 }), (privNum, msg) => {
|
|
||||||
const privKey = privNum.toString(16).padStart(64, '0');
|
|
||||||
const pub = starknet.getPublicKey(privKey);
|
|
||||||
const sig = starknet.sign(msg, privKey);
|
|
||||||
deepStrictEqual(starknet.verify(sig, msg, pub), true);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ESM is broken.
|
|
||||||
import url from 'url';
|
|
||||||
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
|
||||||
should.run();
|
|
||||||
}
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
import { deepStrictEqual, throws } from 'assert';
|
|
||||||
import { describe, should } from 'micro-should';
|
|
||||||
import { hex, utf8 } from '@scure/base';
|
|
||||||
import * as bip32 from '@scure/bip32';
|
|
||||||
import * as bip39 from '@scure/bip39';
|
|
||||||
import * as starknet from '../../lib/esm/stark.js';
|
|
||||||
import { default as sigVec } from './fixtures/rfc6979_signature_test_vector.json' assert { type: 'json' };
|
|
||||||
import { default as precomputedKeys } from './fixtures/keys_precomputed.json' assert { type: 'json' };
|
|
||||||
|
|
||||||
describe('starknet', () => {
|
|
||||||
should('custom keccak', () => {
|
|
||||||
const value = starknet.keccak(utf8.decode('hello'));
|
|
||||||
deepStrictEqual(value, 0x8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8n);
|
|
||||||
deepStrictEqual(value < 2n ** 250n, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('RFC6979', () => {
|
|
||||||
for (const msg of sigVec.messages) {
|
|
||||||
const { r, s } = starknet.sign(msg.hash, sigVec.private_key);
|
|
||||||
// const { r, s } = starknet.Signature.fromDER(sig);
|
|
||||||
deepStrictEqual(r.toString(10), msg.r);
|
|
||||||
deepStrictEqual(s.toString(10), msg.s);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Signatures', () => {
|
|
||||||
const vectors = [
|
|
||||||
{
|
|
||||||
// Message hash of length 61.
|
|
||||||
msg: 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47',
|
|
||||||
r: '5f496f6f210b5810b2711c74c15c05244dad43d18ecbbdbe6ed55584bc3b0a2',
|
|
||||||
s: '4e8657b153787f741a67c0666bad6426c3741b478c8eaa3155196fc571416f3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Message hash of length 61, with leading zeros.
|
|
||||||
msg: '00c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47',
|
|
||||||
r: '5f496f6f210b5810b2711c74c15c05244dad43d18ecbbdbe6ed55584bc3b0a2',
|
|
||||||
s: '4e8657b153787f741a67c0666bad6426c3741b478c8eaa3155196fc571416f3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Message hash of length 62.
|
|
||||||
msg: 'c465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47a',
|
|
||||||
r: '233b88c4578f0807b4a7480c8076eca5cfefa29980dd8e2af3c46a253490e9c',
|
|
||||||
s: '28b055e825bc507349edfb944740a35c6f22d377443c34742c04e0d82278cf1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Message hash of length 63.
|
|
||||||
msg: '7465dd6b1bbffdb05442eb17f5ca38ad1aa78a6f56bf4415bdee219114a47a1',
|
|
||||||
r: 'b6bee8010f96a723f6de06b5fa06e820418712439c93850dd4e9bde43ddf',
|
|
||||||
s: '1a3d2bc954ed77e22986f507d68d18115fa543d1901f5b4620db98e2f6efd80',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const privateKey = '2dccce1da22003777062ee0870e9881b460a8b7eca276870f57c601f182136c';
|
|
||||||
const publicKey = starknet.getPublicKey(privateKey);
|
|
||||||
for (const v of vectors) {
|
|
||||||
const sig = starknet.sign(v.msg, privateKey);
|
|
||||||
const { r, s } = sig;
|
|
||||||
// const { r, s } = starknet.Signature.fromDER(sig);
|
|
||||||
deepStrictEqual(r.toString(16), v.r, 'r equality');
|
|
||||||
deepStrictEqual(s.toString(16), v.s, 's equality');
|
|
||||||
deepStrictEqual(starknet.verify(sig, v.msg, publicKey), true, 'verify');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Invalid signatures', () => {
|
|
||||||
/*
|
|
||||||
|
|
||||||
it('should not verify invalid signature inputs lengths', () => {
|
|
||||||
const ecOrder = starkwareCrypto.ec.n;
|
|
||||||
const {maxEcdsaVal} = starkwareCrypto;
|
|
||||||
const maxMsgHash = maxEcdsaVal.sub(oneBn);
|
|
||||||
const maxR = maxEcdsaVal.sub(oneBn);
|
|
||||||
const maxS = ecOrder.sub(oneBn).sub(oneBn);
|
|
||||||
const maxStarkKey = maxEcdsaVal.sub(oneBn);
|
|
||||||
|
|
||||||
// Test invalid message length.
|
|
||||||
expect(() =>
|
|
||||||
starkwareCrypto.verify(maxStarkKey, maxMsgHash.add(oneBn).toString(16), {
|
|
||||||
r: maxR,
|
|
||||||
s: maxS
|
|
||||||
})
|
|
||||||
).to.throw('Message not signable, invalid msgHash length.');
|
|
||||||
// Test invalid r length.
|
|
||||||
expect(() =>
|
|
||||||
starkwareCrypto.verify(maxStarkKey, maxMsgHash.toString(16), {
|
|
||||||
r: maxR.add(oneBn),
|
|
||||||
s: maxS
|
|
||||||
})
|
|
||||||
).to.throw('Message not signable, invalid r length.');
|
|
||||||
// Test invalid w length.
|
|
||||||
expect(() =>
|
|
||||||
starkwareCrypto.verify(maxStarkKey, maxMsgHash.toString(16), {
|
|
||||||
r: maxR,
|
|
||||||
s: maxS.add(oneBn)
|
|
||||||
})
|
|
||||||
).to.throw('Message not signable, invalid w length.');
|
|
||||||
// Test invalid s length.
|
|
||||||
expect(() =>
|
|
||||||
starkwareCrypto.verify(maxStarkKey, maxMsgHash.toString(16), {
|
|
||||||
r: maxR,
|
|
||||||
s: maxS.add(oneBn).add(oneBn)
|
|
||||||
})
|
|
||||||
).to.throw('Message not signable, invalid s length.');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not verify invalid signatures', () => {
|
|
||||||
const privKey = generateRandomStarkPrivateKey();
|
|
||||||
const keyPair = starkwareCrypto.ec.keyFromPrivate(privKey, 'hex');
|
|
||||||
const keyPairPub = starkwareCrypto.ec.keyFromPublic(
|
|
||||||
keyPair.getPublic(),
|
|
||||||
'BN'
|
|
||||||
);
|
|
||||||
const msgHash = new BN(randomHexString(61));
|
|
||||||
const msgSignature = starkwareCrypto.sign(keyPair, msgHash);
|
|
||||||
|
|
||||||
// Test invalid public key.
|
|
||||||
const invalidKeyPairPub = starkwareCrypto.ec.keyFromPublic(
|
|
||||||
{x: keyPairPub.pub.getX().add(oneBn), y: keyPairPub.pub.getY()},
|
|
||||||
'BN'
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
starkwareCrypto.verify(
|
|
||||||
invalidKeyPairPub,
|
|
||||||
msgHash.toString(16),
|
|
||||||
msgSignature
|
|
||||||
)
|
|
||||||
).to.be.false;
|
|
||||||
// Test invalid message.
|
|
||||||
expect(
|
|
||||||
starkwareCrypto.verify(
|
|
||||||
keyPair,
|
|
||||||
msgHash.add(oneBn).toString(16),
|
|
||||||
msgSignature
|
|
||||||
)
|
|
||||||
).to.be.false;
|
|
||||||
expect(
|
|
||||||
starkwareCrypto.verify(
|
|
||||||
keyPairPub,
|
|
||||||
msgHash.add(oneBn).toString(16),
|
|
||||||
msgSignature
|
|
||||||
)
|
|
||||||
).to.be.false;
|
|
||||||
// Test invalid r.
|
|
||||||
msgSignature.r.iadd(oneBn);
|
|
||||||
expect(starkwareCrypto.verify(keyPair, msgHash.toString(16), msgSignature))
|
|
||||||
.to.be.false;
|
|
||||||
expect(
|
|
||||||
starkwareCrypto.verify(keyPairPub, msgHash.toString(16), msgSignature)
|
|
||||||
).to.be.false;
|
|
||||||
// Test invalid s.
|
|
||||||
msgSignature.r.isub(oneBn);
|
|
||||||
msgSignature.s.iadd(oneBn);
|
|
||||||
expect(starkwareCrypto.verify(keyPair, msgHash.toString(16), msgSignature))
|
|
||||||
.to.be.false;
|
|
||||||
expect(
|
|
||||||
starkwareCrypto.verify(keyPairPub, msgHash.toString(16), msgSignature)
|
|
||||||
).to.be.false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Pedersen', () => {
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.pedersen(
|
|
||||||
'0x3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb',
|
|
||||||
'0x208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a'
|
|
||||||
),
|
|
||||||
'0x30e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.pedersen(
|
|
||||||
'0x58f580910a6ca59b28927c08fe6c43e2e303ca384badc365795fc645d479d45',
|
|
||||||
'0x78734f65a067be9bdb39de18434d71e79f7b6466a4b66bbd979ab9e7515fe0b'
|
|
||||||
),
|
|
||||||
'0x68cc0b76cddd1dd4ed2301ada9b7c872b23875d5ff837b3a87993e0d9996b87'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Hash chain', () => {
|
|
||||||
deepStrictEqual(starknet.hashChain([1, 2, 3]), starknet.pedersen(1, starknet.pedersen(2, 3)));
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Key grinding', () => {
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.grindKey('86F3E7293141F20A8BAFF320E8EE4ACCB9D4A4BF2B4D295E8CEE784DB46E0519'),
|
|
||||||
'5c8c8683596c732541a59e03007b2d30dbbbb873556fe65b5fb63c16688f941'
|
|
||||||
);
|
|
||||||
// Loops more than once (verified manually)
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.grindKey('94F3E7293141F20A8BAFF320E8EE4ACCB9D4A4BF2B4D295E8CEE784DB46E0595'),
|
|
||||||
'33880b9aba464c1c01c9f8f5b4fc1134698f9b0a8d18505cab6cdd34d93dc02'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Private to stark key', () => {
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.getStarkKey('0x178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F'),
|
|
||||||
'0x1895a6a77ae14e7987b9cb51329a5adfb17bd8e7c638f92d6892d76e51cebcf'
|
|
||||||
);
|
|
||||||
for (const [privKey, expectedPubKey] of Object.entries(precomputedKeys)) {
|
|
||||||
deepStrictEqual(starknet.getStarkKey(privKey), expectedPubKey);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Private stark key from eth signature', () => {
|
|
||||||
const ethSignature =
|
|
||||||
'0x21fbf0696d5e0aa2ef41a2b4ffb623bcaf070461d61cf7251c74161f82fec3a43' +
|
|
||||||
'70854bc0a34b3ab487c1bc021cd318c734c51ae29374f2beb0e6f2dd49b4bf41c';
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.ethSigToPrivate(ethSignature),
|
|
||||||
'766f11e90cd7c7b43085b56da35c781f8c067ac0d578eabdceebc4886435bda'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
should('Key derivation', () => {
|
|
||||||
const layer = 'starkex';
|
|
||||||
const application = 'starkdeployement';
|
|
||||||
const mnemonic =
|
|
||||||
'range mountain blast problem vibrant void vivid doctor cluster enough melody ' +
|
|
||||||
'salt layer language laptop boat major space monkey unit glimpse pause change vibrant';
|
|
||||||
const ethAddress = '0xa4864d977b944315389d1765ffa7e66F74ee8cd7';
|
|
||||||
const VECTORS = [
|
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
path: "m/2645'/579218131'/891216374'/1961790679'/2135936222'/0",
|
|
||||||
privateKey: '6cf0a8bf113352eb863157a45c5e5567abb34f8d32cddafd2c22aa803f4892c',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
index: 7,
|
|
||||||
path: "m/2645'/579218131'/891216374'/1961790679'/2135936222'/7",
|
|
||||||
privateKey: '341751bdc42841da35ab74d13a1372c1f0250617e8a2ef96034d9f46e6847af',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
index: 598,
|
|
||||||
path: "m/2645'/579218131'/891216374'/1961790679'/2135936222'/598",
|
|
||||||
privateKey: '41a4d591a868353d28b7947eb132aa4d00c4a022743689ffd20a3628d6ca28c',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const hd = bip32.HDKey.fromMasterSeed(bip39.mnemonicToSeedSync(mnemonic));
|
|
||||||
for (const { index, path, privateKey } of VECTORS) {
|
|
||||||
const realPath = starknet.getAccountPath(layer, application, ethAddress, index);
|
|
||||||
deepStrictEqual(realPath, path);
|
|
||||||
deepStrictEqual(starknet.grindKey(hd.derive(realPath).privateKey), privateKey);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verified against starknet.js
|
|
||||||
should('Starknet.js cross-tests', () => {
|
|
||||||
const privateKey = '0x019800ea6a9a73f94aee6a3d2edf018fc770443e90c7ba121e8303ec6b349279';
|
|
||||||
// NOTE: there is no compressed keys here, getPubKey returns stark-key (which is schnorr-like X coordinate)
|
|
||||||
// But it is not used in signing/verifying
|
|
||||||
deepStrictEqual(
|
|
||||||
starknet.getStarkKey(privateKey),
|
|
||||||
'0x33f45f07e1bd1a51b45fc24ec8c8c9908db9e42191be9e169bfcac0c0d99745'
|
|
||||||
);
|
|
||||||
const msgHash = '0x6d1706bd3d1ba7c517be2a2a335996f63d4738e2f182144d078a1dd9997062e';
|
|
||||||
const sig = starknet.sign(msgHash, privateKey);
|
|
||||||
const { r, s } = sig;
|
|
||||||
|
|
||||||
deepStrictEqual(
|
|
||||||
r.toString(),
|
|
||||||
'1427981024487605678086498726488552139932400435436186597196374630267616399345'
|
|
||||||
);
|
|
||||||
deepStrictEqual(
|
|
||||||
s.toString(),
|
|
||||||
'1853664302719670721837677288395394946745467311923401353018029119631574115563'
|
|
||||||
);
|
|
||||||
const hashMsg2 = starknet.pedersen(
|
|
||||||
'0x33f45f07e1bd1a51b45fc24ec8c8c9908db9e42191be9e169bfcac0c0d99745',
|
|
||||||
'1'
|
|
||||||
);
|
|
||||||
deepStrictEqual(hashMsg2, '0x2b0d4d43acce8ff68416f667f92ec7eab2b96f1d2224abd4d9d4d1e7fa4bb00');
|
|
||||||
const pubKey =
|
|
||||||
'04033f45f07e1bd1a51b45fc24ec8c8c9908db9e42191be9e169bfcac0c0d997450319d0f53f6ca077c4fa5207819144a2a4165daef6ee47a7c1d06c0dcaa3e456';
|
|
||||||
const sig2 = new starknet.Signature(
|
|
||||||
558858382392827003930138586379728730695763862039474863361948210004201119180n,
|
|
||||||
2440689354481625417078677634625227600823892606910345662891037256374285369343n
|
|
||||||
);
|
|
||||||
deepStrictEqual(starknet.verify(sig2.toDERHex(), hashMsg2, pubKey), true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ESM is broken.
|
|
||||||
import url from 'url';
|
|
||||||
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
|
|
||||||
should.run();
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"outDir": "lib/esm",
|
"outDir": "esm",
|
||||||
"target": "es2020",
|
"target": "es2020",
|
||||||
"module": "es6",
|
"module": "es6",
|
||||||
"moduleResolution": "node16",
|
"moduleResolution": "node16",
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@noble/hashes/crypto": [ "src/crypto" ]
|
"@noble/hashes/crypto": [ "src/crypto" ]
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"outDir": "lib",
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": ".",
|
||||||
"target": "es2020",
|
"target": "es2020",
|
||||||
"lib": ["es2020"], // Set explicitly to remove DOM
|
"lib": ["es2020"], // Set explicitly to remove DOM
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
|||||||
Reference in New Issue
Block a user