forked from tornado-packages/noble-curves
hash-to-curve: assertValidity
This commit is contained in:
parent
69b3ab5a57
commit
4ef2cad685
@ -11,6 +11,7 @@
|
|||||||
* We are using Fp for private keys (shorter) and Fp₂ for signatures (longer).
|
* We are using Fp for private keys (shorter) and Fp₂ for signatures (longer).
|
||||||
* Some projects may prefer to swap this relation, it is not supported for now.
|
* Some projects may prefer to swap this relation, it is not supported for now.
|
||||||
*/
|
*/
|
||||||
|
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, hexToBytes, bytesToHex } from './utils.js';
|
||||||
import * as htf from './hash-to-curve.js';
|
import * as htf from './hash-to-curve.js';
|
||||||
@ -19,7 +20,6 @@ import {
|
|||||||
ProjPointType as ProjPointType,
|
ProjPointType as ProjPointType,
|
||||||
CurvePointsRes,
|
CurvePointsRes,
|
||||||
weierstrassPoints,
|
weierstrassPoints,
|
||||||
AffinePoint,
|
|
||||||
} from './weierstrass.js';
|
} from './weierstrass.js';
|
||||||
|
|
||||||
type Fp = bigint; // Can be different field?
|
type Fp = bigint; // Can be different field?
|
||||||
|
@ -4,6 +4,11 @@ import { Field, validateField, nLength } from './modular.js';
|
|||||||
const _0n = BigInt(0);
|
const _0n = BigInt(0);
|
||||||
const _1n = BigInt(1);
|
const _1n = BigInt(1);
|
||||||
|
|
||||||
|
export type AffinePoint<T> = {
|
||||||
|
x: T;
|
||||||
|
y: T;
|
||||||
|
} & { z?: never; t?: never };
|
||||||
|
|
||||||
export interface Group<T extends Group<T>> {
|
export interface Group<T extends Group<T>> {
|
||||||
double(): T;
|
double(): T;
|
||||||
negate(): T;
|
negate(): T;
|
||||||
|
@ -10,7 +10,14 @@ import {
|
|||||||
Hex,
|
Hex,
|
||||||
numberToBytesLE,
|
numberToBytesLE,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
import { Group, GroupConstructor, wNAF, AbstractCurve, validateAbsOpts } from './curve.js';
|
import {
|
||||||
|
Group,
|
||||||
|
GroupConstructor,
|
||||||
|
wNAF,
|
||||||
|
AbstractCurve,
|
||||||
|
validateAbsOpts,
|
||||||
|
AffinePoint,
|
||||||
|
} from './curve.js';
|
||||||
|
|
||||||
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
|
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
|
||||||
const _0n = BigInt(0);
|
const _0n = BigInt(0);
|
||||||
@ -28,7 +35,7 @@ export type CurveType = AbstractCurve<bigint> & {
|
|||||||
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array; // Used for hashing
|
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array; // Used for hashing
|
||||||
uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint }; // Ratio √(u/v)
|
uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint }; // Ratio √(u/v)
|
||||||
preHash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
|
preHash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
|
||||||
mapToCurve?: (scalar: bigint[]) => AffinePoint; // for hash-to-curve standard
|
mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>; // for hash-to-curve standard
|
||||||
};
|
};
|
||||||
|
|
||||||
function validateOpts(curve: CurveType) {
|
function validateOpts(curve: CurveType) {
|
||||||
@ -49,29 +56,24 @@ function validateOpts(curve: CurveType) {
|
|||||||
return Object.freeze({ ...opts } as const);
|
return Object.freeze({ ...opts } as const);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2d point in XY coords
|
|
||||||
export type AffinePoint = {
|
|
||||||
x: bigint;
|
|
||||||
y: bigint;
|
|
||||||
} & { z?: never; t?: never };
|
|
||||||
|
|
||||||
// Instance of Extended Point with coordinates in X, Y, Z, T
|
// Instance of Extended Point with coordinates in X, Y, Z, T
|
||||||
export interface ExtPointType extends Group<ExtPointType> {
|
export interface ExtPointType extends Group<ExtPointType> {
|
||||||
readonly ex: bigint;
|
readonly ex: bigint;
|
||||||
readonly ey: bigint;
|
readonly ey: bigint;
|
||||||
readonly ez: bigint;
|
readonly ez: bigint;
|
||||||
readonly et: bigint;
|
readonly et: bigint;
|
||||||
|
assertValidity(): void;
|
||||||
multiply(scalar: bigint): ExtPointType;
|
multiply(scalar: bigint): ExtPointType;
|
||||||
multiplyUnsafe(scalar: bigint): ExtPointType;
|
multiplyUnsafe(scalar: bigint): ExtPointType;
|
||||||
isSmallOrder(): boolean;
|
isSmallOrder(): boolean;
|
||||||
isTorsionFree(): boolean;
|
isTorsionFree(): boolean;
|
||||||
toAffine(iz?: bigint): AffinePoint;
|
|
||||||
clearCofactor(): ExtPointType;
|
clearCofactor(): ExtPointType;
|
||||||
|
toAffine(iz?: bigint): AffinePoint<bigint>;
|
||||||
}
|
}
|
||||||
// Static methods of Extended Point with coordinates in X, Y, Z, T
|
// Static methods of Extended Point with coordinates in X, Y, Z, T
|
||||||
export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
|
export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
|
||||||
new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
|
new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
|
||||||
fromAffine(p: AffinePoint): ExtPointType;
|
fromAffine(p: AffinePoint<bigint>): ExtPointType;
|
||||||
fromHex(hex: Hex): ExtPointType;
|
fromHex(hex: Hex): ExtPointType;
|
||||||
fromPrivateKey(privateKey: Hex): ExtPointType; // TODO: remove
|
fromPrivateKey(privateKey: Hex): ExtPointType; // TODO: remove
|
||||||
}
|
}
|
||||||
@ -159,7 +161,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
return this.toAffine().y;
|
return this.toAffine().y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromAffine(p: AffinePoint): Point {
|
static fromAffine(p: AffinePoint<bigint>): Point {
|
||||||
if (p instanceof Point) throw new Error('extended point not allowed');
|
if (p instanceof Point) throw new Error('extended point not allowed');
|
||||||
const { x, y } = p || {};
|
const { x, y } = p || {};
|
||||||
if (!in0MaskRange(x) || !in0MaskRange(y)) throw new Error('invalid affine point');
|
if (!in0MaskRange(x) || !in0MaskRange(y)) throw new Error('invalid affine point');
|
||||||
@ -181,6 +183,8 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
pointPrecomputes.delete(this);
|
pointPrecomputes.delete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertValidity(): void {}
|
||||||
|
|
||||||
// Compare one point to another.
|
// Compare one point to another.
|
||||||
equals(other: Point): boolean {
|
equals(other: Point): boolean {
|
||||||
isPoint(other);
|
isPoint(other);
|
||||||
@ -309,7 +313,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
|
|
||||||
// Converts Extended point to default (x, y) coordinates.
|
// Converts Extended point to default (x, y) coordinates.
|
||||||
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
||||||
toAffine(iz?: bigint): AffinePoint {
|
toAffine(iz?: bigint): AffinePoint<bigint> {
|
||||||
const { ex: x, ey: y, ez: z } = this;
|
const { ex: x, ey: y, ez: z } = this;
|
||||||
const is0 = this.is0();
|
const is0 = this.is0();
|
||||||
if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint); // 8 was chosen arbitrarily
|
if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint); // 8 was chosen arbitrarily
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||||
import type { Group, GroupConstructor } 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 } from './utils.js';
|
import { CHash, Hex, concatBytes, ensureBytes } from './utils.js';
|
||||||
|
|
||||||
@ -182,11 +182,11 @@ export function isogenyMap<T, F extends Field<T>>(field: F, map: [T[], T[], T[],
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type AffinePoint<T> = { x: T; y: T };
|
|
||||||
export interface H2CPoint<T> extends Group<H2CPoint<T>> {
|
export interface H2CPoint<T> extends Group<H2CPoint<T>> {
|
||||||
add(rhs: H2CPoint<T>): H2CPoint<T>;
|
add(rhs: H2CPoint<T>): H2CPoint<T>;
|
||||||
toAffine(iz?: bigint): AffinePoint<T>;
|
toAffine(iz?: bigint): AffinePoint<T>;
|
||||||
clearCofactor(): H2CPoint<T>;
|
clearCofactor(): H2CPoint<T>;
|
||||||
|
assertValidity(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface H2CPointConstructor<T> extends GroupConstructor<H2CPoint<T>> {
|
export interface H2CPointConstructor<T> extends GroupConstructor<H2CPoint<T>> {
|
||||||
@ -216,9 +216,11 @@ export function hashToCurve<T>(
|
|||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
||||||
msg = ensureBytes(msg);
|
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);
|
||||||
return Point.fromAffine(mapToCurve(u[0]))
|
const P = Point.fromAffine(mapToCurve(u[0]))
|
||||||
.add(Point.fromAffine(mapToCurve(u[1])))
|
.add(Point.fromAffine(mapToCurve(u[1])))
|
||||||
.clearCofactor();
|
.clearCofactor();
|
||||||
|
P.assertValidity();
|
||||||
|
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
|
||||||
@ -226,7 +228,9 @@ export function hashToCurve<T>(
|
|||||||
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
if (!mapToCurve) throw new Error('CURVE.mapToCurve() has not been defined');
|
||||||
msg = ensureBytes(msg);
|
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);
|
||||||
return Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
|
||||||
|
P.assertValidity();
|
||||||
|
return P;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,16 @@
|
|||||||
import * as mod from './modular.js';
|
import * as mod from './modular.js';
|
||||||
import * as ut from './utils.js';
|
import * as ut from './utils.js';
|
||||||
import { Hex, PrivKey, ensureBytes, CHash } from './utils.js';
|
import { Hex, PrivKey, ensureBytes, CHash } from './utils.js';
|
||||||
import { Group, GroupConstructor, wNAF, AbstractCurve, validateAbsOpts } from './curve.js';
|
import {
|
||||||
|
Group,
|
||||||
|
GroupConstructor,
|
||||||
|
wNAF,
|
||||||
|
AbstractCurve,
|
||||||
|
validateAbsOpts,
|
||||||
|
AffinePoint,
|
||||||
|
} from './curve.js';
|
||||||
|
|
||||||
|
export type { AffinePoint };
|
||||||
type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
||||||
type EndomorphismOpts = {
|
type EndomorphismOpts = {
|
||||||
beta: bigint;
|
beta: bigint;
|
||||||
@ -55,10 +63,6 @@ export type VerOpts = { lowS?: boolean; prehash?: boolean };
|
|||||||
* TODO: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
|
* TODO: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type AffinePoint<T> = {
|
|
||||||
x: T;
|
|
||||||
y: T;
|
|
||||||
} & { z?: never };
|
|
||||||
// Instance for 3d XYZ points
|
// Instance for 3d XYZ points
|
||||||
export interface ProjPointType<T> extends Group<ProjPointType<T>> {
|
export interface ProjPointType<T> extends Group<ProjPointType<T>> {
|
||||||
readonly px: T;
|
readonly px: T;
|
||||||
|
Loading…
Reference in New Issue
Block a user