@noble/curves 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -43
- package/lib/abstract/edwards.js +24 -1
- package/lib/abstract/modular.d.ts +1 -1
- package/lib/abstract/montgomery.js +3 -1
- package/lib/abstract/utils.d.ts +15 -2
- package/lib/abstract/utils.js +24 -16
- package/lib/abstract/weierstrass.js +3 -0
- package/lib/esm/abstract/edwards.js +24 -1
- package/lib/esm/abstract/montgomery.js +3 -1
- package/lib/esm/abstract/utils.js +24 -16
- package/lib/esm/abstract/weierstrass.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -329,47 +329,54 @@ The module allows to hash arbitrary strings to elliptic curve points.
|
|
|
329
329
|
|
|
330
330
|
- `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..
|
|
331
331
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
332
|
+
```ts
|
|
333
|
+
function expand_message_xmd(
|
|
334
|
+
msg: Uint8Array,
|
|
335
|
+
DST: Uint8Array,
|
|
336
|
+
lenInBytes: number,
|
|
337
|
+
H: CHash
|
|
338
|
+
): Uint8Array;
|
|
339
|
+
function expand_message_xof(
|
|
340
|
+
msg: Uint8Array,
|
|
341
|
+
DST: Uint8Array,
|
|
342
|
+
lenInBytes: number,
|
|
343
|
+
k: number,
|
|
344
|
+
H: CHash
|
|
345
|
+
): Uint8Array;
|
|
346
|
+
```
|
|
340
347
|
|
|
341
348
|
- `hash_to_field(msg, count, options)` [(spec)](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3)
|
|
342
|
-
hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
349
|
+
hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
|
350
|
+
_ `msg` a byte string containing the message to hash
|
|
351
|
+
_ `count` the number of elements of F to output
|
|
352
|
+
_ `options` `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
|
|
353
|
+
_ Returns `[u_0, ..., u_(count - 1)]`, a list of field elements.
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
function hash_to_field(msg: Uint8Array, count: number, options: htfOpts): bigint[][];
|
|
357
|
+
type htfOpts = {
|
|
358
|
+
// DST: a domain separation tag
|
|
359
|
+
// defined in section 2.2.5
|
|
360
|
+
DST: string;
|
|
361
|
+
// p: the characteristic of F
|
|
362
|
+
// where F is a finite field of characteristic p and order q = p^m
|
|
363
|
+
p: bigint;
|
|
364
|
+
// m: the extension degree of F, m >= 1
|
|
365
|
+
// where F is a finite field of characteristic p and order q = p^m
|
|
366
|
+
m: number;
|
|
367
|
+
// k: the target security level for the suite in bits
|
|
368
|
+
// defined in section 5.1
|
|
369
|
+
k: number;
|
|
370
|
+
// option to use a message that has already been processed by
|
|
371
|
+
// expand_message_xmd
|
|
372
|
+
expand?: 'xmd' | 'xof';
|
|
373
|
+
// Hash functions for: expand_message_xmd is appropriate for use with a
|
|
374
|
+
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
|
375
|
+
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|
|
376
|
+
// TODO: verify that hash is shake if expand==='xof' via types
|
|
377
|
+
hash: CHash;
|
|
378
|
+
};
|
|
379
|
+
```
|
|
373
380
|
|
|
374
381
|
### abstract/poseidon: Poseidon hash
|
|
375
382
|
|
|
@@ -516,11 +523,11 @@ Upgrading from @noble/secp256k1 1.7:
|
|
|
516
523
|
- Compressed (33-byte) public keys are now returned by default, instead of uncompressed
|
|
517
524
|
- Methods are now synchronous. Setting `secp.utils.hmacSha256` is no longer required
|
|
518
525
|
- `sign()`
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
526
|
+
- `der`, `recovered` options were removed
|
|
527
|
+
- `canonical` was renamed to `lowS`
|
|
528
|
+
- Return type is now `{ r: bigint, s: bigint, recovery: number }` instance of `Signature`
|
|
522
529
|
- `verify()`
|
|
523
|
-
|
|
530
|
+
- `strict` was renamed to `lowS`
|
|
524
531
|
- `recoverPublicKey()`: moved to sig instance `Signature#recoverPublicKey(msgHash)`
|
|
525
532
|
- `Point` was removed: use `ProjectivePoint` in xyz coordinates
|
|
526
533
|
- `utils`: Many methods were removed, others were moved to `schnorr` namespace
|
|
@@ -532,6 +539,7 @@ Upgrading from @noble/ed25519 1.7:
|
|
|
532
539
|
- `Point` was removed: use `ExtendedPoint` in xyzt coordinates
|
|
533
540
|
- `Signature` was removed
|
|
534
541
|
- `getSharedSecret` was removed: use separate x25519 sub-module
|
|
542
|
+
- `bigint` is no longer allowed in `getPublicKey`, `sign`, `verify`. Reason: ed25519 is LE, can lead to bugs
|
|
535
543
|
|
|
536
544
|
## Contributing & testing
|
|
537
545
|
|
package/lib/abstract/edwards.js
CHANGED
|
@@ -109,7 +109,30 @@ function twistedEdwards(curveDef) {
|
|
|
109
109
|
this._WINDOW_SIZE = windowSize;
|
|
110
110
|
pointPrecomputes.delete(this);
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
// Not required for fromHex(), which always creates valid points.
|
|
113
|
+
// Could be useful for fromAffine().
|
|
114
|
+
assertValidity() {
|
|
115
|
+
const { a, d } = CURVE;
|
|
116
|
+
if (this.is0())
|
|
117
|
+
throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?
|
|
118
|
+
// Equation in affine coordinates: ax² + y² = 1 + dx²y²
|
|
119
|
+
// Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²
|
|
120
|
+
const { ex: X, ey: Y, ez: Z, et: T } = this;
|
|
121
|
+
const X2 = modP(X * X); // X²
|
|
122
|
+
const Y2 = modP(Y * Y); // Y²
|
|
123
|
+
const Z2 = modP(Z * Z); // Z²
|
|
124
|
+
const Z4 = modP(Z2 * Z2); // Z⁴
|
|
125
|
+
const aX2 = modP(X2 * a); // aX²
|
|
126
|
+
const left = modP(Z2 * modP(aX2 + Y2)); // (aX² + Y²)Z²
|
|
127
|
+
const right = modP(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²
|
|
128
|
+
if (left !== right)
|
|
129
|
+
throw new Error('bad point: equation left != right (1)');
|
|
130
|
+
// In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T
|
|
131
|
+
const XY = modP(X * Y);
|
|
132
|
+
const ZT = modP(Z * T);
|
|
133
|
+
if (XY !== ZT)
|
|
134
|
+
throw new Error('bad point: equation left != right (2)');
|
|
135
|
+
}
|
|
113
136
|
// Compare one point to another.
|
|
114
137
|
equals(other) {
|
|
115
138
|
isPoint(other);
|
|
@@ -42,7 +42,7 @@ export interface Field<T> {
|
|
|
42
42
|
fromBytes(bytes: Uint8Array): T;
|
|
43
43
|
cmov(a: T, b: T, c: boolean): T;
|
|
44
44
|
}
|
|
45
|
-
export declare function validateField<T>(field: Field<T>):
|
|
45
|
+
export declare function validateField<T>(field: Field<T>): Field<T>;
|
|
46
46
|
export declare function FpPow<T>(f: Field<T>, num: T, power: bigint): T;
|
|
47
47
|
export declare function FpInvertBatch<T>(f: Field<T>, nums: T[]): T[];
|
|
48
48
|
export declare function FpDiv<T>(f: Field<T>, lhs: T, rhs: T | bigint): T;
|
|
@@ -121,7 +121,9 @@ function montgomery(curveDef) {
|
|
|
121
121
|
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
|
122
122
|
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
|
123
123
|
const u = (0, utils_js_1.ensureBytes)(uEnc, montgomeryBytes);
|
|
124
|
-
u[fieldLen
|
|
124
|
+
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
|
|
125
|
+
if (fieldLen === montgomeryBytes)
|
|
126
|
+
u[fieldLen - 1] &= 127; // 0b0111_1111
|
|
125
127
|
return (0, utils_js_1.bytesToNumberLE)(u);
|
|
126
128
|
}
|
|
127
129
|
function decodeScalar(n) {
|
package/lib/abstract/utils.d.ts
CHANGED
|
@@ -25,6 +25,19 @@ export declare function bitLen(n: bigint): number;
|
|
|
25
25
|
export declare const bitGet: (n: bigint, pos: number) => bigint;
|
|
26
26
|
export declare const bitSet: (n: bigint, pos: number, value: boolean) => bigint;
|
|
27
27
|
export declare const bitMask: (n: number) => bigint;
|
|
28
|
-
declare
|
|
29
|
-
|
|
28
|
+
declare const validatorFns: {
|
|
29
|
+
readonly bigint: (val: any) => boolean;
|
|
30
|
+
readonly function: (val: any) => boolean;
|
|
31
|
+
readonly boolean: (val: any) => boolean;
|
|
32
|
+
readonly string: (val: any) => boolean;
|
|
33
|
+
readonly isSafeInteger: (val: any) => boolean;
|
|
34
|
+
readonly array: (val: any) => boolean;
|
|
35
|
+
readonly field: (val: any, object: any) => any;
|
|
36
|
+
readonly hash: (val: any) => boolean;
|
|
37
|
+
};
|
|
38
|
+
declare type Validator = keyof typeof validatorFns;
|
|
39
|
+
declare type ValMap<T extends Record<string, any>> = {
|
|
40
|
+
[K in keyof T]?: Validator;
|
|
41
|
+
};
|
|
42
|
+
export declare function validateObject<T extends Record<string, any>>(object: T, validators: ValMap<T>, optValidators?: ValMap<T>): T;
|
|
30
43
|
export {};
|
package/lib/abstract/utils.js
CHANGED
|
@@ -27,7 +27,7 @@ function hexToNumber(hex) {
|
|
|
27
27
|
if (typeof hex !== 'string')
|
|
28
28
|
throw new Error('string expected, got ' + typeof hex);
|
|
29
29
|
// Big Endian
|
|
30
|
-
return BigInt(`0x${hex}`);
|
|
30
|
+
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
|
31
31
|
}
|
|
32
32
|
exports.hexToNumber = hexToNumber;
|
|
33
33
|
// Caching slows it down 2-3x
|
|
@@ -118,18 +118,18 @@ exports.bitSet = bitSet;
|
|
|
118
118
|
// Not using ** operator with bigints for old engines.
|
|
119
119
|
const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
|
|
120
120
|
exports.bitMask = bitMask;
|
|
121
|
+
const validatorFns = {
|
|
122
|
+
bigint: (val) => typeof val === 'bigint',
|
|
123
|
+
function: (val) => typeof val === 'function',
|
|
124
|
+
boolean: (val) => typeof val === 'boolean',
|
|
125
|
+
string: (val) => typeof val === 'string',
|
|
126
|
+
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
127
|
+
array: (val) => Array.isArray(val),
|
|
128
|
+
field: (val, object) => object.Fp.isValid(val),
|
|
129
|
+
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
130
|
+
};
|
|
131
|
+
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
|
|
121
132
|
function validateObject(object, validators, optValidators = {}) {
|
|
122
|
-
const validatorFns = {
|
|
123
|
-
bigint: (val) => typeof val === 'bigint',
|
|
124
|
-
function: (val) => typeof val === 'function',
|
|
125
|
-
boolean: (val) => typeof val === 'boolean',
|
|
126
|
-
string: (val) => typeof val === 'string',
|
|
127
|
-
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
128
|
-
array: (val) => Array.isArray(val),
|
|
129
|
-
field: (val) => object.Fp.isValid(val),
|
|
130
|
-
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
131
|
-
};
|
|
132
|
-
// type Key = keyof typeof validators;
|
|
133
133
|
const checkField = (fieldName, type, isOptional) => {
|
|
134
134
|
const checkVal = validatorFns[type];
|
|
135
135
|
if (typeof checkVal !== 'function')
|
|
@@ -137,14 +137,22 @@ function validateObject(object, validators, optValidators = {}) {
|
|
|
137
137
|
const val = object[fieldName];
|
|
138
138
|
if (isOptional && val === undefined)
|
|
139
139
|
return;
|
|
140
|
-
if (!checkVal(val)) {
|
|
141
|
-
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
|
|
140
|
+
if (!checkVal(val, object)) {
|
|
141
|
+
throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
|
|
142
142
|
}
|
|
143
143
|
};
|
|
144
|
-
for (
|
|
144
|
+
for (const [fieldName, type] of Object.entries(validators))
|
|
145
145
|
checkField(fieldName, type, false);
|
|
146
|
-
for (
|
|
146
|
+
for (const [fieldName, type] of Object.entries(optValidators))
|
|
147
147
|
checkField(fieldName, type, true);
|
|
148
148
|
return object;
|
|
149
149
|
}
|
|
150
150
|
exports.validateObject = validateObject;
|
|
151
|
+
// validate type tests
|
|
152
|
+
// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
|
|
153
|
+
// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
|
|
154
|
+
// // Should fail type-check
|
|
155
|
+
// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
|
|
156
|
+
// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
|
|
157
|
+
// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
|
|
158
|
+
// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
|
|
@@ -19,6 +19,7 @@ function validatePointOpts(curve) {
|
|
|
19
19
|
wrapPrivateKey: 'boolean',
|
|
20
20
|
isTorsionFree: 'function',
|
|
21
21
|
clearCofactor: 'function',
|
|
22
|
+
allowInfinityPoint: 'boolean',
|
|
22
23
|
});
|
|
23
24
|
const { endo, Fp, a } = opts;
|
|
24
25
|
if (endo) {
|
|
@@ -157,6 +158,8 @@ function weierstrassPoints(opts) {
|
|
|
157
158
|
if (pz == null || !Fp.isValid(pz))
|
|
158
159
|
throw new Error('z required');
|
|
159
160
|
}
|
|
161
|
+
// Does not validate if the point is on-curve.
|
|
162
|
+
// Use fromHex instead, or call assertValidity() later.
|
|
160
163
|
static fromAffine(p) {
|
|
161
164
|
const { x, y } = p || {};
|
|
162
165
|
if (!p || !Fp.isValid(x) || !Fp.isValid(y))
|
|
@@ -106,7 +106,30 @@ export function twistedEdwards(curveDef) {
|
|
|
106
106
|
this._WINDOW_SIZE = windowSize;
|
|
107
107
|
pointPrecomputes.delete(this);
|
|
108
108
|
}
|
|
109
|
-
|
|
109
|
+
// Not required for fromHex(), which always creates valid points.
|
|
110
|
+
// Could be useful for fromAffine().
|
|
111
|
+
assertValidity() {
|
|
112
|
+
const { a, d } = CURVE;
|
|
113
|
+
if (this.is0())
|
|
114
|
+
throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?
|
|
115
|
+
// Equation in affine coordinates: ax² + y² = 1 + dx²y²
|
|
116
|
+
// Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²
|
|
117
|
+
const { ex: X, ey: Y, ez: Z, et: T } = this;
|
|
118
|
+
const X2 = modP(X * X); // X²
|
|
119
|
+
const Y2 = modP(Y * Y); // Y²
|
|
120
|
+
const Z2 = modP(Z * Z); // Z²
|
|
121
|
+
const Z4 = modP(Z2 * Z2); // Z⁴
|
|
122
|
+
const aX2 = modP(X2 * a); // aX²
|
|
123
|
+
const left = modP(Z2 * modP(aX2 + Y2)); // (aX² + Y²)Z²
|
|
124
|
+
const right = modP(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²
|
|
125
|
+
if (left !== right)
|
|
126
|
+
throw new Error('bad point: equation left != right (1)');
|
|
127
|
+
// In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T
|
|
128
|
+
const XY = modP(X * Y);
|
|
129
|
+
const ZT = modP(Z * T);
|
|
130
|
+
if (XY !== ZT)
|
|
131
|
+
throw new Error('bad point: equation left != right (2)');
|
|
132
|
+
}
|
|
110
133
|
// Compare one point to another.
|
|
111
134
|
equals(other) {
|
|
112
135
|
isPoint(other);
|
|
@@ -118,7 +118,9 @@ export function montgomery(curveDef) {
|
|
|
118
118
|
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
|
|
119
119
|
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
|
|
120
120
|
const u = ensureBytes(uEnc, montgomeryBytes);
|
|
121
|
-
u[fieldLen
|
|
121
|
+
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
|
|
122
|
+
if (fieldLen === montgomeryBytes)
|
|
123
|
+
u[fieldLen - 1] &= 127; // 0b0111_1111
|
|
122
124
|
return bytesToNumberLE(u);
|
|
123
125
|
}
|
|
124
126
|
function decodeScalar(n) {
|
|
@@ -22,7 +22,7 @@ export function hexToNumber(hex) {
|
|
|
22
22
|
if (typeof hex !== 'string')
|
|
23
23
|
throw new Error('string expected, got ' + typeof hex);
|
|
24
24
|
// Big Endian
|
|
25
|
-
return BigInt(`0x${hex}`);
|
|
25
|
+
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
|
26
26
|
}
|
|
27
27
|
// Caching slows it down 2-3x
|
|
28
28
|
export function hexToBytes(hex) {
|
|
@@ -99,18 +99,18 @@ export const bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos)
|
|
|
99
99
|
// Return mask for N bits (Same as BigInt(`0b${Array(i).fill('1').join('')}`))
|
|
100
100
|
// Not using ** operator with bigints for old engines.
|
|
101
101
|
export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
|
|
102
|
+
const validatorFns = {
|
|
103
|
+
bigint: (val) => typeof val === 'bigint',
|
|
104
|
+
function: (val) => typeof val === 'function',
|
|
105
|
+
boolean: (val) => typeof val === 'boolean',
|
|
106
|
+
string: (val) => typeof val === 'string',
|
|
107
|
+
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
108
|
+
array: (val) => Array.isArray(val),
|
|
109
|
+
field: (val, object) => object.Fp.isValid(val),
|
|
110
|
+
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
111
|
+
};
|
|
112
|
+
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
|
|
102
113
|
export function validateObject(object, validators, optValidators = {}) {
|
|
103
|
-
const validatorFns = {
|
|
104
|
-
bigint: (val) => typeof val === 'bigint',
|
|
105
|
-
function: (val) => typeof val === 'function',
|
|
106
|
-
boolean: (val) => typeof val === 'boolean',
|
|
107
|
-
string: (val) => typeof val === 'string',
|
|
108
|
-
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
109
|
-
array: (val) => Array.isArray(val),
|
|
110
|
-
field: (val) => object.Fp.isValid(val),
|
|
111
|
-
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
112
|
-
};
|
|
113
|
-
// type Key = keyof typeof validators;
|
|
114
114
|
const checkField = (fieldName, type, isOptional) => {
|
|
115
115
|
const checkVal = validatorFns[type];
|
|
116
116
|
if (typeof checkVal !== 'function')
|
|
@@ -118,13 +118,21 @@ export function validateObject(object, validators, optValidators = {}) {
|
|
|
118
118
|
const val = object[fieldName];
|
|
119
119
|
if (isOptional && val === undefined)
|
|
120
120
|
return;
|
|
121
|
-
if (!checkVal(val)) {
|
|
122
|
-
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
|
|
121
|
+
if (!checkVal(val, object)) {
|
|
122
|
+
throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
|
|
123
123
|
}
|
|
124
124
|
};
|
|
125
|
-
for (
|
|
125
|
+
for (const [fieldName, type] of Object.entries(validators))
|
|
126
126
|
checkField(fieldName, type, false);
|
|
127
|
-
for (
|
|
127
|
+
for (const [fieldName, type] of Object.entries(optValidators))
|
|
128
128
|
checkField(fieldName, type, true);
|
|
129
129
|
return object;
|
|
130
130
|
}
|
|
131
|
+
// validate type tests
|
|
132
|
+
// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
|
|
133
|
+
// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
|
|
134
|
+
// // Should fail type-check
|
|
135
|
+
// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
|
|
136
|
+
// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
|
|
137
|
+
// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
|
|
138
|
+
// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
|
|
@@ -16,6 +16,7 @@ function validatePointOpts(curve) {
|
|
|
16
16
|
wrapPrivateKey: 'boolean',
|
|
17
17
|
isTorsionFree: 'function',
|
|
18
18
|
clearCofactor: 'function',
|
|
19
|
+
allowInfinityPoint: 'boolean',
|
|
19
20
|
});
|
|
20
21
|
const { endo, Fp, a } = opts;
|
|
21
22
|
if (endo) {
|
|
@@ -154,6 +155,8 @@ export function weierstrassPoints(opts) {
|
|
|
154
155
|
if (pz == null || !Fp.isValid(pz))
|
|
155
156
|
throw new Error('z required');
|
|
156
157
|
}
|
|
158
|
+
// Does not validate if the point is on-curve.
|
|
159
|
+
// Use fromHex instead, or call assertValidity() later.
|
|
157
160
|
static fromAffine(p) {
|
|
158
161
|
const { x, y } = p || {};
|
|
159
162
|
if (!p || !Fp.isValid(x) || !Fp.isValid(y))
|