forked from tornado-packages/noble-curves
hash-to-curve, weierstrass, bls, ed: upgrade h2c comments to rfc 9380
This commit is contained in:
parent
e7ac5e85d3
commit
eb8e7ec964
33
README.md
33
README.md
@ -9,8 +9,7 @@ Audited & minimal JS implementation of elliptic curve cryptography.
|
||||
- ➰ Short Weierstrass, Edwards, Montgomery curves
|
||||
- ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
|
||||
- 🔖 SUF-CMA and SBS (non-repudiation) for ed25519, ed448 and others
|
||||
- #️⃣ Hash-to-curve
|
||||
for encoding or hashing an arbitrary string to an elliptic curve point
|
||||
- #️⃣ hash-to-curve for encoding or hashing an arbitrary string to an elliptic curve point
|
||||
- 🧜♂️ Poseidon ZK-friendly hash
|
||||
|
||||
### This library belongs to _noble_ crypto
|
||||
@ -676,7 +675,7 @@ utils: {
|
||||
|
||||
### 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 [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
|
||||
|
||||
Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security:
|
||||
|
||||
@ -692,19 +691,17 @@ 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)).
|
||||
Low-level methods from the spec:
|
||||
|
||||
```ts
|
||||
// produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
|
||||
function expand_message_xmd(
|
||||
msg: Uint8Array,
|
||||
DST: Uint8Array,
|
||||
lenInBytes: number,
|
||||
H: CHash
|
||||
H: CHash // For CHash see abstract/weierstrass docs section
|
||||
): Uint8Array;
|
||||
// produces a uniformly random byte string using an extendable-output function (XOF) H.
|
||||
function expand_message_xof(
|
||||
msg: Uint8Array,
|
||||
DST: Uint8Array,
|
||||
@ -712,13 +709,9 @@ function expand_message_xof(
|
||||
k: number,
|
||||
H: CHash
|
||||
): Uint8Array;
|
||||
```
|
||||
// Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
|
||||
function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][];
|
||||
|
||||
`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.
|
||||
|
||||
```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
|
||||
@ -736,16 +729,6 @@ type Opts = {
|
||||
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[][];
|
||||
```
|
||||
|
||||
### abstract/poseidon: Poseidon hash
|
||||
|
@ -59,7 +59,7 @@ function isNum(item: unknown): void {
|
||||
}
|
||||
|
||||
// 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://www.rfc-editor.org/rfc/rfc9380#section-5.3.1
|
||||
export function expand_message_xmd(
|
||||
msg: Uint8Array,
|
||||
DST: Uint8Array,
|
||||
@ -69,7 +69,7 @@ export function expand_message_xmd(
|
||||
isBytes(msg);
|
||||
isBytes(DST);
|
||||
isNum(lenInBytes);
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
||||
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
||||
if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
|
||||
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
|
||||
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
||||
@ -88,6 +88,11 @@ export function expand_message_xmd(
|
||||
return pseudo_random_bytes.slice(0, lenInBytes);
|
||||
}
|
||||
|
||||
// Produces a uniformly random byte string using an extendable-output function (XOF) H.
|
||||
// 1. The collision resistance of H MUST be at least k bits.
|
||||
// 2. H MUST be an XOF that has been proved indifferentiable from
|
||||
// a random oracle under a reasonable cryptographic assumption.
|
||||
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2
|
||||
export function expand_message_xof(
|
||||
msg: Uint8Array,
|
||||
DST: Uint8Array,
|
||||
@ -98,7 +103,7 @@ export function expand_message_xof(
|
||||
isBytes(msg);
|
||||
isBytes(DST);
|
||||
isNum(lenInBytes);
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
||||
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
||||
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
||||
if (DST.length > 255) {
|
||||
const dkLen = Math.ceil((2 * k) / 8);
|
||||
@ -119,7 +124,7 @@ export function expand_message_xof(
|
||||
|
||||
/**
|
||||
* 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
|
||||
* https://www.rfc-editor.org/rfc/rfc9380#section-5.2
|
||||
* @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
|
||||
@ -201,8 +206,8 @@ export function createHasher<T>(
|
||||
) {
|
||||
if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined');
|
||||
return {
|
||||
// Encodes byte string to elliptic curve
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
||||
// Encodes byte string to elliptic curve.
|
||||
// hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3
|
||||
hashToCurve(msg: Uint8Array, options?: htfBasicOpts) {
|
||||
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts);
|
||||
const u0 = Point.fromAffine(mapToCurve(u[0]));
|
||||
@ -212,7 +217,8 @@ export function createHasher<T>(
|
||||
return P;
|
||||
},
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
|
||||
// Encodes byte string to elliptic curve.
|
||||
// encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3
|
||||
encodeToCurve(msg: Uint8Array, options?: htfBasicOpts) {
|
||||
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts);
|
||||
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
||||
|
@ -1171,7 +1171,8 @@ export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
|
||||
return sqrtRatio;
|
||||
}
|
||||
/**
|
||||
* From draft-irtf-cfrg-hash-to-curve-16
|
||||
* Simplified Shallue-van de Woestijne-Ulas Method
|
||||
* https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2
|
||||
*/
|
||||
export function mapToCurveSimpleSWU<T>(
|
||||
Fp: mod.IField<T>,
|
||||
|
@ -8,8 +8,8 @@
|
||||
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
|
||||
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
|
||||
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
|
||||
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
|
||||
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).
|
||||
// [bls-sigs-04](https:/cfrg-hash-to/tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
|
||||
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf--curve-12).
|
||||
//
|
||||
// ### Summary
|
||||
// 1. BLS Relies on Bilinear Pairing (expensive)
|
||||
@ -177,7 +177,7 @@ const Fp2: mod.IField<Fp2> & Fp2Utils = {
|
||||
if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1;
|
||||
return x2;
|
||||
},
|
||||
// Same as sgn0_fp2 in draft-irtf-cfrg-hash-to-curve-16
|
||||
// Same as sgn0_m_eq_2 in RFC 9380
|
||||
isOdd: (x: Fp2) => {
|
||||
const { re: x0, im: x1 } = Fp2.reim(x);
|
||||
const sign_0 = x0 % _2n;
|
||||
@ -780,8 +780,7 @@ const FP12_FROBENIUS_COEFFICIENTS = [
|
||||
|
||||
// HashToCurve
|
||||
|
||||
// 3-isogeny map from E' to E
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-E.3
|
||||
// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3
|
||||
const isogenyMapG2 = isogenyMap(
|
||||
Fp2,
|
||||
[
|
||||
@ -985,7 +984,7 @@ function G2psi2(c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) {
|
||||
//
|
||||
// Parameter definitions are in section 5.3 of the spec unless otherwise noted.
|
||||
// Parameter values come from section 8.8.2 of the spec.
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.8.2
|
||||
// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2
|
||||
//
|
||||
// Base field F is GF(p^m)
|
||||
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
||||
@ -1040,7 +1039,7 @@ function signatureG2ToRawBytes(point: ProjPointType<Fp2>) {
|
||||
}
|
||||
|
||||
// To verify curve parameters, see pairing-friendly-curves spec:
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-09
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11
|
||||
// Basic math is done over finite fields over p.
|
||||
// More complicated math is done over polynominal extension fields.
|
||||
// To simplify calculations in Fp12, we construct extension tower:
|
||||
|
@ -478,8 +478,7 @@ export const RistrettoPoint = /* @__PURE__ */ (() => {
|
||||
return RistPoint;
|
||||
})();
|
||||
|
||||
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/
|
||||
// Appendix B. Hashing to ristretto255
|
||||
// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B
|
||||
export const hashToRistretto255 = (msg: Uint8Array, options: htfBasicOpts) => {
|
||||
const d = options.DST;
|
||||
const DST = typeof d === 'string' ? utf8ToBytes(d) : d;
|
||||
|
@ -69,7 +69,7 @@ function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
|
||||
// Uses algo from RFC8032 5.1.3.
|
||||
function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } {
|
||||
const P = ed448P;
|
||||
// https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.3
|
||||
// https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3
|
||||
// To compute the square root of (u/v), the first step is to compute the
|
||||
// candidate root x = (u/v)^((p+1)/4). This can be done using the
|
||||
// following trick, to use a single modular powering for both the
|
||||
@ -454,8 +454,7 @@ export const DecafPoint = /* @__PURE__ */ (() => {
|
||||
return DcfPoint;
|
||||
})();
|
||||
|
||||
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/16/
|
||||
// Appendix C. Hashing to decaf448
|
||||
// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C
|
||||
export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts) => {
|
||||
const d = options.DST;
|
||||
const DST = typeof d === 'string' ? utf8ToBytes(d) : d;
|
||||
|
Loading…
Reference in New Issue
Block a user