@noble/curves 1.1.0 → 1.3.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 +295 -258
- package/abstract/bls.d.ts +27 -10
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +60 -10
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +2 -2
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +22 -16
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +51 -11
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +79 -21
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +5 -7
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +39 -41
- package/abstract/poseidon.js.map +1 -1
- package/abstract/utils.d.ts +3 -1
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +56 -31
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +25 -28
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +17 -15
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +142 -88
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +3 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +3 -2
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +5 -2
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +17 -8
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +53 -2
- package/ed448.d.ts.map +1 -1
- package/ed448.js +216 -29
- package/ed448.js.map +1 -1
- package/esm/abstract/bls.js +61 -11
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.js +23 -17
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.js +75 -20
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.js +5 -7
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.js +39 -41
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/utils.js +54 -30
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.js +17 -15
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +143 -89
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.js +3 -2
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.js +17 -8
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.js +218 -32
- package/esm/ed448.js.map +1 -1
- package/esm/jubjub.js +1 -1
- package/esm/jubjub.js.map +1 -1
- package/esm/p256.js +2 -2
- package/esm/p256.js.map +1 -1
- package/esm/p384.js +2 -2
- package/esm/p384.js.map +1 -1
- package/esm/p521.js +3 -3
- package/esm/p521.js.map +1 -1
- package/esm/package.json +1 -4
- package/esm/secp256k1.js +6 -6
- package/esm/secp256k1.js.map +1 -1
- package/jubjub.js.map +1 -1
- package/p256.js +2 -2
- package/p256.js.map +1 -1
- package/p384.js +2 -2
- package/p384.js.map +1 -1
- package/p521.js +3 -3
- package/p521.js.map +1 -1
- package/package.json +7 -6
- package/secp256k1.js +6 -6
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +120 -22
- package/src/abstract/hash-to-curve.ts +24 -17
- package/src/abstract/modular.ts +81 -22
- package/src/abstract/montgomery.ts +4 -6
- package/src/abstract/poseidon.ts +39 -40
- package/src/abstract/utils.ts +55 -26
- package/src/abstract/weierstrass.ts +29 -18
- package/src/bls12-381.ts +132 -75
- package/src/bn254.ts +3 -2
- package/src/ed25519.ts +19 -8
- package/src/ed448.ts +267 -34
- package/src/jubjub.ts +1 -1
package/src/ed448.ts
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
2
|
import { shake256 } from '@noble/hashes/sha3';
|
|
3
3
|
import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils';
|
|
4
|
-
import { twistedEdwards } from './abstract/edwards.js';
|
|
5
|
-
import { mod, pow2, Field } from './abstract/modular.js';
|
|
4
|
+
import { ExtPointType, twistedEdwards } from './abstract/edwards.js';
|
|
5
|
+
import { mod, pow2, Field, isNegativeLE } from './abstract/modular.js';
|
|
6
6
|
import { montgomery } from './abstract/montgomery.js';
|
|
7
|
-
import { createHasher } from './abstract/hash-to-curve.js';
|
|
7
|
+
import { createHasher, htfBasicOpts, expand_message_xof } from './abstract/hash-to-curve.js';
|
|
8
|
+
import {
|
|
9
|
+
bytesToHex,
|
|
10
|
+
bytesToNumberLE,
|
|
11
|
+
ensureBytes,
|
|
12
|
+
equalBytes,
|
|
13
|
+
Hex,
|
|
14
|
+
numberToBytesLE,
|
|
15
|
+
} from './abstract/utils.js';
|
|
16
|
+
import { AffinePoint, Group } from './abstract/curve.js';
|
|
8
17
|
|
|
9
18
|
/**
|
|
10
19
|
* Edwards448 (not Ed448-Goldilocks) curve with following addons:
|
|
11
|
-
*
|
|
20
|
+
* - X448 ECDH
|
|
21
|
+
* - Decaf cofactor elimination
|
|
22
|
+
* - Elligator hash-to-group / point indistinguishability
|
|
12
23
|
* Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2
|
|
13
24
|
*/
|
|
14
25
|
|
|
@@ -18,15 +29,16 @@ const ed448P = BigInt(
|
|
|
18
29
|
'726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439'
|
|
19
30
|
);
|
|
20
31
|
|
|
32
|
+
// prettier-ignore
|
|
33
|
+
const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4), _11n = BigInt(11);
|
|
34
|
+
// prettier-ignore
|
|
35
|
+
const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);
|
|
36
|
+
|
|
21
37
|
// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
|
|
22
38
|
// Used for efficient square root calculation.
|
|
23
39
|
// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]
|
|
24
40
|
function ed448_pow_Pminus3div4(x: bigint): bigint {
|
|
25
41
|
const P = ed448P;
|
|
26
|
-
// prettier-ignore
|
|
27
|
-
const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _11n = BigInt(11);
|
|
28
|
-
// prettier-ignore
|
|
29
|
-
const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);
|
|
30
42
|
const b2 = (x * x * x) % P;
|
|
31
43
|
const b3 = (b2 * b2 * x) % P;
|
|
32
44
|
const b6 = (pow2(b3, _3n, P) * b3) % P;
|
|
@@ -53,8 +65,29 @@ function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
|
|
|
53
65
|
return bytes;
|
|
54
66
|
}
|
|
55
67
|
|
|
68
|
+
// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.
|
|
69
|
+
// Uses algo from RFC8032 5.1.3.
|
|
70
|
+
function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } {
|
|
71
|
+
const P = ed448P;
|
|
72
|
+
// https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3
|
|
73
|
+
// To compute the square root of (u/v), the first step is to compute the
|
|
74
|
+
// candidate root x = (u/v)^((p+1)/4). This can be done using the
|
|
75
|
+
// following trick, to use a single modular powering for both the
|
|
76
|
+
// inversion of v and the square root:
|
|
77
|
+
// x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p)
|
|
78
|
+
const u2v = mod(u * u * v, P); // u²v
|
|
79
|
+
const u3v = mod(u2v * u, P); // u³v
|
|
80
|
+
const u5v3 = mod(u3v * u2v * v, P); // u⁵v³
|
|
81
|
+
const root = ed448_pow_Pminus3div4(u5v3);
|
|
82
|
+
const x = mod(u3v * root, P);
|
|
83
|
+
// Verify that root is exists
|
|
84
|
+
const x2 = mod(x * x, P); // x²
|
|
85
|
+
// If vx² = u, the recovered x-coordinate is x. Otherwise, no
|
|
86
|
+
// square root exists, and the decoding fails.
|
|
87
|
+
return { isValid: mod(x2 * v, P) === u, value: x };
|
|
88
|
+
}
|
|
89
|
+
|
|
56
90
|
const Fp = Field(ed448P, 456, true);
|
|
57
|
-
const _4n = BigInt(4);
|
|
58
91
|
|
|
59
92
|
const ED448_DEF = {
|
|
60
93
|
// Param: a
|
|
@@ -70,6 +103,7 @@ const ED448_DEF = {
|
|
|
70
103
|
n: BigInt(
|
|
71
104
|
'181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'
|
|
72
105
|
),
|
|
106
|
+
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
|
|
73
107
|
nBitLength: 456,
|
|
74
108
|
// Cofactor
|
|
75
109
|
h: BigInt(4),
|
|
@@ -94,39 +128,19 @@ const ED448_DEF = {
|
|
|
94
128
|
data
|
|
95
129
|
);
|
|
96
130
|
},
|
|
97
|
-
|
|
98
|
-
// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.
|
|
99
|
-
// Uses algo from RFC8032 5.1.3.
|
|
100
|
-
uvRatio: (u: bigint, v: bigint): { isValid: boolean; value: bigint } => {
|
|
101
|
-
const P = ed448P;
|
|
102
|
-
// https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.3
|
|
103
|
-
// To compute the square root of (u/v), the first step is to compute the
|
|
104
|
-
// candidate root x = (u/v)^((p+1)/4). This can be done using the
|
|
105
|
-
// following trick, to use a single modular powering for both the
|
|
106
|
-
// inversion of v and the square root:
|
|
107
|
-
// x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p)
|
|
108
|
-
const u2v = mod(u * u * v, P); // u²v
|
|
109
|
-
const u3v = mod(u2v * u, P); // u³v
|
|
110
|
-
const u5v3 = mod(u3v * u2v * v, P); // u⁵v³
|
|
111
|
-
const root = ed448_pow_Pminus3div4(u5v3);
|
|
112
|
-
const x = mod(u3v * root, P);
|
|
113
|
-
// Verify that root is exists
|
|
114
|
-
const x2 = mod(x * x, P); // x²
|
|
115
|
-
// If vx² = u, the recovered x-coordinate is x. Otherwise, no
|
|
116
|
-
// square root exists, and the decoding fails.
|
|
117
|
-
return { isValid: mod(x2 * v, P) === u, value: x };
|
|
118
|
-
},
|
|
131
|
+
uvRatio,
|
|
119
132
|
} as const;
|
|
120
133
|
|
|
121
|
-
export const ed448 = twistedEdwards(ED448_DEF);
|
|
134
|
+
export const ed448 = /* @__PURE__ */ twistedEdwards(ED448_DEF);
|
|
122
135
|
// NOTE: there is no ed448ctx, since ed448 supports ctx by default
|
|
123
|
-
export const ed448ph = twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });
|
|
136
|
+
export const ed448ph = /* @__PURE__ */ twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });
|
|
124
137
|
|
|
125
138
|
export const x448 = /* @__PURE__ */ (() =>
|
|
126
139
|
montgomery({
|
|
127
140
|
a: BigInt(156326),
|
|
141
|
+
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
|
|
128
142
|
montgomeryBits: 448,
|
|
129
|
-
nByteLength:
|
|
143
|
+
nByteLength: 56,
|
|
130
144
|
P: ed448P,
|
|
131
145
|
Gu: BigInt(5),
|
|
132
146
|
powPminus2: (x: bigint): bigint => {
|
|
@@ -152,11 +166,14 @@ export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Ar
|
|
|
152
166
|
const _1n = BigInt(1);
|
|
153
167
|
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
|
|
154
168
|
}
|
|
169
|
+
|
|
155
170
|
export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
|
|
171
|
+
// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
|
|
156
172
|
|
|
157
173
|
// Hash To Curve Elligator2 Map
|
|
158
174
|
const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
159
175
|
const ELL2_J = BigInt(156326);
|
|
176
|
+
|
|
160
177
|
function map_to_curve_elligator2_curve448(u: bigint) {
|
|
161
178
|
let tv1 = Fp.sqr(u); // 1. tv1 = u^2
|
|
162
179
|
let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1
|
|
@@ -186,6 +203,7 @@ function map_to_curve_elligator2_curve448(u: bigint) {
|
|
|
186
203
|
y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
|
|
187
204
|
return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
|
|
188
205
|
}
|
|
206
|
+
|
|
189
207
|
function map_to_curve_elligator2_edwards448(u: bigint) {
|
|
190
208
|
let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
|
|
191
209
|
let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2
|
|
@@ -245,3 +263,218 @@ const htf = /* @__PURE__ */ (() =>
|
|
|
245
263
|
))();
|
|
246
264
|
export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();
|
|
247
265
|
export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();
|
|
266
|
+
|
|
267
|
+
function assertDcfPoint(other: unknown) {
|
|
268
|
+
if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 1-d
|
|
272
|
+
const ONE_MINUS_D = BigInt('39082');
|
|
273
|
+
// 1-2d
|
|
274
|
+
const ONE_MINUS_TWO_D = BigInt('78163');
|
|
275
|
+
// √(-d)
|
|
276
|
+
const SQRT_MINUS_D = BigInt(
|
|
277
|
+
'98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214'
|
|
278
|
+
);
|
|
279
|
+
// 1 / √(-d)
|
|
280
|
+
const INVSQRT_MINUS_D = BigInt(
|
|
281
|
+
'315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716'
|
|
282
|
+
);
|
|
283
|
+
// Calculates 1/√(number)
|
|
284
|
+
const invertSqrt = (number: bigint) => uvRatio(_1n, number);
|
|
285
|
+
|
|
286
|
+
const MAX_448B = BigInt(
|
|
287
|
+
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
|
288
|
+
);
|
|
289
|
+
const bytes448ToNumberLE = (bytes: Uint8Array) =>
|
|
290
|
+
ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B);
|
|
291
|
+
|
|
292
|
+
type ExtendedPoint = ExtPointType;
|
|
293
|
+
|
|
294
|
+
// Computes Elligator map for Decaf
|
|
295
|
+
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2
|
|
296
|
+
function calcElligatorDecafMap(r0: bigint): ExtendedPoint {
|
|
297
|
+
const { d } = ed448.CURVE;
|
|
298
|
+
const P = ed448.CURVE.Fp.ORDER;
|
|
299
|
+
const mod = ed448.CURVE.Fp.create;
|
|
300
|
+
|
|
301
|
+
const r = mod(-(r0 * r0)); // 1
|
|
302
|
+
const u0 = mod(d * (r - _1n)); // 2
|
|
303
|
+
const u1 = mod((u0 + _1n) * (u0 - r)); // 3
|
|
304
|
+
|
|
305
|
+
const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)); // 4
|
|
306
|
+
|
|
307
|
+
let v_prime = v; // 5
|
|
308
|
+
if (!was_square) v_prime = mod(r0 * v);
|
|
309
|
+
|
|
310
|
+
let sgn = _1n; // 6
|
|
311
|
+
if (!was_square) sgn = mod(-_1n);
|
|
312
|
+
|
|
313
|
+
const s = mod(v_prime * (r + _1n)); // 7
|
|
314
|
+
let s_abs = s;
|
|
315
|
+
if (isNegativeLE(s, P)) s_abs = mod(-s);
|
|
316
|
+
|
|
317
|
+
const s2 = s * s;
|
|
318
|
+
const W0 = mod(s_abs * _2n); // 8
|
|
319
|
+
const W1 = mod(s2 + _1n); // 9
|
|
320
|
+
const W2 = mod(s2 - _1n); // 10
|
|
321
|
+
const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn); // 11
|
|
322
|
+
return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Each ed448/ExtendedPoint has 4 different equivalent points. This can be
|
|
327
|
+
* a source of bugs for protocols like ring signatures. Decaf was created to solve this.
|
|
328
|
+
* Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
|
|
329
|
+
* but it should work in its own namespace: do not combine those two.
|
|
330
|
+
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
|
|
331
|
+
*/
|
|
332
|
+
class DcfPoint implements Group<DcfPoint> {
|
|
333
|
+
static BASE: DcfPoint;
|
|
334
|
+
static ZERO: DcfPoint;
|
|
335
|
+
// Private property to discourage combining ExtendedPoint + DecafPoint
|
|
336
|
+
// Always use Decaf encoding/decoding instead.
|
|
337
|
+
constructor(private readonly ep: ExtendedPoint) {}
|
|
338
|
+
|
|
339
|
+
static fromAffine(ap: AffinePoint<bigint>) {
|
|
340
|
+
return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`.
|
|
345
|
+
* The hash-to-group operation applies Elligator twice and adds the results.
|
|
346
|
+
* **Note:** this is one-way map, there is no conversion from point to hash.
|
|
347
|
+
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2
|
|
348
|
+
* @param hex 112-byte output of a hash function
|
|
349
|
+
*/
|
|
350
|
+
static hashToCurve(hex: Hex): DcfPoint {
|
|
351
|
+
hex = ensureBytes('decafHash', hex, 112);
|
|
352
|
+
const r1 = bytes448ToNumberLE(hex.slice(0, 56));
|
|
353
|
+
const R1 = calcElligatorDecafMap(r1);
|
|
354
|
+
const r2 = bytes448ToNumberLE(hex.slice(56, 112));
|
|
355
|
+
const R2 = calcElligatorDecafMap(r2);
|
|
356
|
+
return new DcfPoint(R1.add(R2));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Converts decaf-encoded string to decaf point.
|
|
361
|
+
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2
|
|
362
|
+
* @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding
|
|
363
|
+
*/
|
|
364
|
+
static fromHex(hex: Hex): DcfPoint {
|
|
365
|
+
hex = ensureBytes('decafHex', hex, 56);
|
|
366
|
+
const { d } = ed448.CURVE;
|
|
367
|
+
const P = ed448.CURVE.Fp.ORDER;
|
|
368
|
+
const mod = ed448.CURVE.Fp.create;
|
|
369
|
+
const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint';
|
|
370
|
+
const s = bytes448ToNumberLE(hex);
|
|
371
|
+
|
|
372
|
+
// 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
|
|
373
|
+
// 2. Check that s is non-negative, or else abort
|
|
374
|
+
if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg);
|
|
375
|
+
|
|
376
|
+
const s2 = mod(s * s); // 1
|
|
377
|
+
const u1 = mod(_1n + s2); // 2
|
|
378
|
+
const u1sq = mod(u1 * u1);
|
|
379
|
+
const u2 = mod(u1sq - _4n * d * s2); // 3
|
|
380
|
+
|
|
381
|
+
const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)); // 4
|
|
382
|
+
|
|
383
|
+
let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D); // 5
|
|
384
|
+
if (isNegativeLE(u3, P)) u3 = mod(-u3);
|
|
385
|
+
|
|
386
|
+
const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D); // 6
|
|
387
|
+
const y = mod((_1n - s2) * invsqrt * u1); // 7
|
|
388
|
+
const t = mod(x * y); // 8
|
|
389
|
+
|
|
390
|
+
if (!isValid) throw new Error(emsg);
|
|
391
|
+
return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Encodes decaf point to Uint8Array.
|
|
396
|
+
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2
|
|
397
|
+
*/
|
|
398
|
+
toRawBytes(): Uint8Array {
|
|
399
|
+
let { ex: x, ey: _y, ez: z, et: t } = this.ep;
|
|
400
|
+
const P = ed448.CURVE.Fp.ORDER;
|
|
401
|
+
const mod = ed448.CURVE.Fp.create;
|
|
402
|
+
|
|
403
|
+
const u1 = mod(mod(x + t) * mod(x - t)); // 1
|
|
404
|
+
const x2 = mod(x * x);
|
|
405
|
+
const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)); // 2
|
|
406
|
+
|
|
407
|
+
let ratio = mod(invsqrt * u1 * SQRT_MINUS_D); // 3
|
|
408
|
+
if (isNegativeLE(ratio, P)) ratio = mod(-ratio);
|
|
409
|
+
|
|
410
|
+
const u2 = mod(INVSQRT_MINUS_D * ratio * z - t); // 4
|
|
411
|
+
|
|
412
|
+
let s = mod(ONE_MINUS_D * invsqrt * x * u2); // 5
|
|
413
|
+
if (isNegativeLE(s, P)) s = mod(-s);
|
|
414
|
+
|
|
415
|
+
return numberToBytesLE(s, 56);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
toHex(): string {
|
|
419
|
+
return bytesToHex(this.toRawBytes());
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
toString(): string {
|
|
423
|
+
return this.toHex();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Compare one point to another.
|
|
427
|
+
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2
|
|
428
|
+
equals(other: DcfPoint): boolean {
|
|
429
|
+
assertDcfPoint(other);
|
|
430
|
+
const { ex: X1, ey: Y1 } = this.ep;
|
|
431
|
+
const { ex: X2, ey: Y2 } = other.ep;
|
|
432
|
+
const mod = ed448.CURVE.Fp.create;
|
|
433
|
+
// (x1 * y2 == y1 * x2)
|
|
434
|
+
return mod(X1 * Y2) === mod(Y1 * X2);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
add(other: DcfPoint): DcfPoint {
|
|
438
|
+
assertDcfPoint(other);
|
|
439
|
+
return new DcfPoint(this.ep.add(other.ep));
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
subtract(other: DcfPoint): DcfPoint {
|
|
443
|
+
assertDcfPoint(other);
|
|
444
|
+
return new DcfPoint(this.ep.subtract(other.ep));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
multiply(scalar: bigint): DcfPoint {
|
|
448
|
+
return new DcfPoint(this.ep.multiply(scalar));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
multiplyUnsafe(scalar: bigint): DcfPoint {
|
|
452
|
+
return new DcfPoint(this.ep.multiplyUnsafe(scalar));
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
double(): DcfPoint {
|
|
456
|
+
return new DcfPoint(this.ep.double());
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
negate(): DcfPoint {
|
|
460
|
+
return new DcfPoint(this.ep.negate());
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export const DecafPoint = /* @__PURE__ */ (() => {
|
|
465
|
+
// decaf448 base point is ed448 base x 2
|
|
466
|
+
// https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699
|
|
467
|
+
if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n);
|
|
468
|
+
if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO);
|
|
469
|
+
return DcfPoint;
|
|
470
|
+
})();
|
|
471
|
+
|
|
472
|
+
// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C
|
|
473
|
+
export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts) => {
|
|
474
|
+
const d = options.DST;
|
|
475
|
+
const DST = typeof d === 'string' ? utf8ToBytes(d) : d;
|
|
476
|
+
const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256);
|
|
477
|
+
const P = DcfPoint.hashToCurve(uniform_bytes);
|
|
478
|
+
return P;
|
|
479
|
+
};
|
|
480
|
+
export const hash_to_decaf448 = hashToDecaf448; // legacy
|
package/src/jubjub.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Field } from './abstract/modular.js';
|
|
|
11
11
|
* jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
export const jubjub = twistedEdwards({
|
|
14
|
+
export const jubjub = /* @__PURE__ */ twistedEdwards({
|
|
15
15
|
// Params: a, d
|
|
16
16
|
a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'),
|
|
17
17
|
d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'),
|