@noble/curves 2.0.0-beta.1 → 2.0.0-beta.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 +442 -273
- package/abstract/bls.d.ts +17 -17
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +14 -9
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +9 -3
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +7 -9
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +12 -16
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +32 -31
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +15 -14
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +7 -5
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +3 -3
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +9 -13
- package/abstract/montgomery.js.map +1 -1
- package/abstract/oprf.d.ts +4 -4
- package/abstract/oprf.d.ts.map +1 -1
- package/abstract/oprf.js +2 -2
- package/abstract/oprf.js.map +1 -1
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +8 -9
- package/abstract/poseidon.js.map +1 -1
- package/abstract/weierstrass.d.ts +66 -20
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +72 -68
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +3 -9
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +3 -14
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +3 -3
- package/bn254.d.ts.map +1 -1
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +22 -18
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +59 -31
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +17 -8
- package/ed448.d.ts.map +1 -1
- package/ed448.js +69 -52
- package/ed448.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +20 -4
- package/index.js.map +1 -1
- package/misc.js +2 -2
- package/misc.js.map +1 -1
- package/nist.d.ts +20 -2
- package/nist.d.ts.map +1 -1
- package/nist.js +30 -10
- package/nist.js.map +1 -1
- package/package.json +14 -13
- package/secp256k1.d.ts +10 -7
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +15 -16
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +22 -22
- package/src/abstract/curve.ts +19 -5
- package/src/abstract/edwards.ts +20 -23
- package/src/abstract/hash-to-curve.ts +50 -51
- package/src/abstract/modular.ts +7 -5
- package/src/abstract/montgomery.ts +12 -18
- package/src/abstract/oprf.ts +5 -5
- package/src/abstract/poseidon.ts +6 -8
- package/src/abstract/weierstrass.ts +139 -89
- package/src/bls12-381.ts +4 -15
- package/src/bn254.ts +6 -6
- package/src/ed25519.ts +65 -40
- package/src/ed448.ts +87 -69
- package/src/index.ts +19 -3
- package/src/misc.ts +2 -2
- package/src/nist.ts +31 -15
- package/src/secp256k1.ts +16 -18
- package/src/utils.ts +33 -83
- package/src/webcrypto.ts +148 -107
- package/utils.d.ts +4 -20
- package/utils.d.ts.map +1 -1
- package/utils.js +30 -73
- package/utils.js.map +1 -1
- package/webcrypto.d.ts +73 -21
- package/webcrypto.d.ts.map +1 -1
- package/webcrypto.js +101 -76
- package/webcrypto.js.map +1 -1
- package/_shortw_utils.d.ts +0 -19
- package/_shortw_utils.d.ts.map +0 -1
- package/_shortw_utils.js +0 -20
- package/_shortw_utils.js.map +0 -1
- package/abstract/utils.d.ts +0 -5
- package/abstract/utils.d.ts.map +0 -1
- package/abstract/utils.js +0 -23
- package/abstract/utils.js.map +0 -1
- package/jubjub.d.ts +0 -12
- package/jubjub.d.ts.map +0 -1
- package/jubjub.js +0 -15
- package/jubjub.js.map +0 -1
- package/p256.d.ts +0 -16
- package/p256.d.ts.map +0 -1
- package/p256.js +0 -13
- package/p256.js.map +0 -1
- package/p384.d.ts +0 -16
- package/p384.d.ts.map +0 -1
- package/p384.js +0 -13
- package/p384.js.map +0 -1
- package/p521.d.ts +0 -16
- package/p521.d.ts.map +0 -1
- package/p521.js +0 -13
- package/p521.js.map +0 -1
- package/pasta.d.ts +0 -10
- package/pasta.d.ts.map +0 -1
- package/pasta.js +0 -13
- package/pasta.js.map +0 -1
package/src/nist.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
|
|
20
20
|
// p = 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n - 1n
|
|
21
21
|
// a = Fp256.create(BigInt('-3'));
|
|
22
|
-
const p256_CURVE: WeierstrassOpts<bigint> = {
|
|
22
|
+
const p256_CURVE: WeierstrassOpts<bigint> = /* @__PURE__ */ (() => ({
|
|
23
23
|
p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
|
|
24
24
|
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
|
|
25
25
|
h: BigInt(1),
|
|
@@ -27,10 +27,10 @@ const p256_CURVE: WeierstrassOpts<bigint> = {
|
|
|
27
27
|
b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
|
|
28
28
|
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
|
|
29
29
|
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
|
|
30
|
-
};
|
|
30
|
+
}))();
|
|
31
31
|
|
|
32
32
|
// p = 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
|
|
33
|
-
const p384_CURVE: WeierstrassOpts<bigint> = {
|
|
33
|
+
const p384_CURVE: WeierstrassOpts<bigint> = /* @__PURE__ */ (() => ({
|
|
34
34
|
p: BigInt(
|
|
35
35
|
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff'
|
|
36
36
|
),
|
|
@@ -50,10 +50,10 @@ const p384_CURVE: WeierstrassOpts<bigint> = {
|
|
|
50
50
|
Gy: BigInt(
|
|
51
51
|
'0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'
|
|
52
52
|
),
|
|
53
|
-
};
|
|
53
|
+
}))();
|
|
54
54
|
|
|
55
55
|
// p = 2n**521n - 1n
|
|
56
|
-
const p521_CURVE: WeierstrassOpts<bigint> = {
|
|
56
|
+
const p521_CURVE: WeierstrassOpts<bigint> = /* @__PURE__ */ (() => ({
|
|
57
57
|
p: BigInt(
|
|
58
58
|
'0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
|
59
59
|
),
|
|
@@ -73,21 +73,36 @@ const p521_CURVE: WeierstrassOpts<bigint> = {
|
|
|
73
73
|
Gy: BigInt(
|
|
74
74
|
'0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'
|
|
75
75
|
),
|
|
76
|
-
};
|
|
76
|
+
}))();
|
|
77
77
|
|
|
78
78
|
type SwuOpts = {
|
|
79
79
|
A: bigint;
|
|
80
80
|
B: bigint;
|
|
81
81
|
Z: bigint;
|
|
82
82
|
};
|
|
83
|
+
|
|
83
84
|
function createSWU(Point: WeierstrassPointCons<bigint>, opts: SwuOpts) {
|
|
84
85
|
const map = mapToCurveSimpleSWU(Point.Fp, opts);
|
|
85
86
|
return (scalars: bigint[]) => map(scalars[0]);
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
// NIST P256
|
|
90
90
|
const p256_Point = /* @__PURE__ */ weierstrass(p256_CURVE);
|
|
91
|
+
/**
|
|
92
|
+
* NIST P256 (aka secp256r1, prime256v1) curve, ECDSA and ECDH methods.
|
|
93
|
+
* Hashes inputs with sha256 by default.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```js
|
|
97
|
+
* import { p256 } from '@noble/curves/nist.js';
|
|
98
|
+
* const { secretKey, publicKey } = p256.keygen();
|
|
99
|
+
* // const publicKey = p256.getPublicKey(secretKey);
|
|
100
|
+
* const msg = new TextEncoder().encode('hello noble');
|
|
101
|
+
* const sig = p256.sign(msg, secretKey);
|
|
102
|
+
* const isValid = p256.verify(sig, msg, publicKey);
|
|
103
|
+
* // const sigKeccak = p256.sign(keccak256(msg), secretKey, { prehash: false });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
91
106
|
export const p256: ECDSA = /* @__PURE__ */ ecdsa(p256_Point, sha256);
|
|
92
107
|
/** Hashing / encoding to p256 points / field. RFC 9380 methods. */
|
|
93
108
|
export const p256_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
|
|
@@ -109,7 +124,7 @@ export const p256_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__
|
|
|
109
124
|
}
|
|
110
125
|
);
|
|
111
126
|
})();
|
|
112
|
-
|
|
127
|
+
/** p256 OPRF, defined in RFC 9497. */
|
|
113
128
|
export const p256_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
114
129
|
createORPF({
|
|
115
130
|
name: 'P256-SHA256',
|
|
@@ -119,8 +134,9 @@ export const p256_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
|
119
134
|
hashToScalar: p256_hasher.hashToScalar,
|
|
120
135
|
}))();
|
|
121
136
|
|
|
137
|
+
// NIST P384
|
|
122
138
|
const p384_Point = /* @__PURE__ */ weierstrass(p384_CURVE);
|
|
123
|
-
/** NIST P384 (aka secp384r1) curve, ECDSA and ECDH methods. */
|
|
139
|
+
/** NIST P384 (aka secp384r1) curve, ECDSA and ECDH methods. Hashes inputs with sha384 by default. */
|
|
124
140
|
export const p384: ECDSA = /* @__PURE__ */ ecdsa(p384_Point, sha384);
|
|
125
141
|
/** Hashing / encoding to p384 points / field. RFC 9380 methods. */
|
|
126
142
|
export const p384_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
|
|
@@ -142,7 +158,7 @@ export const p384_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__
|
|
|
142
158
|
}
|
|
143
159
|
);
|
|
144
160
|
})();
|
|
145
|
-
|
|
161
|
+
/** p384 OPRF, defined in RFC 9497. */
|
|
146
162
|
export const p384_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
147
163
|
createORPF({
|
|
148
164
|
name: 'P384-SHA384',
|
|
@@ -152,11 +168,11 @@ export const p384_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
|
152
168
|
hashToScalar: p384_hasher.hashToScalar,
|
|
153
169
|
}))();
|
|
154
170
|
|
|
155
|
-
|
|
171
|
+
// NIST P521
|
|
172
|
+
const Fn521 = /* @__PURE__ */ (() => Field(p521_CURVE.n, { allowedLengths: [65, 66] }))();
|
|
156
173
|
const p521_Point = /* @__PURE__ */ weierstrass(p521_CURVE, { Fn: Fn521 });
|
|
157
|
-
/** NIST P521 (aka secp521r1) curve, ECDSA and ECDH methods. */
|
|
174
|
+
/** NIST P521 (aka secp521r1) curve, ECDSA and ECDH methods. Hashes inputs with sha512 by default. */
|
|
158
175
|
export const p521: ECDSA = /* @__PURE__ */ ecdsa(p521_Point, sha512);
|
|
159
|
-
|
|
160
176
|
/** Hashing / encoding to p521 points / field. RFC 9380 methods. */
|
|
161
177
|
export const p521_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
|
|
162
178
|
return createHasher(
|
|
@@ -177,7 +193,7 @@ export const p521_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__
|
|
|
177
193
|
}
|
|
178
194
|
);
|
|
179
195
|
})();
|
|
180
|
-
|
|
196
|
+
/** p521 OPRF, defined in RFC 9497. */
|
|
181
197
|
export const p521_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
182
198
|
createORPF({
|
|
183
199
|
name: 'P521-SHA512',
|
package/src/secp256k1.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
9
9
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
10
10
|
import { randomBytes } from '@noble/hashes/utils.js';
|
|
11
|
-
import type
|
|
11
|
+
import { createKeygen, type CurveLengths } from './abstract/curve.ts';
|
|
12
12
|
import { createHasher, type H2CHasher, isogenyMap } from './abstract/hash-to-curve.ts';
|
|
13
13
|
import { Field, mapHashToField, pow2 } from './abstract/modular.ts';
|
|
14
14
|
import {
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
type WeierstrassOpts,
|
|
22
22
|
type WeierstrassPointCons,
|
|
23
23
|
} from './abstract/weierstrass.ts';
|
|
24
|
-
import { abytes, asciiToBytes, bytesToNumberBE, concatBytes
|
|
24
|
+
import { abytes, asciiToBytes, bytesToNumberBE, concatBytes } from './utils.ts';
|
|
25
25
|
|
|
26
26
|
// Seems like generator was produced from some seed:
|
|
27
27
|
// `Pointk1.BASE.multiply(Pointk1.Fn.inv(2n, N)).toAffine().x`
|
|
@@ -45,7 +45,6 @@ const secp256k1_ENDO: EndomorphismOpts = {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
const _0n = /* @__PURE__ */ BigInt(0);
|
|
48
|
-
const _1n = /* @__PURE__ */ BigInt(1);
|
|
49
48
|
const _2n = /* @__PURE__ */ BigInt(2);
|
|
50
49
|
|
|
51
50
|
/**
|
|
@@ -83,20 +82,22 @@ const Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
|
|
|
83
82
|
});
|
|
84
83
|
|
|
85
84
|
/**
|
|
86
|
-
* secp256k1 curve
|
|
85
|
+
* secp256k1 curve: ECDSA and ECDH methods.
|
|
87
86
|
*
|
|
88
|
-
*
|
|
87
|
+
* Uses sha256 to hash messages. To use a different hash,
|
|
88
|
+
* pass `{ prehash: false }` to sign / verify.
|
|
89
89
|
*
|
|
90
90
|
* @example
|
|
91
91
|
* ```js
|
|
92
|
-
* import { secp256k1 } from '@noble/curves/secp256k1';
|
|
92
|
+
* import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
93
93
|
* const { secretKey, publicKey } = secp256k1.keygen();
|
|
94
|
-
* const
|
|
94
|
+
* // const publicKey = secp256k1.getPublicKey(secretKey);
|
|
95
|
+
* const msg = new TextEncoder().encode('hello noble');
|
|
95
96
|
* const sig = secp256k1.sign(msg, secretKey);
|
|
96
|
-
* const isValid = secp256k1.verify(sig, msg, publicKey)
|
|
97
|
+
* const isValid = secp256k1.verify(sig, msg, publicKey);
|
|
98
|
+
* // const sigKeccak = secp256k1.sign(keccak256(msg), secretKey, { prehash: false });
|
|
97
99
|
* ```
|
|
98
100
|
*/
|
|
99
|
-
|
|
100
101
|
export const secp256k1: ECDSA = /* @__PURE__ */ ecdsa(Pointk1, sha256);
|
|
101
102
|
|
|
102
103
|
// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
|
|
@@ -188,16 +189,17 @@ function schnorrSign(
|
|
|
188
189
|
* Will swallow errors & return false except for initial type validation of arguments.
|
|
189
190
|
*/
|
|
190
191
|
function schnorrVerify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean {
|
|
191
|
-
const { Fn, BASE } = Pointk1;
|
|
192
|
+
const { Fp, Fn, BASE } = Pointk1;
|
|
192
193
|
const sig = abytes(signature, 64, 'signature');
|
|
193
194
|
const m = abytes(message, undefined, 'message');
|
|
194
195
|
const pub = abytes(publicKey, 32, 'publicKey');
|
|
195
196
|
try {
|
|
196
197
|
const P = lift_x(num(pub)); // P = lift_x(int(pk)); fail if that fails
|
|
197
198
|
const r = num(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
|
198
|
-
if (!
|
|
199
|
+
if (!Fp.isValidNot0(r)) return false;
|
|
199
200
|
const s = num(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
|
|
200
|
-
if (!
|
|
201
|
+
if (!Fn.isValidNot0(s)) return false;
|
|
202
|
+
|
|
201
203
|
const e = challenge(Fn.toBytes(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
|
|
202
204
|
// R = s⋅G - e⋅P, where -eP == (n-e)P
|
|
203
205
|
const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));
|
|
@@ -229,7 +231,7 @@ export type SecpSchnorr = {
|
|
|
229
231
|
* https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
|
|
230
232
|
* @example
|
|
231
233
|
* ```js
|
|
232
|
-
* import { schnorr } from '@noble/curves/secp256k1';
|
|
234
|
+
* import { schnorr } from '@noble/curves/secp256k1.js';
|
|
233
235
|
* const { secretKey, publicKey } = schnorr.keygen();
|
|
234
236
|
* // const publicKey = schnorr.getPublicKey(secretKey);
|
|
235
237
|
* const msg = new TextEncoder().encode('hello');
|
|
@@ -243,12 +245,8 @@ export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => {
|
|
|
243
245
|
const randomSecretKey = (seed = randomBytes(seedLength)): Uint8Array => {
|
|
244
246
|
return mapHashToField(seed, secp256k1_CURVE.n);
|
|
245
247
|
};
|
|
246
|
-
function keygen(seed?: Uint8Array) {
|
|
247
|
-
const secretKey = randomSecretKey(seed);
|
|
248
|
-
return { secretKey, publicKey: schnorrGetPublicKey(secretKey) };
|
|
249
|
-
}
|
|
250
248
|
return {
|
|
251
|
-
keygen,
|
|
249
|
+
keygen: createKeygen(randomSecretKey, schnorrGetPublicKey),
|
|
252
250
|
getPublicKey: schnorrGetPublicKey,
|
|
253
251
|
sign: schnorrSign,
|
|
254
252
|
verify: schnorrVerify,
|
package/src/utils.ts
CHANGED
|
@@ -9,18 +9,15 @@ import {
|
|
|
9
9
|
bytesToHex as bytesToHex_,
|
|
10
10
|
concatBytes as concatBytes_,
|
|
11
11
|
hexToBytes as hexToBytes_,
|
|
12
|
-
isBytes as isBytes_,
|
|
13
12
|
} from '@noble/hashes/utils.js';
|
|
14
13
|
export {
|
|
15
14
|
abytes,
|
|
16
15
|
anumber,
|
|
17
16
|
bytesToHex,
|
|
18
|
-
bytesToUtf8,
|
|
19
17
|
concatBytes,
|
|
20
18
|
hexToBytes,
|
|
21
19
|
isBytes,
|
|
22
20
|
randomBytes,
|
|
23
|
-
utf8ToBytes
|
|
24
21
|
} from '@noble/hashes/utils.js';
|
|
25
22
|
const _0n = /* @__PURE__ */ BigInt(0);
|
|
26
23
|
const _1n = /* @__PURE__ */ BigInt(1);
|
|
@@ -34,22 +31,29 @@ export type CHash = {
|
|
|
34
31
|
export type FHash = (message: Uint8Array) => Uint8Array;
|
|
35
32
|
export function abool(value: boolean, title: string = ''): boolean {
|
|
36
33
|
if (typeof value !== 'boolean') {
|
|
37
|
-
const prefix = title && `"${title}"`;
|
|
34
|
+
const prefix = title && `"${title}" `;
|
|
38
35
|
throw new Error(prefix + 'expected boolean, got type=' + typeof value);
|
|
39
36
|
}
|
|
40
37
|
return value;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
// Used in weierstrass, der
|
|
44
|
-
function
|
|
41
|
+
function abignumber(n: number | bigint) {
|
|
45
42
|
if (typeof n === 'bigint') {
|
|
46
43
|
if (!isPosBig(n)) throw new Error('positive bigint expected, got ' + n);
|
|
47
44
|
} else anumber(n);
|
|
48
45
|
return n;
|
|
49
46
|
}
|
|
50
47
|
|
|
48
|
+
export function asafenumber(value: number, title: string = ''): void {
|
|
49
|
+
if (!Number.isSafeInteger(value)) {
|
|
50
|
+
const prefix = title && `"${title}" `;
|
|
51
|
+
throw new Error(prefix + 'expected safe integer, got type=' + typeof value);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
51
55
|
export function numberToHexUnpadded(num: number | bigint): string {
|
|
52
|
-
const hex =
|
|
56
|
+
const hex = abignumber(num).toString(16);
|
|
53
57
|
return hex.length & 1 ? '0' + hex : hex;
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -68,7 +72,7 @@ export function bytesToNumberLE(bytes: Uint8Array): bigint {
|
|
|
68
72
|
|
|
69
73
|
export function numberToBytesBE(n: number | bigint, len: number): Uint8Array {
|
|
70
74
|
anumber(len);
|
|
71
|
-
n =
|
|
75
|
+
n = abignumber(n);
|
|
72
76
|
const res = hexToBytes_(n.toString(16).padStart(len * 2, '0'));
|
|
73
77
|
if (res.length !== len) throw new Error('number too large');
|
|
74
78
|
return res;
|
|
@@ -78,7 +82,7 @@ export function numberToBytesLE(n: number | bigint, len: number): Uint8Array {
|
|
|
78
82
|
}
|
|
79
83
|
// Unpadded, rarely used
|
|
80
84
|
export function numberToVarBytesBE(n: number | bigint): Uint8Array {
|
|
81
|
-
return hexToBytes_(numberToHexUnpadded(
|
|
85
|
+
return hexToBytes_(numberToHexUnpadded(abignumber(n)));
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
// Compares 2 u8a-s in kinda constant time
|
|
@@ -114,16 +118,6 @@ export function asciiToBytes(ascii: string): Uint8Array {
|
|
|
114
118
|
});
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
/**
|
|
118
|
-
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
|
|
119
|
-
*/
|
|
120
|
-
// export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
|
|
121
|
-
/**
|
|
122
|
-
* Converts bytes to string using UTF8 encoding.
|
|
123
|
-
* @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
|
|
124
|
-
*/
|
|
125
|
-
// export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
|
|
126
|
-
|
|
127
121
|
// Is positive bigint
|
|
128
122
|
const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n;
|
|
129
123
|
|
|
@@ -194,14 +188,18 @@ type Pred<T> = (v: Uint8Array) => T | undefined;
|
|
|
194
188
|
export function createHmacDrbg<T>(
|
|
195
189
|
hashLen: number,
|
|
196
190
|
qByteLen: number,
|
|
197
|
-
hmacFn: (key: Uint8Array,
|
|
191
|
+
hmacFn: (key: Uint8Array, message: Uint8Array) => Uint8Array
|
|
198
192
|
): (seed: Uint8Array, predicate: Pred<T>) => T {
|
|
199
|
-
|
|
200
|
-
|
|
193
|
+
anumber(hashLen, 'hashLen');
|
|
194
|
+
anumber(qByteLen, 'qByteLen');
|
|
201
195
|
if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');
|
|
196
|
+
const u8n = (len: number): Uint8Array => new Uint8Array(len); // creates Uint8Array
|
|
197
|
+
const NULL = u8n(0);
|
|
198
|
+
const byte0 = Uint8Array.of(0x00);
|
|
199
|
+
const byte1 = Uint8Array.of(0x01);
|
|
200
|
+
const _maxDrbgIters = 1000;
|
|
201
|
+
|
|
202
202
|
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
|
203
|
-
const u8n = (len: number) => new Uint8Array(len); // creates Uint8Array
|
|
204
|
-
const u8of = (byte: number) => Uint8Array.of(byte); // another shortcut
|
|
205
203
|
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
206
204
|
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
|
|
207
205
|
let i = 0; // Iterations counter, will throw when over 1000
|
|
@@ -210,18 +208,18 @@ export function createHmacDrbg<T>(
|
|
|
210
208
|
k.fill(0);
|
|
211
209
|
i = 0;
|
|
212
210
|
};
|
|
213
|
-
const h = (...
|
|
214
|
-
const reseed = (seed =
|
|
211
|
+
const h = (...msgs: Uint8Array[]) => hmacFn(k, concatBytes_(v, ...msgs)); // hmac(k)(v, ...values)
|
|
212
|
+
const reseed = (seed = NULL) => {
|
|
215
213
|
// HMAC-DRBG reseed() function. Steps D-G
|
|
216
|
-
k = h(
|
|
214
|
+
k = h(byte0, seed); // k = hmac(k || v || 0x00 || seed)
|
|
217
215
|
v = h(); // v = hmac(k || v)
|
|
218
216
|
if (seed.length === 0) return;
|
|
219
|
-
k = h(
|
|
217
|
+
k = h(byte1, seed); // k = hmac(k || v || 0x01 || seed)
|
|
220
218
|
v = h(); // v = hmac(k || v)
|
|
221
219
|
};
|
|
222
220
|
const gen = () => {
|
|
223
221
|
// HMAC-DRBG generate() function
|
|
224
|
-
if (i++ >=
|
|
222
|
+
if (i++ >= _maxDrbgIters) throw new Error('drbg: tried max amount of iterations');
|
|
225
223
|
let len = 0;
|
|
226
224
|
const out: Uint8Array[] = [];
|
|
227
225
|
while (len < qByteLen) {
|
|
@@ -232,7 +230,7 @@ export function createHmacDrbg<T>(
|
|
|
232
230
|
}
|
|
233
231
|
return concatBytes_(...out);
|
|
234
232
|
};
|
|
235
|
-
const genUntil = (seed: Uint8Array
|
|
233
|
+
const genUntil = (seed: Uint8Array<any>, pred: Pred<T>): T => {
|
|
236
234
|
reset();
|
|
237
235
|
reseed(seed); // Steps D-G
|
|
238
236
|
let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]
|
|
@@ -243,59 +241,9 @@ export function createHmacDrbg<T>(
|
|
|
243
241
|
return genUntil;
|
|
244
242
|
}
|
|
245
243
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const validatorFns = {
|
|
249
|
-
bigint: (val: any): boolean => typeof val === 'bigint',
|
|
250
|
-
function: (val: any): boolean => typeof val === 'function',
|
|
251
|
-
boolean: (val: any): boolean => typeof val === 'boolean',
|
|
252
|
-
string: (val: any): boolean => typeof val === 'string',
|
|
253
|
-
stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes_(val),
|
|
254
|
-
isSafeInteger: (val: any): boolean => Number.isSafeInteger(val),
|
|
255
|
-
array: (val: any): boolean => Array.isArray(val),
|
|
256
|
-
field: (val: any, object: any): any => (object as any).Fp.isValid(val),
|
|
257
|
-
hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
|
258
|
-
} as const;
|
|
259
|
-
type Validator = keyof typeof validatorFns;
|
|
260
|
-
type ValMap<T extends Record<string, any>> = { [K in keyof T]?: Validator };
|
|
261
|
-
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
|
|
262
|
-
|
|
263
|
-
export function validateObject<T extends Record<string, any>>(
|
|
264
|
-
object: T,
|
|
265
|
-
validators: ValMap<T>,
|
|
266
|
-
optValidators: ValMap<T> = {}
|
|
267
|
-
): T {
|
|
268
|
-
const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {
|
|
269
|
-
const checkVal = validatorFns[type];
|
|
270
|
-
if (typeof checkVal !== 'function') throw new Error('invalid validator function');
|
|
271
|
-
|
|
272
|
-
const val = object[fieldName as keyof typeof object];
|
|
273
|
-
if (isOptional && val === undefined) return;
|
|
274
|
-
if (!checkVal(val, object)) {
|
|
275
|
-
throw new Error(
|
|
276
|
-
'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false);
|
|
281
|
-
for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true);
|
|
282
|
-
return object;
|
|
283
|
-
}
|
|
284
|
-
// validate type tests
|
|
285
|
-
// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
|
|
286
|
-
// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
|
|
287
|
-
// // Should fail type-check
|
|
288
|
-
// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
|
|
289
|
-
// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
|
|
290
|
-
// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
|
|
291
|
-
// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
|
|
292
|
-
|
|
293
|
-
export function isHash(val: CHash): boolean {
|
|
294
|
-
return typeof val === 'function' && Number.isSafeInteger(val.outputLen);
|
|
295
|
-
}
|
|
296
|
-
export function _validateObject(
|
|
244
|
+
export function validateObject(
|
|
297
245
|
object: Record<string, any>,
|
|
298
|
-
fields: Record<string, string
|
|
246
|
+
fields: Record<string, string> = {},
|
|
299
247
|
optFields: Record<string, string> = {}
|
|
300
248
|
): void {
|
|
301
249
|
if (!object || typeof object !== 'object') throw new Error('expected valid options object');
|
|
@@ -307,8 +255,10 @@ export function _validateObject(
|
|
|
307
255
|
if (current !== expectedType || val === null)
|
|
308
256
|
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
309
257
|
}
|
|
310
|
-
|
|
311
|
-
|
|
258
|
+
const iter = (f: typeof fields, isOpt: boolean) =>
|
|
259
|
+
Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
|
|
260
|
+
iter(fields, false);
|
|
261
|
+
iter(optFields, true);
|
|
312
262
|
}
|
|
313
263
|
|
|
314
264
|
/**
|