forked from tornado-packages/noble-curves
README, lint
This commit is contained in:
parent
0277c01efd
commit
ba121ff24c
186
README.md
186
README.md
@ -10,11 +10,16 @@ Minimal, zero-dependency JS implementation of elliptic curve cryptography.
|
|||||||
- 🔻 Helps JS bundlers with lack of entry point, ensures small size of your app
|
- 🔻 Helps JS bundlers with lack of entry point, ensures small size of your app
|
||||||
- 🔍 Unique tests ensure correctness. Wycheproof vectors included
|
- 🔍 Unique tests ensure correctness. Wycheproof vectors included
|
||||||
|
|
||||||
To keep the package minimal, no curve definitions are provided out-of-box. Use `micro-curve-definitions` module:
|
No curve definitions are provided out-of-box. Use separate package `micro-curve-definitions`:
|
||||||
|
|
||||||
- It provides P192, P224, P256, P384, P521, secp256k1, stark, bn254, pasta (pallas/vesta), ed25519, ed448 & bls12-381 curves
|
- It provides:
|
||||||
- Main reason for separate package is the fact hashing library (like @noble/hashes) is required for full functionality
|
- NIST curves secp192r1/P192, secp224r1/P224, secp256r1/P256, secp384r1/P384, secp521r1/P521
|
||||||
- We may reconsider merging packages in future, when a stable version would be ready
|
- SECG curve secp256k1
|
||||||
|
- bls12-381, bn254 pairing-friendly curves
|
||||||
|
- ed25519/curve25519/x25519/ristretto, edwards448/curve448/x448 RFC7748 / RFC8032 / ZIP215 stuff
|
||||||
|
- It allows to keep the main library minimal, zero-dependency.
|
||||||
|
m-c-d depends on a hashing library `@noble/hashes`
|
||||||
|
- Packages may be merged later, once a stable version is ready
|
||||||
|
|
||||||
The goal for the near future is to update previous packages
|
The goal for the near future is to update previous packages
|
||||||
([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
([secp256k1](https://github.com/paulmillr/noble-secp256k1),
|
||||||
@ -45,7 +50,8 @@ Use NPM in node.js / browser, or include single file from
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
|
import { Fp } from '@noble/curves/modular';
|
||||||
|
import { weierstrass } from '@noble/curves/weierstrass';
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
import { hmac } from '@noble/hashes/hmac';
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
@ -53,8 +59,8 @@ import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|||||||
const secp256k1 = weierstrass({
|
const secp256k1 = weierstrass({
|
||||||
a: 0n,
|
a: 0n,
|
||||||
b: 7n,
|
b: 7n,
|
||||||
P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
|
Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
|
||||||
n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
|
n: 2n ** 256n - 432420386565659656852420866394968145599n,
|
||||||
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
||||||
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
||||||
hash: sha256,
|
hash: sha256,
|
||||||
@ -65,10 +71,10 @@ const key = secp256k1.utils.randomPrivateKey();
|
|||||||
const pub = secp256k1.getPublicKey(key);
|
const pub = secp256k1.getPublicKey(key);
|
||||||
const msg = randomBytes(32);
|
const msg = randomBytes(32);
|
||||||
const sig = secp256k1.sign(msg, key);
|
const sig = secp256k1.sign(msg, key);
|
||||||
secp256k1.verify(sig, msg, pub); // true
|
secp256k1.verify(sig, msg, pub) === true;
|
||||||
sig.recoverPublicKey(msg); // == pub
|
sig.recoverPublicKey(msg) === pub;
|
||||||
const someonesPubkey = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
|
||||||
const shared = secp256k1.getSharedSecret(key, someonesPubkey);
|
const shared = secp256k1.getSharedSecret(key, someonesPub);
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
@ -86,9 +92,9 @@ const shared = secp256k1.getSharedSecret(key, someonesPubkey);
|
|||||||
* All curves expose same generic interface:
|
* All curves expose same generic interface:
|
||||||
* `getPublicKey()`, `sign()`, `verify()` functions
|
* `getPublicKey()`, `sign()`, `verify()` functions
|
||||||
* `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
|
* `Point` conforming to `Group` interface with add/multiply/double/negate/add/equals methods
|
||||||
* `CURVE` object with curve variables like `Gx`, `Gy`, `P` (field), `n` (order)
|
* `CURVE` object with curve variables like `Gx`, `Gy`, `Fp` (field), `n` (order)
|
||||||
* `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
|
* `utils` object with `randomPrivateKey()`, `mod()`, `invert()` methods (`mod CURVE.P`)
|
||||||
* All arithmetics is done with JS bigints over finite fields
|
* 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.
|
* 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:
|
Any other library must conform to the CHash interface:
|
||||||
```ts
|
```ts
|
||||||
@ -99,19 +105,19 @@ const shared = secp256k1.getSharedSecret(key, someonesPubkey);
|
|||||||
```
|
```
|
||||||
* w-ary non-adjacent form (wNAF) method with constant-time adjustments is used for point multiplication.
|
* 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.
|
It is possible to enable precomputes for edwards & weierstrass curves.
|
||||||
Precomputes are calculated once (takes ~20-40ms), after that most `G` multiplications
|
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.
|
for example, `getPublicKey()`, `sign()` and similar methods - would be much faster.
|
||||||
Use `curve.utils.precompute()`
|
Use `curve.utils.precompute()` to adjust precomputation window size
|
||||||
* Special params that tune performance can be optionally provided. For example:
|
* You could use optional special params to tune performance:
|
||||||
* `sqrtMod` square root calculation, used for point decompression
|
* `Fp({sqrt})` square root calculation, used for point decompression
|
||||||
* `endo` endomorphism options for Koblitz curves
|
* `endo` endomorphism options for Koblitz curves
|
||||||
|
|
||||||
### edwards: Twisted Edwards curve
|
### 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 curve params `a`, `d`, field `P`, 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, params `hash` is also 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
|
```typescript
|
||||||
import { twistedEdwards } from '@noble/curves/edwards'; // Twisted Edwards curve
|
import { twistedEdwards } from '@noble/curves/edwards'; // Twisted Edwards curve
|
||||||
@ -128,14 +134,18 @@ const ed25519 = twistedEdwards({
|
|||||||
Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
|
Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
|
||||||
hash: sha512,
|
hash: sha512,
|
||||||
randomBytes,
|
randomBytes,
|
||||||
adjustScalarBytes(bytes) { // optional
|
adjustScalarBytes(bytes) { // optional in general, 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);
|
||||||
ed25519.getPublicKey(ed25519.utils.randomPrivateKey());
|
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:
|
||||||
@ -195,23 +205,23 @@ const x25519 = montgomery({
|
|||||||
|
|
||||||
Short Weierstrass curve's formula is: y² = x³ + ax + b. Uses deterministic ECDSA from RFC6979. You can also specify `extraEntropy` in `sign()`.
|
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 `P`; curve order `n`; coordinates `Gx`, `Gy` of generator point
|
* 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 ECDSA, you must specify `hash`, `hmac`. It is also possible to recover keys from signatures
|
||||||
* For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
|
* For ECDH, use `getSharedSecret(privKeyA, pubKeyB)`
|
||||||
* Optional params are `lowS` (default value), `sqrtMod` (square root chain) and `endo` (endomorphism)
|
* Optional params are `lowS` (default value) and `endo` (endomorphism)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
import { Fp } from '@noble/curves/modular';
|
||||||
import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
|
import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
|
||||||
import { sha256 } from '@noble/hashes/sha256';
|
import { sha256 } from '@noble/hashes/sha256';
|
||||||
import { hmac } from '@noble/hashes/hmac';
|
import { hmac } from '@noble/hashes/hmac';
|
||||||
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
||||||
|
|
||||||
const secp256k1 = weierstrass({
|
const secp256k1 = weierstrass({
|
||||||
// Required params
|
|
||||||
a: 0n,
|
a: 0n,
|
||||||
b: 7n,
|
b: 7n,
|
||||||
P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
|
Fp: Fp(2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n),
|
||||||
n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
|
n: 2n ** 256n - 432420386565659656852420866394968145599n,
|
||||||
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
|
||||||
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
|
||||||
hash: sha256,
|
hash: sha256,
|
||||||
@ -219,19 +229,14 @@ const secp256k1 = weierstrass({
|
|||||||
randomBytes,
|
randomBytes,
|
||||||
|
|
||||||
// Optional params
|
// Optional params
|
||||||
// Cofactor
|
h: 1n, // Cofactor
|
||||||
h: BigInt(1),
|
lowS: true, // Allow only low-S signatures by default in sign() and verify()
|
||||||
// Allow only low-S signatures by default in sign() and verify()
|
endo: { // Endomorphism options for Koblitz curve
|
||||||
lowS: true,
|
|
||||||
// More efficient curve-specific implementation of square root
|
|
||||||
sqrtMod(y: bigint) { return sqrt(y); },
|
|
||||||
// Endomorphism options
|
|
||||||
endo: {
|
|
||||||
// Beta param
|
// Beta param
|
||||||
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
beta: 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501een,
|
||||||
// Split scalar k into k1, k2
|
// Split scalar k into k1, k2
|
||||||
splitScalar: (k: bigint) => {
|
splitScalar: (k: bigint) => {
|
||||||
return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
|
// return { k1neg: true, k1: 512n, k2neg: false, k2: 448n };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -262,8 +267,8 @@ export type CurveFn = {
|
|||||||
ProjectivePoint: ProjectivePointConstructor;
|
ProjectivePoint: ProjectivePointConstructor;
|
||||||
Signature: SignatureConstructor;
|
Signature: SignatureConstructor;
|
||||||
utils: {
|
utils: {
|
||||||
mod: (a: bigint, b?: bigint) => bigint;
|
mod: (a: bigint) => bigint;
|
||||||
invert: (number: bigint, modulo?: bigint) => bigint;
|
invert: (number: bigint) => bigint;
|
||||||
isValidPrivateKey(privateKey: PrivKey): boolean;
|
isValidPrivateKey(privateKey: PrivKey): boolean;
|
||||||
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
hashToPrivateKey: (hash: Hex) => Uint8Array;
|
||||||
randomPrivateKey: () => Uint8Array;
|
randomPrivateKey: () => Uint8Array;
|
||||||
@ -276,12 +281,15 @@ export type CurveFn = {
|
|||||||
Modular arithmetics utilities.
|
Modular arithmetics utilities.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import * as mod from '@noble/curves/modular';
|
import { mod, invert, div, invertBatch, sqrt, Fp } from '@noble/curves/modular';
|
||||||
mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
|
mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
|
||||||
mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
|
invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
|
||||||
mod.div(5n, 17n, 10n); // 5/17 mod 10 == 5 * invert(17) mod 10; division
|
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
|
||||||
mod.sqrt(21n, 73n); // sqrt(21) mod 73; square root
|
sqrt(21n, 73n); // √21 mod 73; square root
|
||||||
|
const fp = Fp(2n ** 255n - 19n); // Finite field over 2^255-19
|
||||||
|
fp.mul(591n, 932n);
|
||||||
|
fp.pow(481n, 11024858120n);
|
||||||
```
|
```
|
||||||
|
|
||||||
### utils
|
### utils
|
||||||
@ -316,59 +324,43 @@ We consider infrastructure attacks like rogue NPM modules very important; that's
|
|||||||
Benchmark results on Apple M2 with node v18.10:
|
Benchmark results on Apple M2 with node v18.10:
|
||||||
|
|
||||||
```
|
```
|
||||||
==== secp256k1 ====
|
getPublicKey
|
||||||
- getPublicKey1 (samples: 10000)
|
secp256k1 x 5,241 ops/sec @ 190μs/op
|
||||||
noble_old x 8,131 ops/sec @ 122μs/op
|
P256 x 7,993 ops/sec @ 125μs/op
|
||||||
secp256k1 x 7,374 ops/sec @ 135μs/op
|
P384 x 3,819 ops/sec @ 261μs/op
|
||||||
- getPublicKey255 (samples: 10000)
|
P521 x 2,074 ops/sec @ 481μs/op
|
||||||
noble_old x 7,894 ops/sec @ 126μs/op
|
ed25519 x 8,390 ops/sec @ 119μs/op
|
||||||
secp256k1 x 7,327 ops/sec @ 136μs/op
|
ed448 x 3,224 ops/sec @ 310μs/op
|
||||||
- sign (samples: 5000)
|
sign
|
||||||
noble_old x 5,243 ops/sec @ 190μs/op
|
secp256k1 x 3,934 ops/sec @ 254μs/op
|
||||||
secp256k1 x 4,834 ops/sec @ 206μs/op
|
P256 x 5,327 ops/sec @ 187μs/op
|
||||||
- getSharedSecret (samples: 1000)
|
P384 x 2,728 ops/sec @ 366μs/op
|
||||||
noble_old x 653 ops/sec @ 1ms/op
|
P521 x 1,594 ops/sec @ 626μs/op
|
||||||
secp256k1 x 634 ops/sec @ 1ms/op
|
ed25519 x 4,233 ops/sec @ 236μs/op
|
||||||
- verify (samples: 1000)
|
ed448 x 1,561 ops/sec @ 640μs/op
|
||||||
secp256k1_old x 1,038 ops/sec @ 962μs/op
|
verify
|
||||||
secp256k1 x 1,009 ops/sec @ 990μs/op
|
secp256k1 x 731 ops/sec @ 1ms/op
|
||||||
==== ed25519 ====
|
P256 x 806 ops/sec @ 1ms/op
|
||||||
- getPublicKey (samples: 10000)
|
P384 x 353 ops/sec @ 2ms/op
|
||||||
old x 8,632 ops/sec @ 115μs/op
|
P521 x 171 ops/sec @ 5ms/op
|
||||||
noble x 8,390 ops/sec @ 119μs/op
|
ed25519 x 860 ops/sec @ 1ms/op
|
||||||
- sign (samples: 5000)
|
ed448 x 313 ops/sec @ 3ms/op
|
||||||
old x 4,376 ops/sec @ 228μs/op
|
getSharedSecret
|
||||||
noble x 4,233 ops/sec @ 236μs/op
|
secp256k1 x 445 ops/sec @ 2ms/op
|
||||||
- verify (samples: 1000)
|
recoverPublicKey
|
||||||
old x 865 ops/sec @ 1ms/op
|
secp256k1 x 732 ops/sec @ 1ms/op
|
||||||
noble x 860 ops/sec @ 1ms/op
|
==== bls12-381 ====
|
||||||
==== ed448 ====
|
getPublicKey x 817 ops/sec @ 1ms/op
|
||||||
- getPublicKey (samples: 5000)
|
sign x 50 ops/sec @ 19ms/op
|
||||||
noble x 3,224 ops/sec @ 310μs/op
|
verify x 34 ops/sec @ 28ms/op
|
||||||
- sign (samples: 2500)
|
pairing x 89 ops/sec @ 11ms/op
|
||||||
noble x 1,561 ops/sec @ 640μs/op
|
|
||||||
- verify (samples: 500)
|
|
||||||
noble x 313 ops/sec @ 3ms/op
|
|
||||||
==== nist ====
|
|
||||||
- getPublicKey (samples: 2500)
|
|
||||||
P256 x 7,993 ops/sec @ 125μs/op
|
|
||||||
P384 x 3,819 ops/sec @ 261μs/op
|
|
||||||
P521 x 2,074 ops/sec @ 481μs/op
|
|
||||||
- sign (samples: 1000)
|
|
||||||
P256 x 5,327 ops/sec @ 187μs/op
|
|
||||||
P384 x 2,728 ops/sec @ 366μs/op
|
|
||||||
P521 x 1,594 ops/sec @ 626μs/op
|
|
||||||
- verify (samples: 250)
|
|
||||||
P256 x 806 ops/sec @ 1ms/op
|
|
||||||
P384 x 353 ops/sec @ 2ms/op
|
|
||||||
P521 x 171 ops/sec @ 5ms/op
|
|
||||||
==== stark ====
|
==== stark ====
|
||||||
- pedersen (samples: 500)
|
pedersen
|
||||||
old x 85 ops/sec @ 11ms/op
|
old x 85 ops/sec @ 11ms/op
|
||||||
noble x 1,216 ops/sec @ 822μs/op
|
noble x 1,216 ops/sec @ 822μs/op
|
||||||
- verify (samples: 500)
|
verify
|
||||||
old x 302 ops/sec @ 3ms/op
|
old x 302 ops/sec @ 3ms/op
|
||||||
noble x 698 ops/sec @ 1ms/op
|
noble x 698 ops/sec @ 1ms/op
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing & testing
|
## Contributing & testing
|
||||||
|
@ -2,14 +2,6 @@
|
|||||||
|
|
||||||
Elliptic curves implementations. `@noble/curves` is zero-dependency library for internal arithmetics.
|
Elliptic curves implementations. `@noble/curves` is zero-dependency library for internal arithmetics.
|
||||||
|
|
||||||
`micro-curve-definitions` is the actual implementations. Current functionality:
|
|
||||||
|
|
||||||
- NIST curves: P192, P224, P256, P384, P521 (ECDSA)
|
|
||||||
- secp256k1 (ECDSA, without Schnorr)
|
|
||||||
- stark curve
|
|
||||||
- bls12-381
|
|
||||||
- bn254
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
@ -243,9 +243,7 @@ const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => {
|
|||||||
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
|
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
|
||||||
c0: Fp2.add(
|
c0: Fp2.add(
|
||||||
t0,
|
t0,
|
||||||
Fp2.mulByNonresidue(
|
Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2)))
|
||||||
Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
|
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
|
||||||
c1: Fp2.add(
|
c1: Fp2.add(
|
||||||
@ -318,10 +316,7 @@ const Fp6: mod.Field<Fp6> & Fp6Utils = {
|
|||||||
let t2 = Fp2.sub(Fp2.square(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
|
let t2 = Fp2.sub(Fp2.square(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
|
||||||
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
||||||
let t4 = Fp2.invert(
|
let t4 = Fp2.invert(
|
||||||
Fp2.add(
|
Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0))
|
||||||
Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))),
|
|
||||||
Fp2.mul(c0, t0)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
||||||
},
|
},
|
||||||
@ -568,10 +563,7 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
|
|||||||
return {
|
return {
|
||||||
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
|
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
|
||||||
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
||||||
c1: Fp6.sub(
|
c1: Fp6.sub(Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
|
||||||
Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0),
|
|
||||||
t1
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
multiplyByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({
|
multiplyByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({
|
||||||
@ -624,20 +616,14 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
|
|||||||
const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2);
|
const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2);
|
||||||
const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x));
|
const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x));
|
||||||
const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x));
|
const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x));
|
||||||
const t6 = Fp12.mul(
|
const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2));
|
||||||
Fp12.conjugate(Fp12._cyclotomicExp(t5, x)),
|
|
||||||
Fp12._cyclotomicSquare(t2)
|
|
||||||
);
|
|
||||||
const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x));
|
const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x));
|
||||||
const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2);
|
const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2);
|
||||||
const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3);
|
const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3);
|
||||||
const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1);
|
const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1);
|
||||||
const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1);
|
const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1);
|
||||||
// (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1
|
// (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1
|
||||||
return Fp12.mul(
|
return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1);
|
||||||
Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1),
|
|
||||||
t7_t3c_t1
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const FP12_FROBENIUS_COEFFICIENTS = [
|
const FP12_FROBENIUS_COEFFICIENTS = [
|
||||||
@ -897,10 +883,7 @@ function map_to_curve_simple_swu_9mod16(t: bigint[] | Fp2): [Fp2, Fp2] {
|
|||||||
let v = Fp2.pow(denominator, 3n);
|
let v = Fp2.pow(denominator, 3n);
|
||||||
// u = N³ + a * N * D² + b * D³
|
// u = N³ + a * N * D² + b * D³
|
||||||
let u = Fp2.add(
|
let u = Fp2.add(
|
||||||
Fp2.add(
|
Fp2.add(Fp2.pow(numerator, 3n), Fp2.mul(Fp2.mul(iso_3_a, numerator), Fp2.pow(denominator, 2n))),
|
||||||
Fp2.pow(numerator, 3n),
|
|
||||||
Fp2.mul(Fp2.mul(iso_3_a, numerator), Fp2.pow(denominator, 2n))
|
|
||||||
),
|
|
||||||
Fp2.mul(iso_3_b, v)
|
Fp2.mul(iso_3_b, v)
|
||||||
);
|
);
|
||||||
// Attempt y = sqrt(u / v)
|
// Attempt y = sqrt(u / v)
|
||||||
|
@ -3,7 +3,7 @@ import { sha512 } from '@noble/hashes/sha512';
|
|||||||
import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils';
|
import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils';
|
||||||
import { twistedEdwards, ExtendedPointType } from '@noble/curves/edwards';
|
import { twistedEdwards, ExtendedPointType } from '@noble/curves/edwards';
|
||||||
import { montgomery } from '@noble/curves/montgomery';
|
import { montgomery } from '@noble/curves/montgomery';
|
||||||
import { mod, pow2, isNegativeLE, Fp as FpFn } from '@noble/curves/modular';
|
import { mod, pow2, isNegativeLE, Fp } from '@noble/curves/modular';
|
||||||
import {
|
import {
|
||||||
ensureBytes,
|
ensureBytes,
|
||||||
equalBytes,
|
equalBytes,
|
||||||
@ -98,7 +98,7 @@ const ED25519_DEF = {
|
|||||||
// Negative number is P - number, and division is invert(number, P)
|
// Negative number is P - number, and division is invert(number, P)
|
||||||
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
|
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
|
||||||
// Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
|
// Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
|
||||||
Fp: FpFn(ED25519_P),
|
Fp: Fp(ED25519_P),
|
||||||
// Subgroup order: how many points ed25519 has
|
// Subgroup order: how many points ed25519 has
|
||||||
// 2n ** 252n + 27742317777372353535851937790883648493n;
|
// 2n ** 252n + 27742317777372353535851937790883648493n;
|
||||||
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
|
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*! @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 FpFn, mod, pow2 } from '@noble/curves/modular';
|
import { Fp, mod, pow2 } from '@noble/curves/modular';
|
||||||
import { createCurve } from './_shortw_utils.js';
|
import { createCurve } from './_shortw_utils.js';
|
||||||
import { PointType } from '@noble/curves/weierstrass';
|
import { PointType } from '@noble/curves/weierstrass';
|
||||||
import {
|
import {
|
||||||
@ -58,7 +58,7 @@ function sqrtMod(y: bigint): bigint {
|
|||||||
return pow2(t2, _2n, P);
|
return pow2(t2, _2n, P);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Fp = FpFn(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
|
const fp = Fp(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
|
||||||
|
|
||||||
export const secp256k1 = createCurve(
|
export const secp256k1 = createCurve(
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ export const secp256k1 = createCurve(
|
|||||||
b: BigInt(7),
|
b: BigInt(7),
|
||||||
// Field over which we'll do calculations;
|
// Field over which we'll do calculations;
|
||||||
// 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
// 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
||||||
Fp,
|
Fp: fp,
|
||||||
// Curve order, total count of valid points in the field
|
// Curve order, total count of valid points in the field
|
||||||
n: secp256k1N,
|
n: secp256k1N,
|
||||||
// Base point (x, y) aka generator point
|
// Base point (x, y) aka generator point
|
||||||
|
Loading…
Reference in New Issue
Block a user