@noble/curves 2.0.0 → 2.2.0
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 +214 -122
- package/abstract/bls.d.ts +299 -16
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +89 -24
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +274 -27
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +177 -23
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +166 -30
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +221 -86
- package/abstract/edwards.js.map +1 -1
- package/abstract/fft.d.ts +327 -10
- package/abstract/fft.d.ts.map +1 -1
- package/abstract/fft.js +155 -12
- package/abstract/fft.js.map +1 -1
- package/abstract/frost.d.ts +293 -0
- package/abstract/frost.d.ts.map +1 -0
- package/abstract/frost.js +704 -0
- package/abstract/frost.js.map +1 -0
- package/abstract/hash-to-curve.d.ts +173 -24
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +170 -31
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +429 -37
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +414 -119
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +83 -12
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +32 -7
- package/abstract/montgomery.js.map +1 -1
- package/abstract/oprf.d.ts +164 -91
- package/abstract/oprf.d.ts.map +1 -1
- package/abstract/oprf.js +88 -29
- package/abstract/oprf.js.map +1 -1
- package/abstract/poseidon.d.ts +138 -7
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +178 -15
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +122 -3
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +323 -139
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +339 -76
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +395 -205
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +16 -2
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +199 -209
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +11 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +93 -38
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +135 -14
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +207 -41
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +108 -14
- package/ed448.d.ts.map +1 -1
- package/ed448.js +194 -42
- package/ed448.js.map +1 -1
- package/index.js +7 -1
- package/index.js.map +1 -1
- package/misc.d.ts +106 -7
- package/misc.d.ts.map +1 -1
- package/misc.js +141 -32
- package/misc.js.map +1 -1
- package/nist.d.ts +112 -11
- package/nist.d.ts.map +1 -1
- package/nist.js +139 -17
- package/nist.js.map +1 -1
- package/package.json +34 -6
- package/secp256k1.d.ts +92 -15
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +211 -28
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +356 -69
- package/src/abstract/curve.ts +327 -44
- package/src/abstract/edwards.ts +367 -143
- package/src/abstract/fft.ts +371 -36
- package/src/abstract/frost.ts +1092 -0
- package/src/abstract/hash-to-curve.ts +255 -56
- package/src/abstract/modular.ts +591 -144
- package/src/abstract/montgomery.ts +114 -30
- package/src/abstract/oprf.ts +383 -194
- package/src/abstract/poseidon.ts +235 -35
- package/src/abstract/tower.ts +428 -159
- package/src/abstract/weierstrass.ts +710 -312
- package/src/bls12-381.ts +239 -236
- package/src/bn254.ts +107 -46
- package/src/ed25519.ts +234 -56
- package/src/ed448.ts +227 -57
- package/src/index.ts +7 -1
- package/src/misc.ts +154 -35
- package/src/nist.ts +143 -20
- package/src/secp256k1.ts +284 -41
- package/src/utils.ts +583 -81
- package/src/webcrypto.ts +302 -73
- package/utils.d.ts +457 -24
- package/utils.d.ts.map +1 -1
- package/utils.js +410 -53
- package/utils.js.map +1 -1
- package/webcrypto.d.ts +167 -25
- package/webcrypto.d.ts.map +1 -1
- package/webcrypto.js +165 -58
- package/webcrypto.js.map +1 -1
package/src/ed448.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Edwards448 (
|
|
2
|
+
* Edwards448 (also called Goldilocks) curve with following addons:
|
|
3
3
|
* - X448 ECDH
|
|
4
4
|
* - Decaf cofactor elimination
|
|
5
5
|
* - Elligator hash-to-group / point indistinguishability
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type EdwardsPoint,
|
|
21
21
|
type EdwardsPointCons,
|
|
22
22
|
} from './abstract/edwards.ts';
|
|
23
|
+
import { createFROST, type FROST } from './abstract/frost.ts';
|
|
23
24
|
import {
|
|
24
25
|
_DST_scalar,
|
|
25
26
|
createHasher,
|
|
@@ -30,8 +31,15 @@ import {
|
|
|
30
31
|
} from './abstract/hash-to-curve.ts';
|
|
31
32
|
import { Field, FpInvertBatch, isNegativeLE, mod, pow2, type IField } from './abstract/modular.ts';
|
|
32
33
|
import { montgomery, type MontgomeryECDH } from './abstract/montgomery.ts';
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
34
|
+
import { createOPRF, type OPRF } from './abstract/oprf.ts';
|
|
35
|
+
import {
|
|
36
|
+
abytes,
|
|
37
|
+
asciiToBytes,
|
|
38
|
+
bytesToNumberLE,
|
|
39
|
+
equalBytes,
|
|
40
|
+
type TArg,
|
|
41
|
+
type TRet,
|
|
42
|
+
} from './utils.ts';
|
|
35
43
|
|
|
36
44
|
// edwards448 curve
|
|
37
45
|
// a = 1n
|
|
@@ -39,7 +47,7 @@ import { abytes, asciiToBytes, bytesToNumberLE, equalBytes } from './utils.ts';
|
|
|
39
47
|
// Finite field 2n**448n - 2n**224n - 1n
|
|
40
48
|
// Subgroup order
|
|
41
49
|
// 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
|
|
42
|
-
const ed448_CURVE_p = BigInt(
|
|
50
|
+
const ed448_CURVE_p = /* @__PURE__ */ BigInt(
|
|
43
51
|
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
|
44
52
|
);
|
|
45
53
|
const ed448_CURVE: EdwardsOpts = /* @__PURE__ */ (() => ({
|
|
@@ -60,9 +68,14 @@ const ed448_CURVE: EdwardsOpts = /* @__PURE__ */ (() => ({
|
|
|
60
68
|
),
|
|
61
69
|
}))();
|
|
62
70
|
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
71
|
+
// This is not RFC 8032 edwards448 / Goldilocks (`ed448` below, d = -39081).
|
|
72
|
+
// It is NIST SP 800-186 §3.2.3.3 E448, the Curve448-isomorphic Edwards model
|
|
73
|
+
// also described in draft-ietf-lwig-curve-representations-23 Appendix M, with
|
|
74
|
+
// d = 39082/39081 and Gy = 3/2.
|
|
75
|
+
// RFC 7748's literal Edwards point / birational map are wrong here: the literal
|
|
76
|
+
// point is the wrong-sign (Gx, -Gy) order-2*n variant. Keep the corrected
|
|
77
|
+
// prime-order (Gx, Gy) base so Point.BASE stays a subgroup generator, which is
|
|
78
|
+
// what noble's generic Edwards API expects.
|
|
66
79
|
const E448_CURVE: EdwardsOpts = /* @__PURE__ */ (() =>
|
|
67
80
|
Object.assign({}, ed448_CURVE, {
|
|
68
81
|
d: BigInt(
|
|
@@ -80,9 +93,9 @@ const shake256_114 = /* @__PURE__ */ wrapConstructor(() => shake256.create({ dkL
|
|
|
80
93
|
const shake256_64 = /* @__PURE__ */ wrapConstructor(() => shake256.create({ dkLen: 64 }));
|
|
81
94
|
|
|
82
95
|
// prettier-ignore
|
|
83
|
-
const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = /* @__PURE__ */ BigInt(4), _11n = BigInt(11);
|
|
96
|
+
const _1n = /* @__PURE__ */ BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3), _4n = /* @__PURE__ */ BigInt(4), _11n = /* @__PURE__ */ BigInt(11);
|
|
84
97
|
// prettier-ignore
|
|
85
|
-
const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);
|
|
98
|
+
const _22n = /* @__PURE__ */ BigInt(22), _44n = /* @__PURE__ */ BigInt(44), _88n = /* @__PURE__ */ BigInt(88), _223n = /* @__PURE__ */ BigInt(223);
|
|
86
99
|
|
|
87
100
|
// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
|
|
88
101
|
// Used for efficient square root calculation.
|
|
@@ -104,18 +117,21 @@ function ed448_pow_Pminus3div4(x: bigint): bigint {
|
|
|
104
117
|
return (pow2(b223, _223n, P) * b222) % P;
|
|
105
118
|
}
|
|
106
119
|
|
|
107
|
-
|
|
120
|
+
// Mutates and returns the provided buffer in place. The final `bytes[56] = 0`
|
|
121
|
+
// write is the Ed448 path; for 56-byte X448 inputs it is an out-of-bounds no-op.
|
|
122
|
+
function adjustScalarBytes(bytes: TArg<Uint8Array>): TRet<Uint8Array> {
|
|
108
123
|
// Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0,
|
|
109
124
|
bytes[0] &= 252; // 0b11111100
|
|
110
125
|
// and the most significant bit of the last byte to 1.
|
|
111
126
|
bytes[55] |= 128; // 0b10000000
|
|
112
127
|
// NOTE: is NOOP for 56 bytes scalars (X25519/X448)
|
|
113
128
|
bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
|
|
114
|
-
return bytes
|
|
129
|
+
return bytes as TRet<Uint8Array>;
|
|
115
130
|
}
|
|
116
131
|
|
|
117
|
-
// Constant-time
|
|
118
|
-
//
|
|
132
|
+
// Constant-time Ed448 decode helper for RFC 8032 §5.2.3 steps 2-3. Unlike
|
|
133
|
+
// `SQRT_RATIO_M1`, the returned `value` only has the documented meaning when
|
|
134
|
+
// `isValid` is true.
|
|
119
135
|
function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } {
|
|
120
136
|
const P = ed448_CURVE_p;
|
|
121
137
|
// https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3
|
|
@@ -137,34 +153,50 @@ function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } {
|
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
// Finite field 2n**448n - 2n**224n - 1n
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
// -
|
|
156
|
+
// RFC 8032 encodes Ed448 field/scalar elements in 57 bytes even though field
|
|
157
|
+
// values fit in 448 bits and scalars in 446 bits. Noble models that with a
|
|
158
|
+
// 456-bit storage width so the final-octet x-sign bit (bit 455) still fits in
|
|
159
|
+
// the shared little-endian container.
|
|
143
160
|
const Fp = /* @__PURE__ */ (() => Field(ed448_CURVE_p, { BITS: 456, isLE: true }))();
|
|
161
|
+
// Same 57-byte container shape as `Fp`; canonical scalar encodings still have
|
|
162
|
+
// the top ten bits clear per RFC 8032.
|
|
144
163
|
const Fn = /* @__PURE__ */ (() => Field(ed448_CURVE.n, { BITS: 456, isLE: true }))();
|
|
145
|
-
// decaf448
|
|
164
|
+
// Generic 56-byte field shape used by decaf448 and raw X448 u-coordinates.
|
|
165
|
+
// Plain `Field` decoding stays canonical here, so callers that want RFC 7748's
|
|
166
|
+
// modulo-p acceptance must reduce externally.
|
|
146
167
|
const Fp448 = /* @__PURE__ */ (() => Field(ed448_CURVE_p, { BITS: 448, isLE: true }))();
|
|
168
|
+
// Strict 56-byte scalar parser matching RFC 9496's recommended canonical form.
|
|
147
169
|
const Fn448 = /* @__PURE__ */ (() => Field(ed448_CURVE.n, { BITS: 448, isLE: true }))();
|
|
148
170
|
|
|
149
171
|
// SHAKE256(dom4(phflag,context)||x, 114)
|
|
150
|
-
|
|
172
|
+
// RFC 8032 `dom4` prefix. Empty contexts are valid; the accepted length range
|
|
173
|
+
// is 0..255 octets inclusive.
|
|
174
|
+
function dom4(data: TArg<Uint8Array>, ctx: TArg<Uint8Array>, phflag: boolean): TRet<Uint8Array> {
|
|
151
175
|
if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length);
|
|
152
176
|
return concatBytes(
|
|
153
177
|
asciiToBytes('SigEd448'),
|
|
154
178
|
new Uint8Array([phflag ? 1 : 0, ctx.length]),
|
|
155
179
|
ctx,
|
|
156
180
|
data
|
|
157
|
-
)
|
|
181
|
+
) as TRet<Uint8Array>;
|
|
158
182
|
}
|
|
159
183
|
const ed448_Point = /* @__PURE__ */ edwards(ed448_CURVE, { Fp, Fn, uvRatio });
|
|
160
184
|
|
|
161
|
-
|
|
162
|
-
|
|
185
|
+
// Shared internal factory for both `ed448` and `ed448ph`; callers are only
|
|
186
|
+
// expected to override narrow family options such as prehashing.
|
|
187
|
+
function ed4(opts: TArg<EdDSAOpts>) {
|
|
188
|
+
return eddsa(
|
|
189
|
+
ed448_Point,
|
|
190
|
+
shake256_114,
|
|
191
|
+
Object.assign({ adjustScalarBytes, domain: dom4 }, opts as EdDSAOpts)
|
|
192
|
+
);
|
|
163
193
|
}
|
|
164
194
|
|
|
165
195
|
/**
|
|
166
196
|
* ed448 EdDSA curve and methods.
|
|
167
197
|
* @example
|
|
198
|
+
* Generate one Ed448 keypair, sign a message, and verify it.
|
|
199
|
+
*
|
|
168
200
|
* ```js
|
|
169
201
|
* import { ed448 } from '@noble/curves/ed448.js';
|
|
170
202
|
* const { secretKey, publicKey } = ed448.keygen();
|
|
@@ -177,18 +209,47 @@ function ed4(opts: EdDSAOpts) {
|
|
|
177
209
|
export const ed448: EdDSA = /* @__PURE__ */ ed4({});
|
|
178
210
|
|
|
179
211
|
// There is no ed448ctx, since ed448 supports ctx by default
|
|
180
|
-
/**
|
|
212
|
+
/**
|
|
213
|
+
* Prehashed version of ed448. See {@link ed448}
|
|
214
|
+
* @example
|
|
215
|
+
* Use the prehashed Ed448 variant for one message.
|
|
216
|
+
*
|
|
217
|
+
* ```ts
|
|
218
|
+
* const { secretKey, publicKey } = ed448ph.keygen();
|
|
219
|
+
* const msg = new TextEncoder().encode('hello noble');
|
|
220
|
+
* const sig = ed448ph.sign(msg, secretKey);
|
|
221
|
+
* const isValid = ed448ph.verify(sig, msg, publicKey);
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
181
224
|
export const ed448ph: EdDSA = /* @__PURE__ */ ed4({ prehash: shake256_64 });
|
|
182
225
|
/**
|
|
183
|
-
* E448
|
|
184
|
-
*
|
|
226
|
+
* E448 here is NIST SP 800-186 §3.2.3.3 E448, the Edwards representation of
|
|
227
|
+
* Curve448, not RFC 8032 edwards448 / Goldilocks.
|
|
228
|
+
* Goldilocks is the separate 4-isogenous curve exposed as `ed448`.
|
|
229
|
+
* We keep the corrected prime-order base here; RFC 7748's literal Edwards
|
|
230
|
+
* point / map are wrong for this curve model, and the literal point is the
|
|
231
|
+
* wrong-sign order-2*n variant.
|
|
232
|
+
* @param X - Projective X coordinate.
|
|
233
|
+
* @param Y - Projective Y coordinate.
|
|
234
|
+
* @param Z - Projective Z coordinate.
|
|
235
|
+
* @param T - Projective T coordinate.
|
|
236
|
+
* @example
|
|
237
|
+
* Multiply the E448 base point.
|
|
238
|
+
*
|
|
239
|
+
* ```ts
|
|
240
|
+
* const point = E448.BASE.multiply(2n);
|
|
241
|
+
* ```
|
|
185
242
|
*/
|
|
186
243
|
export const E448: EdwardsPointCons = /* @__PURE__ */ edwards(E448_CURVE);
|
|
187
244
|
|
|
188
245
|
/**
|
|
189
246
|
* ECDH using curve448 aka x448.
|
|
247
|
+
* The wrapper aborts on all-zero shared secrets by default, and seeded
|
|
248
|
+
* `keygen(seed)` reuses the provided 56-byte seed buffer instead of copying it.
|
|
190
249
|
*
|
|
191
250
|
* @example
|
|
251
|
+
* Derive one shared secret between two X448 peers.
|
|
252
|
+
*
|
|
192
253
|
* ```js
|
|
193
254
|
* import { x448 } from '@noble/curves/ed448.js';
|
|
194
255
|
* const alice = x448.keygen();
|
|
@@ -196,7 +257,7 @@ export const E448: EdwardsPointCons = /* @__PURE__ */ edwards(E448_CURVE);
|
|
|
196
257
|
* const shared = x448.getSharedSecret(alice.secretKey, bob.publicKey);
|
|
197
258
|
* ```
|
|
198
259
|
*/
|
|
199
|
-
export const x448: MontgomeryECDH = /* @__PURE__ */ (() => {
|
|
260
|
+
export const x448: TRet<MontgomeryECDH> = /* @__PURE__ */ (() => {
|
|
200
261
|
const P = ed448_CURVE_p;
|
|
201
262
|
return montgomery({
|
|
202
263
|
P,
|
|
@@ -211,9 +272,12 @@ export const x448: MontgomeryECDH = /* @__PURE__ */ (() => {
|
|
|
211
272
|
})();
|
|
212
273
|
|
|
213
274
|
// Hash To Curve Elligator2 Map
|
|
214
|
-
|
|
275
|
+
// 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
276
|
+
const ELL2_C1 = /* @__PURE__ */ (() => (ed448_CURVE_p - BigInt(3)) / BigInt(4))();
|
|
215
277
|
const ELL2_J = /* @__PURE__ */ BigInt(156326);
|
|
216
278
|
|
|
279
|
+
// Returns RFC 9380 Appendix G.2.3 rational Montgomery numerators/denominators
|
|
280
|
+
// `{ xn, xd, yn, yd }`, not an affine point.
|
|
217
281
|
function map_to_curve_elligator2_curve448(u: bigint) {
|
|
218
282
|
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
|
|
219
283
|
let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1
|
|
@@ -231,7 +295,8 @@ function map_to_curve_elligator2_curve448(u: bigint) {
|
|
|
231
295
|
tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
|
|
232
296
|
let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
|
|
233
297
|
y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
|
|
234
|
-
|
|
298
|
+
// 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
|
|
299
|
+
let x2n = Fp.mul(x1n, Fp.neg(tv1));
|
|
235
300
|
let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
|
|
236
301
|
y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
|
|
237
302
|
tv2 = Fp.sqr(y1); // 20. tv2 = y1^2
|
|
@@ -244,8 +309,10 @@ function map_to_curve_elligator2_curve448(u: bigint) {
|
|
|
244
309
|
return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
|
|
245
310
|
}
|
|
246
311
|
|
|
312
|
+
// Returns affine `{ x, y }` after inverting the Appendix G.2.4 denominators.
|
|
247
313
|
function map_to_curve_elligator2_edwards448(u: bigint) {
|
|
248
|
-
|
|
314
|
+
// 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
|
|
315
|
+
let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u);
|
|
249
316
|
let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2
|
|
250
317
|
let xd2 = Fp.sqr(xd); // 3. xd2 = xd^2
|
|
251
318
|
let xd4 = Fp.sqr(xd2); // 4. xd4 = xd2^2
|
|
@@ -287,7 +354,18 @@ function map_to_curve_elligator2_edwards448(u: bigint) {
|
|
|
287
354
|
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
|
288
355
|
}
|
|
289
356
|
|
|
290
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* Hashing / encoding to ed448 points / field. RFC 9380 methods.
|
|
359
|
+
* Public `mapToCurve()` consumes one field element bigint for `m = 1`, and RFC
|
|
360
|
+
* Appendix J vectors use the special `QUUX-V01-*` test DST overrides rather
|
|
361
|
+
* than the default suite IDs below.
|
|
362
|
+
* @example
|
|
363
|
+
* Hash one message onto the ed448 curve.
|
|
364
|
+
*
|
|
365
|
+
* ```ts
|
|
366
|
+
* const point = ed448_hasher.hashToCurve(new TextEncoder().encode('hello noble'));
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
291
369
|
export const ed448_hasher: H2CHasher<EdwardsPointCons> = /* @__PURE__ */ (() =>
|
|
292
370
|
createHasher(ed448_Point, (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), {
|
|
293
371
|
DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
|
|
@@ -298,6 +376,32 @@ export const ed448_hasher: H2CHasher<EdwardsPointCons> = /* @__PURE__ */ (() =>
|
|
|
298
376
|
expand: 'xof',
|
|
299
377
|
hash: shake256,
|
|
300
378
|
}))();
|
|
379
|
+
/**
|
|
380
|
+
* FROST threshold signatures over ed448. RFC 9591.
|
|
381
|
+
* @example
|
|
382
|
+
* Create one trusted-dealer package for 2-of-3 ed448 signing.
|
|
383
|
+
*
|
|
384
|
+
* ```ts
|
|
385
|
+
* const alice = ed448_FROST.Identifier.derive('alice@example.com');
|
|
386
|
+
* const bob = ed448_FROST.Identifier.derive('bob@example.com');
|
|
387
|
+
* const carol = ed448_FROST.Identifier.derive('carol@example.com');
|
|
388
|
+
* const deal = ed448_FROST.trustedDealer({ min: 2, max: 3 }, [alice, bob, carol]);
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
export const ed448_FROST: TRet<FROST> = /* @__PURE__ */ (() =>
|
|
392
|
+
createFROST({
|
|
393
|
+
name: 'FROST-ED448-SHAKE256-v1',
|
|
394
|
+
Point: ed448_Point,
|
|
395
|
+
validatePoint: (p) => {
|
|
396
|
+
p.assertValidity();
|
|
397
|
+
if (!p.isTorsionFree()) throw new Error('bad point: not torsion-free');
|
|
398
|
+
},
|
|
399
|
+
// Group: edwards448 [RFC8032], where Ne = 57 and Ns = 57.
|
|
400
|
+
// Fn is 57 bytes, Fp is 57 bytes too
|
|
401
|
+
Fn,
|
|
402
|
+
hash: shake256_114,
|
|
403
|
+
H2: 'SigEd448\0\0',
|
|
404
|
+
}))();
|
|
301
405
|
|
|
302
406
|
// 1-d
|
|
303
407
|
const ONE_MINUS_D = /* @__PURE__ */ BigInt('39082');
|
|
@@ -311,13 +415,22 @@ const SQRT_MINUS_D = /* @__PURE__ */ BigInt(
|
|
|
311
415
|
const INVSQRT_MINUS_D = /* @__PURE__ */ BigInt(
|
|
312
416
|
'315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716'
|
|
313
417
|
);
|
|
314
|
-
//
|
|
315
|
-
|
|
418
|
+
// RFC 9496 `SQRT_RATIO_M1` must return `CT_ABS(s)`, i.e. the nonnegative root.
|
|
419
|
+
// Keep this Decaf-local: RFC 9496 decode/encode/map formulas depend on that
|
|
420
|
+
// canonical representative, while ordinary Ed448 decoding still uses `uvRatio()`
|
|
421
|
+
// plus the public sign bit from RFC 8032.
|
|
422
|
+
const sqrtRatioM1 = (u: bigint, v: bigint) => {
|
|
423
|
+
const P = ed448_CURVE_p;
|
|
424
|
+
const { isValid, value } = uvRatio(u, v);
|
|
425
|
+
return { isValid, value: isNegativeLE(value, P) ? Fp448.create(-value) : value };
|
|
426
|
+
};
|
|
427
|
+
const invertSqrt = (number: bigint) => sqrtRatioM1(_1n, number);
|
|
316
428
|
|
|
317
429
|
/**
|
|
318
430
|
* Elligator map for hash-to-curve of decaf448.
|
|
319
|
-
*
|
|
320
|
-
* and
|
|
431
|
+
* Primary formula source is RFC 9496 §5.3.4. Step 1 intentionally reduces the
|
|
432
|
+
* input modulo `p`, and the return value is the internal Edwards
|
|
433
|
+
* representation, not a public decaf encoding.
|
|
321
434
|
*/
|
|
322
435
|
function calcElligatorDecafMap(r0: bigint): EdwardsPoint {
|
|
323
436
|
const { d, p: P } = ed448_CURVE;
|
|
@@ -327,7 +440,7 @@ function calcElligatorDecafMap(r0: bigint): EdwardsPoint {
|
|
|
327
440
|
const u0 = mod(d * (r - _1n)); // 2
|
|
328
441
|
const u1 = mod((u0 + _1n) * (u0 - r)); // 3
|
|
329
442
|
|
|
330
|
-
const { isValid: was_square, value: v } =
|
|
443
|
+
const { isValid: was_square, value: v } = sqrtRatioM1(ONE_MINUS_TWO_D, mod((r + _1n) * u1)); // 4
|
|
331
444
|
|
|
332
445
|
let v_prime = v; // 5
|
|
333
446
|
if (!was_square) v_prime = mod(r0 * v);
|
|
@@ -347,6 +460,19 @@ function calcElligatorDecafMap(r0: bigint): EdwardsPoint {
|
|
|
347
460
|
return new ed448_Point(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
|
|
348
461
|
}
|
|
349
462
|
|
|
463
|
+
// Keep the Decaf448 base representative literal here: deriving it with
|
|
464
|
+
// `new _DecafPoint(ed448_Point.BASE).multiplyUnsafe(2)` forces eager WNAF precomputes and
|
|
465
|
+
// adds about 100ms to `ed448.js` import time.
|
|
466
|
+
const DECAF_BASE_X = /* @__PURE__ */ BigInt(
|
|
467
|
+
'0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555'
|
|
468
|
+
);
|
|
469
|
+
const DECAF_BASE_Y = /* @__PURE__ */ BigInt(
|
|
470
|
+
'0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed'
|
|
471
|
+
);
|
|
472
|
+
const DECAF_BASE_T = /* @__PURE__ */ BigInt(
|
|
473
|
+
'0x696d84643374bace9d70983a12aa9d461da74d2d5c35e8d97ba72c3aba4450a5d29274229bd22c1d5e3a6474ee4ffb0e7a9e200a28eee402'
|
|
474
|
+
);
|
|
475
|
+
|
|
350
476
|
/**
|
|
351
477
|
* Each ed448/EdwardsPoint has 4 different equivalent points. This can be
|
|
352
478
|
* a source of bugs for protocols like ring signatures. Decaf was created to solve this.
|
|
@@ -358,7 +484,7 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
358
484
|
// The following gymnastics is done because typescript strips comments otherwise
|
|
359
485
|
// prettier-ignore
|
|
360
486
|
static BASE: _DecafPoint =
|
|
361
|
-
/* @__PURE__ */ (() => new _DecafPoint(ed448_Point
|
|
487
|
+
/* @__PURE__ */ (() => new _DecafPoint(new ed448_Point(DECAF_BASE_X, DECAF_BASE_Y, _1n, DECAF_BASE_T)))();
|
|
362
488
|
// prettier-ignore
|
|
363
489
|
static ZERO: _DecafPoint =
|
|
364
490
|
/* @__PURE__ */ (() => new _DecafPoint(ed448_Point.ZERO))();
|
|
@@ -373,6 +499,12 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
373
499
|
super(ep);
|
|
374
500
|
}
|
|
375
501
|
|
|
502
|
+
/**
|
|
503
|
+
* Create one Decaf448 point from affine Edwards coordinates.
|
|
504
|
+
* This wraps the internal Edwards representative directly and is not a
|
|
505
|
+
* canonical decaf448 decoding path.
|
|
506
|
+
* Use `toBytes()` / `fromBytes()` if canonical decaf448 bytes matter.
|
|
507
|
+
*/
|
|
376
508
|
static fromAffine(ap: AffinePoint<bigint>): _DecafPoint {
|
|
377
509
|
return new _DecafPoint(ed448_Point.fromAffine(ap));
|
|
378
510
|
}
|
|
@@ -385,7 +517,7 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
385
517
|
return new _DecafPoint(ep);
|
|
386
518
|
}
|
|
387
519
|
|
|
388
|
-
static fromBytes(bytes: Uint8Array): _DecafPoint {
|
|
520
|
+
static fromBytes(bytes: TArg<Uint8Array>): _DecafPoint {
|
|
389
521
|
abytes(bytes, 56);
|
|
390
522
|
const { d, p: P } = ed448_CURVE;
|
|
391
523
|
const mod = (n: bigint) => Fp448.create(n);
|
|
@@ -417,7 +549,7 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
417
549
|
/**
|
|
418
550
|
* Converts decaf-encoded string to decaf point.
|
|
419
551
|
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-decode-2).
|
|
420
|
-
* @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding
|
|
552
|
+
* @param hex - Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding
|
|
421
553
|
*/
|
|
422
554
|
static fromHex(hex: string): _DecafPoint {
|
|
423
555
|
return _DecafPoint.fromBytes(hexToBytes(hex));
|
|
@@ -427,7 +559,7 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
427
559
|
* Encodes decaf point to Uint8Array.
|
|
428
560
|
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-encode-2).
|
|
429
561
|
*/
|
|
430
|
-
toBytes(): Uint8Array {
|
|
562
|
+
toBytes(): TRet<Uint8Array> {
|
|
431
563
|
const { X, Z, T } = this.ep;
|
|
432
564
|
const P = ed448_CURVE.p;
|
|
433
565
|
const mod = (n: bigint) => Fp448.create(n);
|
|
@@ -439,7 +571,7 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
439
571
|
const u2 = mod(INVSQRT_MINUS_D * ratio * Z - T); // 4
|
|
440
572
|
let s = mod(ONE_MINUS_D * invsqrt * X * u2); // 5
|
|
441
573
|
if (isNegativeLE(s, P)) s = mod(-s);
|
|
442
|
-
return Fn448.toBytes(s)
|
|
574
|
+
return Fn448.toBytes(s) as TRet<Uint8Array>;
|
|
443
575
|
}
|
|
444
576
|
|
|
445
577
|
/**
|
|
@@ -458,16 +590,33 @@ class _DecafPoint extends PrimeEdwardsPoint<_DecafPoint> {
|
|
|
458
590
|
return this.equals(_DecafPoint.ZERO);
|
|
459
591
|
}
|
|
460
592
|
}
|
|
593
|
+
Object.freeze(_DecafPoint.BASE);
|
|
594
|
+
Object.freeze(_DecafPoint.ZERO);
|
|
595
|
+
Object.freeze(_DecafPoint.prototype);
|
|
596
|
+
Object.freeze(_DecafPoint);
|
|
461
597
|
|
|
598
|
+
/** Prime-order Decaf448 group bundle. */
|
|
462
599
|
export const decaf448: {
|
|
463
600
|
Point: typeof _DecafPoint;
|
|
464
|
-
} = { Point: _DecafPoint };
|
|
601
|
+
} = /* @__PURE__ */ Object.freeze({ Point: _DecafPoint });
|
|
465
602
|
|
|
466
|
-
/**
|
|
467
|
-
|
|
603
|
+
/**
|
|
604
|
+
* Hashing to decaf448 points / field. RFC 9380 methods.
|
|
605
|
+
* `hashToCurve()` is RFC 9380 `hash_to_decaf448`, `deriveToCurve()` is RFC
|
|
606
|
+
* 9496 element derivation, and `hashToScalar()` is a library helper layered on
|
|
607
|
+
* top of RFC 9496 scalar reduction.
|
|
608
|
+
* @example
|
|
609
|
+
* Hash one message onto decaf448.
|
|
610
|
+
*
|
|
611
|
+
* ```ts
|
|
612
|
+
* const point = decaf448_hasher.hashToCurve(new TextEncoder().encode('hello noble'));
|
|
613
|
+
* ```
|
|
614
|
+
*/
|
|
615
|
+
export const decaf448_hasher: H2CHasherBase<typeof _DecafPoint> = Object.freeze({
|
|
468
616
|
Point: _DecafPoint,
|
|
469
|
-
hashToCurve(msg: Uint8Array
|
|
470
|
-
|
|
617
|
+
hashToCurve(msg: TArg<Uint8Array>, options?: TArg<H2CDSTOpts>): _DecafPoint {
|
|
618
|
+
// Preserve explicit empty/invalid DST overrides so expand_message_xof() can reject them.
|
|
619
|
+
const DST = options?.DST === undefined ? 'decaf448_XOF:SHAKE256_D448MAP_RO_' : options.DST;
|
|
471
620
|
return decaf448_hasher.deriveToCurve!(expand_message_xof(msg, DST, 112, 224, shake256));
|
|
472
621
|
},
|
|
473
622
|
/**
|
|
@@ -475,7 +624,7 @@ export const decaf448_hasher: H2CHasherBase<typeof _DecafPoint> = {
|
|
|
475
624
|
* RFC is invalid. RFC says "use 64-byte xof", while for 2^-112 bias
|
|
476
625
|
* it must use 84-byte xof (56+56/2), not 64.
|
|
477
626
|
*/
|
|
478
|
-
hashToScalar(msg: Uint8Array
|
|
627
|
+
hashToScalar(msg: TArg<Uint8Array>, options: TArg<H2CDSTOpts> = { DST: _DST_scalar }): bigint {
|
|
479
628
|
// Can't use `Fn448.fromBytes()`. 64-byte input => 56-byte field element
|
|
480
629
|
const xof = expand_message_xof(msg, options.DST, 64, 256, shake256);
|
|
481
630
|
return Fn448.create(bytesToNumberLE(xof));
|
|
@@ -484,10 +633,12 @@ export const decaf448_hasher: H2CHasherBase<typeof _DecafPoint> = {
|
|
|
484
633
|
* HashToCurve-like construction based on RFC 9496 (Element Derivation).
|
|
485
634
|
* Converts 112 uniform random bytes into a curve point.
|
|
486
635
|
*
|
|
487
|
-
* WARNING: This represents an older hash-to-curve construction
|
|
488
|
-
*
|
|
636
|
+
* WARNING: This represents an older hash-to-curve construction from before
|
|
637
|
+
* RFC 9380 was finalized.
|
|
638
|
+
* It was later reused as a component in the newer
|
|
639
|
+
* `hash_to_decaf448` function defined in RFC 9380.
|
|
489
640
|
*/
|
|
490
|
-
deriveToCurve(bytes: Uint8Array): _DecafPoint {
|
|
641
|
+
deriveToCurve(bytes: TArg<Uint8Array>): _DecafPoint {
|
|
491
642
|
abytes(bytes, 112);
|
|
492
643
|
const skipValidation = true;
|
|
493
644
|
// Note: Similar to the field element decoding described in
|
|
@@ -499,14 +650,26 @@ export const decaf448_hasher: H2CHasherBase<typeof _DecafPoint> = {
|
|
|
499
650
|
const R2 = calcElligatorDecafMap(r2);
|
|
500
651
|
return new _DecafPoint(R1.add(R2));
|
|
501
652
|
},
|
|
502
|
-
};
|
|
653
|
+
});
|
|
503
654
|
|
|
504
|
-
/**
|
|
505
|
-
|
|
506
|
-
|
|
655
|
+
/**
|
|
656
|
+
* decaf448 OPRF, defined in RFC 9497.
|
|
657
|
+
* @example
|
|
658
|
+
* Run one blind/evaluate/finalize OPRF round over decaf448.
|
|
659
|
+
*
|
|
660
|
+
* ```ts
|
|
661
|
+
* const input = new TextEncoder().encode('hello noble');
|
|
662
|
+
* const keys = decaf448_oprf.oprf.generateKeyPair();
|
|
663
|
+
* const blind = decaf448_oprf.oprf.blind(input);
|
|
664
|
+
* const evaluated = decaf448_oprf.oprf.blindEvaluate(keys.secretKey, blind.blinded);
|
|
665
|
+
* const output = decaf448_oprf.oprf.finalize(input, blind.blind, evaluated);
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
export const decaf448_oprf: TRet<OPRF> = /* @__PURE__ */ (() =>
|
|
669
|
+
createOPRF({
|
|
507
670
|
name: 'decaf448-SHAKE256',
|
|
508
671
|
Point: _DecafPoint,
|
|
509
|
-
hash: (msg: Uint8Array) => shake256(msg, { dkLen: 64 }),
|
|
672
|
+
hash: (msg: TArg<Uint8Array>) => shake256(msg, { dkLen: 64 }),
|
|
510
673
|
hashToGroup: decaf448_hasher.hashToCurve,
|
|
511
674
|
hashToScalar: decaf448_hasher.hashToScalar,
|
|
512
675
|
}))();
|
|
@@ -514,12 +677,19 @@ export const decaf448_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
|
514
677
|
/**
|
|
515
678
|
* Weird / bogus points, useful for debugging.
|
|
516
679
|
* Unlike ed25519, there is no ed448 generator point which can produce full T subgroup.
|
|
517
|
-
* Instead,
|
|
518
|
-
* (
|
|
680
|
+
* Instead, the torsion subgroup here is cyclic of order 4, generated by
|
|
681
|
+
* `(1, 0)`, and the array below lists that subgroup set (Klein four-group).
|
|
682
|
+
* @example
|
|
683
|
+
* Decode one known torsion point for debugging.
|
|
684
|
+
*
|
|
685
|
+
* ```ts
|
|
686
|
+
* import { ED448_TORSION_SUBGROUP, ed448 } from '@noble/curves/ed448.js';
|
|
687
|
+
* const point = ed448.Point.fromHex(ED448_TORSION_SUBGROUP[1]);
|
|
688
|
+
* ```
|
|
519
689
|
*/
|
|
520
|
-
export const ED448_TORSION_SUBGROUP: string[] = [
|
|
690
|
+
export const ED448_TORSION_SUBGROUP: readonly string[] = /* @__PURE__ */ Object.freeze([
|
|
521
691
|
'010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
522
692
|
'fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff00',
|
|
523
693
|
'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
524
694
|
'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080',
|
|
525
|
-
];
|
|
695
|
+
]);
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,13 @@ import { ed448, ed448ph, x448, decaf448 } from '@noble/curves/ed448.js';
|
|
|
9
9
|
import { p256, p384, p521 } from '@noble/curves/nist.js';
|
|
10
10
|
import { bls12_381 } from '@noble/curves/bls12-381.js';
|
|
11
11
|
import { bn254 } from '@noble/curves/bn254.js';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
jubjub,
|
|
14
|
+
babyjubjub,
|
|
15
|
+
brainpoolP256r1,
|
|
16
|
+
brainpoolP384r1,
|
|
17
|
+
brainpoolP512r1,
|
|
18
|
+
} from '@noble/curves/misc.js';
|
|
13
19
|
import * as webcrypto from '@noble/curves/webcrypto.js';
|
|
14
20
|
|
|
15
21
|
// hash-to-curve
|