5 Commits
0.8.2 ... 0.8.3

Author SHA1 Message Date
Paul Miller
1c6aa07ff7 Release 0.8.3. 2023-03-16 19:41:20 +01:00
Paul Miller
e110237298 readme 2023-03-16 19:17:34 +01:00
Paul Miller
45393db807 Bump docs 2023-03-16 19:05:33 +01:00
Paul Miller
acc3a9dc4d Bump devdep types/node 2023-03-16 18:52:03 +01:00
Paul Miller
9295b0dbae Upgrade to Typescript 5 2023-03-16 18:49:48 +01:00
3 changed files with 213 additions and 158 deletions

299
README.md
View File

@@ -9,20 +9,27 @@
for encoding or hashing an arbitrary string to an elliptic curve point 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 with Wycheproof vectors and [cryptofuzz](https://github.com/guidovranken/cryptofuzz) differential fuzzing - 🔍 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](#abstract-api), zero-dependency EC algorithms 1. [Abstract](#abstract-api), zero-dependency EC algorithms
2. [Implementations](#implementations), utilizing one dependency `@noble/hashes`, providing ready-to-use: 2. [Implementations](#implementations), utilizing one dependency `@noble/hashes`,
providing ready-to-use:
- NIST curves 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 - ed25519/curve25519/x25519/ristretto255, edwards448/curve448/x448
implementing
[RFC7748](https://www.rfc-editor.org/rfc/rfc7748) /
[RFC8032](https://www.rfc-editor.org/rfc/rfc8032) /
[ZIP215](https://zips.z.cash/zip-0215) standards
- pairing-friendly curves bls12-381, bn254 - pairing-friendly curves bls12-381, bn254
Check out [Upgrading](#upgrading) if you've previously used single-feature noble packages Check out [Upgrading](#upgrading) if you've previously used single-feature noble
([secp256k1](https://github.com/paulmillr/noble-secp256k1), [ed25519](https://github.com/paulmillr/noble-ed25519)). packages ([secp256k1](https://github.com/paulmillr/noble-secp256k1),
[ed25519](https://github.com/paulmillr/noble-ed25519)).
See [Resources](#resources) for articles and real-world software that uses curves. See [Resources](#resources) for articles and real-world software that uses curves.
### This library belongs to _noble_ crypto ### This library belongs to _noble_ crypto
@@ -41,22 +48,25 @@ See [Resources](#resources) for articles and real-world software that uses curve
## Usage ## Usage
Use NPM for browser / node.js: Browser, deno and node.js are supported:
> npm install @noble/curves > npm install @noble/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 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). [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'`. The library is tree-shaking-friendly and does not expose root entry point as
Instead, you need to import specific primitives. This is done to ensure small size of your apps. `import * from '@noble/curves'`. Instead, you need to import specific primitives.
This is done to ensure small size of your apps.
### Implementations ### Implementations
Each curve can be used in the following way: Each curve can be used in the following way:
```ts ```ts
import { secp256k1 } from '@noble/curves/secp256k1'; // ECMAScript Modules (ESM) and Common.js import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno // import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
const priv = secp256k1.utils.randomPrivateKey(); const priv = secp256k1.utils.randomPrivateKey();
const pub = secp256k1.getPublicKey(priv); const pub = secp256k1.getPublicKey(priv);
@@ -64,8 +74,9 @@ const msg = new Uint8Array(32).fill(1);
const sig = secp256k1.sign(msg, priv); const sig = secp256k1.sign(msg, priv);
secp256k1.verify(sig, msg, pub) === true; secp256k1.verify(sig, msg, pub) === true;
// hex strings are also supported besides Uint8Arrays:
const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236'; const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236';
const pub2 = secp256k1.getPublicKey(privHex); // keys & other inputs can be Uint8Array-s or hex strings const pub2 = secp256k1.getPublicKey(privHex);
``` ```
All curves: All curves:
@@ -90,7 +101,7 @@ Weierstrass curves feature recovering public keys from signatures and ECDH key a
const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true }); const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true });
sig.recoverPublicKey(msg) === pub; // public key recovery sig.recoverPublicKey(msg) === pub; // public key recovery
const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey()); const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH (elliptic curve diffie-hellman) const shared = secp256k1.getSharedSecret(priv, someonesPub); // ECDH
``` ```
secp256k1 has schnorr signature implementation which follows secp256k1 has schnorr signature implementation which follows
@@ -103,7 +114,6 @@ const pub = schnorr.getPublicKey(priv);
const msg = new TextEncoder().encode('hello'); const msg = new TextEncoder().encode('hello');
const sig = schnorr.sign(msg, priv); const sig = schnorr.sign(msg, priv);
const isValid = schnorr.verify(sig, msg, pub); const isValid = schnorr.verify(sig, msg, pub);
console.log(isValid);
``` ```
ed25519 module has ed25519ctx / ed25519ph variants, ed25519 module has ed25519ctx / ed25519ph variants,
@@ -134,18 +144,20 @@ RistrettoPoint.hashToCurve('Ristretto is traditionally a short shot of espresso
// also has add(), equals(), multiply(), toRawBytes() methods // also has add(), equals(), multiply(), toRawBytes() methods
``` ```
ed448 module is basically the same: ed448 is similar:
```ts ```ts
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448';
import { hashToCurve, encodeToCurve } from '@noble/curves/ed448'; import { hashToCurve, encodeToCurve } from '@noble/curves/ed448';
ed448.getPublicKey(ed448.utils.randomPrivateKey());
``` ```
BLS12-381 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](https://z.cash/technology/zksnarks/) at the 128-bit security construct [zk-SNARKs](https://z.cash/technology/zksnarks/) at the 128-bit security
and use aggregated, batch-verifiable and use aggregated, batch-verifiable
[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716), [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
using Boneh-Lynn-Shacham signature scheme. using Boneh-Lynn-Shacham signature scheme. Compatible with ETH and others,
just make sure to provide correct DST (domain separation tag argument).
```ts ```ts
import { bls12_381 as bls } from '@noble/curves/bls12-381'; import { bls12_381 as bls } from '@noble/curves/bls12-381';
@@ -182,10 +194,13 @@ console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
## Abstract API ## Abstract API
Abstract API allows to define custom curves. All arithmetics is done with JS bigints over finite fields, Abstract API allows to define custom curves. All arithmetics is done with JS
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/). bigints over finite fields, which is defined from `modular` sub-module. For
Precomputes are enabled for weierstrass and edwards BASE points of a curve. You could precompute any scalar multiplication, we use
other point (e.g. for ECDH) using `utils.precompute()` method: check out examples. [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: There are following zero-dependency algorithms:
@@ -201,14 +216,34 @@ There are following zero-dependency algorithms:
```ts ```ts
import { weierstrass } from '@noble/curves/abstract/weierstrass'; import { weierstrass } from '@noble/curves/abstract/weierstrass';
import { Fp } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics
import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash
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({
// secq256k1: cycle of secp256k1 with Fp/N flipped.
// https://personaelabs.org/posts/spartan-ecdsa
// https://zcash.github.io/halo2/background/curves.html#cycles-of-curves
a: 0n,
b: 7n,
Fp: Fp(2n ** 256n - 432420386565659656852420866394968145599n),
n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
hash: sha256,
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
randomBytes,
});
``` ```
Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass` expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h` 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. and coordinates `Gx`, `Gy` of generator point.
**`k` generation** is done deterministically, following [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). **`k` generation** is done deterministically, following
For this you will need `hmac` & `hash`, which in our implementations is provided by noble-hashes. [RFC6979](https://www.rfc-editor.org/rfc/rfc6979). For this you will need
If you're using different hashing library, make sure to wrap it in the following interface: `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
type CHash = { type CHash = {
@@ -224,11 +259,35 @@ type CHash = {
1. Exported as `ProjectivePoint` 1. Exported as `ProjectivePoint`
2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) 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 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()` 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 5. Have `assertValidity()` which checks for being on-curve
6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates 6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates
```ts ```ts
// `weierstrass()` returns `CurveFn`
type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array };
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; 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>;
};
};
// T is usually bigint, but can be something else like complex numbers in BLS curves // T is usually bigint, but can be something else like complex numbers in BLS curves
interface ProjPointType<T> extends Group<ProjPointType<T>> { interface ProjPointType<T> extends Group<ProjPointType<T>> {
readonly px: T; readonly px: T;
@@ -254,7 +313,8 @@ interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {
} }
``` ```
**ECDSA signatures** are represented by `Signature` instances and can be described by the interface: **ECDSA signatures** are represented by `Signature` instances and can be
described by the interface:
```ts ```ts
interface SignatureType { interface SignatureType {
@@ -279,28 +339,9 @@ type SignatureConstructor = {
}; };
``` ```
Example implementing [secq256k1](https://personaelabs.org/posts/spartan-ecdsa) (NOT secp256k1) More examples:
[cycle](https://zcash.github.io/halo2/background/curves.html#cycles-of-curves) of secp256k1 with Fp/N flipped.
```typescript ```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({
// secq256k1: cycle of secp256k1 with Fp/N flipped.
a: 0n,
b: 7n,
Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n),
n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
hash: sha256,
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
randomBytes,
});
// All curves expose same generic interface. // All curves expose same generic interface.
const priv = secq256k1.utils.randomPrivateKey(); const priv = secq256k1.utils.randomPrivateKey();
secq256k1.getPublicKey(priv); // Convert private key to public. secq256k1.getPublicKey(priv); // Convert private key to public.
@@ -326,33 +367,34 @@ const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey));
fast.multiply(privKey); // much faster ECDH now fast.multiply(privKey); // much faster ECDH now
``` ```
`weierstrass()` returns `CurveFn`: ### abstract/edwards: Twisted Edwards curve
```ts ```ts
type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array }; import { twistedEdwards } from '@noble/curves/abstract/edwards';
type CurveFn = { import { Fp } from '@noble/curves/abstract/modular';
CURVE: ReturnType<typeof validateOpts>; import { sha512 } from '@noble/hashes/sha512';
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array; import { randomBytes } from '@noble/hashes/utils';
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>;
};
};
```
### abstract/edwards: Twisted Edwards curve const fp = Fp(2n ** 255n - 19n);
const ed25519 = twistedEdwards({
a: -1n,
d: fp.div(-121665n, 121666n), // -121665n/121666n mod p
Fp: fp,
n: 2n ** 252n + 27742317777372353535851937790883648493n,
h: 8n,
Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
hash: sha512,
randomBytes,
adjustScalarBytes(bytes) {
// optional; but mandatory in ed25519
bytes[0] &= 248;
bytes[31] &= 127;
bytes[31] |= 64;
return bytes;
},
} as const);
```
Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h` 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. and coordinates `Gx`, `Gy` of generator point.
@@ -370,6 +412,25 @@ For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs
7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions 7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions
```ts ```ts
// `twistedEdwards()` returns `CurveFn` of following type:
type CurveFn = {
CURVE: ReturnType<typeof validateOpts>;
getPublicKey: (privateKey: Hex) => Uint8Array;
sign: (message: Hex, privateKey: Hex, context?: Hex) => Uint8Array;
verify: (sig: SigType, message: Hex, publicKey: Hex, context?: Hex) => boolean;
ExtendedPoint: ExtPointConstructor;
utils: {
randomPrivateKey: () => Uint8Array;
getExtendedPublicKey: (key: PrivKey) => {
head: Uint8Array;
prefix: Uint8Array;
scalar: bigint;
point: PointType;
pointBytes: Uint8Array;
};
};
};
interface ExtPointType extends Group<ExtPointType> { interface ExtPointType extends Group<ExtPointType> {
readonly ex: bigint; readonly ex: bigint;
readonly ey: bigint; readonly ey: bigint;
@@ -392,67 +453,14 @@ interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
} }
``` ```
Example implementing edwards25519:
```ts
import { twistedEdwards } from '@noble/curves/abstract/edwards';
import { Field, div } from '@noble/curves/abstract/modular';
import { sha512 } from '@noble/hashes/sha512';
const Fp = Field(2n ** 255n - 19n);
const ed25519 = twistedEdwards({
a: -1n,
d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p
Fp,
n: 2n ** 252n + 27742317777372353535851937790883648493n,
h: 8n,
Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
hash: sha512,
randomBytes,
adjustScalarBytes(bytes) {
// optional; but mandatory in ed25519
bytes[0] &= 248;
bytes[31] &= 127;
bytes[31] |= 64;
return bytes;
},
} as const);
```
`twistedEdwards()` returns `CurveFn` of following type:
```ts
type CurveFn = {
CURVE: ReturnType<typeof validateOpts>;
getPublicKey: (privateKey: Hex) => Uint8Array;
sign: (message: Hex, privateKey: Hex, context?: Hex) => Uint8Array;
verify: (sig: SigType, message: Hex, publicKey: Hex, context?: Hex) => boolean;
ExtendedPoint: ExtPointConstructor;
utils: {
randomPrivateKey: () => Uint8Array;
getExtendedPublicKey: (key: PrivKey) => {
head: Uint8Array;
prefix: Uint8Array;
scalar: bigint;
point: PointType;
pointBytes: Uint8Array;
};
};
};
```
### abstract/montgomery: Montgomery curve ### abstract/montgomery: Montgomery curve
The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748. Proper Elliptic Curve Points are not implemented yet.
You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
```typescript ```typescript
import { montgomery } from '@noble/curves/abstract/montgomery'; import { montgomery } from '@noble/curves/abstract/montgomery';
import { Fp } from '@noble/curves/abstract/modular';
const x25519 = montgomery({ const x25519 = montgomery({
Fp: Field(2n ** 255n - 19n), Fp: Fp(2n ** 255n - 19n),
a: 486662n, a: 486662n,
Gu: 9n, Gu: 9n,
montgomeryBits: 255, montgomeryBits: 255,
@@ -467,6 +475,11 @@ const x25519 = montgomery({
}); });
``` ```
The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748.
Proper Elliptic Curve Points are not implemented yet.
You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`.
### 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. Implements [hash-to-curve v16](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16). 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).
@@ -507,19 +520,37 @@ function expand_message_xof(
): 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
- `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
/**
* * `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;
type Opts = {
DST: UnicodeOrBytes;
p: bigint;
m: number;
k: number;
expand?: 'xmd' | 'xof';
hash: CHash;
};
/**
* Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
* @param msg a byte string containing the message to hash
* @param count the number of elements of F to output
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
*/
function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][]; function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
``` ```

62
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@noble/curves", "name": "@noble/curves",
"version": "0.8.0", "version": "0.8.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@noble/curves", "name": "@noble/curves",
"version": "0.8.0", "version": "0.8.3",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -15,23 +15,23 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@noble/hashes": "1.2.0" "@noble/hashes": "1.3.0"
}, },
"devDependencies": { "devDependencies": {
"@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.18",
"fast-check": "3.0.0", "fast-check": "3.0.0",
"micro-bmark": "0.3.1", "micro-bmark": "0.3.1",
"micro-should": "0.4.0", "micro-should": "0.4.0",
"prettier": "2.8.3", "prettier": "2.8.4",
"typescript": "4.7.3" "typescript": "5.0.2"
} }
}, },
"node_modules/@noble/hashes": { "node_modules/@noble/hashes": {
"version": "1.2.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz",
"integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -80,6 +80,18 @@
"@scure/base": "~1.1.0" "@scure/base": "~1.1.0"
} }
}, },
"node_modules/@scure/bip32/node_modules/@noble/hashes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz",
"integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@scure/bip39": { "node_modules/@scure/bip39": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz",
@@ -96,10 +108,22 @@
"@scure/base": "~1.1.0" "@scure/base": "~1.1.0"
} }
}, },
"node_modules/@scure/bip39/node_modules/@noble/hashes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz",
"integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.11.3", "version": "18.11.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
"integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
"dev": true "dev": true
}, },
"node_modules/fast-check": { "node_modules/fast-check": {
@@ -131,9 +155,9 @@
"dev": true "dev": true
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.8.3", "version": "2.8.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz",
"integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==",
"dev": true, "dev": true,
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin-prettier.js"
@@ -162,16 +186,16 @@
] ]
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.7.3", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz",
"integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
}, },
"engines": { "engines": {
"node": ">=4.2.0" "node": ">=12.20"
} }
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@noble/curves", "name": "@noble/curves",
"version": "0.8.2", "version": "0.8.3",
"description": "Minimal, auditable JS implementation of elliptic curve cryptography", "description": "Minimal, auditable JS implementation of elliptic curve cryptography",
"files": [ "files": [
"abstract", "abstract",
@@ -28,17 +28,17 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@noble/hashes": "1.2.0" "@noble/hashes": "1.3.0"
}, },
"devDependencies": { "devDependencies": {
"@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.18",
"fast-check": "3.0.0", "fast-check": "3.0.0",
"micro-bmark": "0.3.1", "micro-bmark": "0.3.1",
"micro-should": "0.4.0", "micro-should": "0.4.0",
"prettier": "2.8.3", "prettier": "2.8.4",
"typescript": "4.7.3" "typescript": "5.0.2"
}, },
"main": "index.js", "main": "index.js",
"exports": { "exports": {