@noble/curves 0.4.0 → 0.5.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.
Files changed (72) hide show
  1. package/README.md +203 -162
  2. package/lib/_shortw_utils.d.ts +75 -0
  3. package/lib/_shortw_utils.js +20 -0
  4. package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
  5. package/lib/{bls.js → abstract/bls.js} +28 -27
  6. package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
  7. package/lib/{edwards.js → abstract/edwards.js} +45 -4
  8. package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
  9. package/lib/{group.js → abstract/group.js} +4 -3
  10. package/lib/{hashToCurve.d.ts → abstract/hash-to-curve.d.ts} +6 -0
  11. package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +15 -2
  12. package/lib/{modular.d.ts → abstract/modular.d.ts} +10 -4
  13. package/lib/{modular.js → abstract/modular.js} +110 -19
  14. package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
  15. package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
  16. package/lib/{utils.d.ts → abstract/utils.d.ts} +1 -1
  17. package/lib/{utils.js → abstract/utils.js} +1 -1
  18. package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
  19. package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
  20. package/lib/bls12-381.d.ts +66 -0
  21. package/lib/bls12-381.js +1132 -0
  22. package/lib/bn.d.ts +7 -0
  23. package/lib/bn.js +24 -0
  24. package/lib/ed25519.d.ts +48 -0
  25. package/lib/ed25519.js +322 -0
  26. package/lib/ed448.d.ts +3 -0
  27. package/lib/ed448.js +128 -0
  28. package/lib/esm/_shortw_utils.js +15 -0
  29. package/lib/esm/{bls.js → abstract/bls.js} +25 -24
  30. package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
  31. package/lib/esm/{group.js → abstract/group.js} +4 -3
  32. package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +13 -1
  33. package/lib/esm/{modular.js → abstract/modular.js} +108 -18
  34. package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
  35. package/lib/esm/{utils.js → abstract/utils.js} +1 -1
  36. package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
  37. package/lib/esm/bls12-381.js +1129 -0
  38. package/lib/esm/bn.js +21 -0
  39. package/lib/esm/ed25519.js +318 -0
  40. package/lib/esm/ed448.js +125 -0
  41. package/lib/esm/index.js +2 -0
  42. package/lib/esm/jubjub.js +52 -0
  43. package/lib/esm/p192.js +21 -0
  44. package/lib/esm/p224.js +21 -0
  45. package/lib/esm/p256.js +39 -0
  46. package/lib/esm/p384.js +44 -0
  47. package/lib/esm/p521.js +58 -0
  48. package/lib/esm/pasta.js +29 -0
  49. package/lib/esm/secp256k1.js +290 -0
  50. package/lib/esm/stark.js +222 -0
  51. package/lib/index.d.ts +0 -0
  52. package/lib/index.js +2 -0
  53. package/lib/jubjub.d.ts +7 -0
  54. package/lib/jubjub.js +57 -0
  55. package/lib/p192.d.ts +130 -0
  56. package/lib/p192.js +24 -0
  57. package/lib/p224.d.ts +130 -0
  58. package/lib/p224.js +24 -0
  59. package/lib/p256.d.ts +130 -0
  60. package/lib/p256.js +42 -0
  61. package/lib/p384.d.ts +130 -0
  62. package/lib/p384.js +47 -0
  63. package/lib/p521.d.ts +131 -0
  64. package/lib/p521.js +61 -0
  65. package/lib/pasta.d.ts +4 -0
  66. package/lib/pasta.js +32 -0
  67. package/lib/secp256k1.d.ts +96 -0
  68. package/lib/secp256k1.js +294 -0
  69. package/lib/stark.d.ts +72 -0
  70. package/lib/stark.js +243 -0
  71. package/package.json +146 -50
  72. package/index.js +0 -1
package/lib/bn.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * bn254 pairing-friendly curve.
3
+ * Previously known as alt_bn_128, when it had 128-bit security.
4
+ * Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
5
+ * https://github.com/zcash/zcash/issues/2502
6
+ */
7
+ export declare const bn254: import("./abstract/weierstrass.js").CurveFn;
package/lib/bn.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bn254 = void 0;
4
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
+ const weierstrass_js_1 = require("./abstract/weierstrass.js");
6
+ const sha256_1 = require("@noble/hashes/sha256");
7
+ const _shortw_utils_js_1 = require("./_shortw_utils.js");
8
+ const modular_js_1 = require("./abstract/modular.js");
9
+ /**
10
+ * bn254 pairing-friendly curve.
11
+ * Previously known as alt_bn_128, when it had 128-bit security.
12
+ * Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
13
+ * https://github.com/zcash/zcash/issues/2502
14
+ */
15
+ exports.bn254 = (0, weierstrass_js_1.weierstrass)({
16
+ a: BigInt(0),
17
+ b: BigInt(3),
18
+ Fp: (0, modular_js_1.Fp)(BigInt('0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47')),
19
+ n: BigInt('0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001'),
20
+ Gx: BigInt(1),
21
+ Gy: BigInt(2),
22
+ h: BigInt(1),
23
+ ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256),
24
+ });
@@ -0,0 +1,48 @@
1
+ import { ExtendedPointType } from './abstract/edwards.js';
2
+ import { Hex } from './abstract/utils.js';
3
+ export declare const ED25519_TORSION_SUBGROUP: string[];
4
+ export declare const ed25519: import("./abstract/edwards.js").CurveFn;
5
+ export declare const ed25519ctx: import("./abstract/edwards.js").CurveFn;
6
+ export declare const ed25519ph: import("./abstract/edwards.js").CurveFn;
7
+ export declare const x25519: import("./abstract/montgomery.js").CurveFn;
8
+ declare type ExtendedPoint = ExtendedPointType;
9
+ /**
10
+ * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be
11
+ * a source of bugs for protocols like ring signatures. Ristretto was created to solve this.
12
+ * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
13
+ * but it should work in its own namespace: do not combine those two.
14
+ * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
15
+ */
16
+ export declare class RistrettoPoint {
17
+ private readonly ep;
18
+ static BASE: RistrettoPoint;
19
+ static ZERO: RistrettoPoint;
20
+ constructor(ep: ExtendedPoint);
21
+ /**
22
+ * Takes uniform output of 64-bit hash function like sha512 and converts it to `RistrettoPoint`.
23
+ * The hash-to-group operation applies Elligator twice and adds the results.
24
+ * **Note:** this is one-way map, there is no conversion from point to hash.
25
+ * https://ristretto.group/formulas/elligator.html
26
+ * @param hex 64-bit output of a hash function
27
+ */
28
+ static hashToCurve(hex: Hex): RistrettoPoint;
29
+ /**
30
+ * Converts ristretto-encoded string to ristretto point.
31
+ * https://ristretto.group/formulas/decoding.html
32
+ * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
33
+ */
34
+ static fromHex(hex: Hex): RistrettoPoint;
35
+ /**
36
+ * Encodes ristretto point to Uint8Array.
37
+ * https://ristretto.group/formulas/encoding.html
38
+ */
39
+ toRawBytes(): Uint8Array;
40
+ toHex(): string;
41
+ toString(): string;
42
+ equals(other: RistrettoPoint): boolean;
43
+ add(other: RistrettoPoint): RistrettoPoint;
44
+ subtract(other: RistrettoPoint): RistrettoPoint;
45
+ multiply(scalar: number | bigint): RistrettoPoint;
46
+ multiplyUnsafe(scalar: number | bigint): RistrettoPoint;
47
+ }
48
+ export {};
package/lib/ed25519.js ADDED
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RistrettoPoint = exports.x25519 = exports.ed25519ph = exports.ed25519ctx = exports.ed25519 = exports.ED25519_TORSION_SUBGROUP = void 0;
4
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
+ const sha512_1 = require("@noble/hashes/sha512");
6
+ const utils_1 = require("@noble/hashes/utils");
7
+ const edwards_js_1 = require("./abstract/edwards.js");
8
+ const montgomery_js_1 = require("./abstract/montgomery.js");
9
+ const modular_js_1 = require("./abstract/modular.js");
10
+ const utils_js_1 = require("./abstract/utils.js");
11
+ /**
12
+ * ed25519 Twisted Edwards curve with following addons:
13
+ * - X25519 ECDH
14
+ * - Ristretto cofactor elimination
15
+ * - Elligator hash-to-group / point indistinguishability
16
+ */
17
+ const ED25519_P = BigInt('57896044618658097711785492504343953926634992332820282019728792003956564819949');
18
+ // √(-1) aka √(a) aka 2^((p-1)/4)
19
+ const ED25519_SQRT_M1 = BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752');
20
+ // prettier-ignore
21
+ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _5n = BigInt(5);
22
+ // prettier-ignore
23
+ const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
24
+ function ed25519_pow_2_252_3(x) {
25
+ const P = ED25519_P;
26
+ const x2 = (x * x) % P;
27
+ const b2 = (x2 * x) % P; // x^3, 11
28
+ const b4 = ((0, modular_js_1.pow2)(b2, _2n, P) * b2) % P; // x^15, 1111
29
+ const b5 = ((0, modular_js_1.pow2)(b4, _1n, P) * x) % P; // x^31
30
+ const b10 = ((0, modular_js_1.pow2)(b5, _5n, P) * b5) % P;
31
+ const b20 = ((0, modular_js_1.pow2)(b10, _10n, P) * b10) % P;
32
+ const b40 = ((0, modular_js_1.pow2)(b20, _20n, P) * b20) % P;
33
+ const b80 = ((0, modular_js_1.pow2)(b40, _40n, P) * b40) % P;
34
+ const b160 = ((0, modular_js_1.pow2)(b80, _80n, P) * b80) % P;
35
+ const b240 = ((0, modular_js_1.pow2)(b160, _80n, P) * b80) % P;
36
+ const b250 = ((0, modular_js_1.pow2)(b240, _10n, P) * b10) % P;
37
+ const pow_p_5_8 = ((0, modular_js_1.pow2)(b250, _2n, P) * x) % P;
38
+ // ^ To pow to (p+3)/8, multiply it by x.
39
+ return { pow_p_5_8, b2 };
40
+ }
41
+ function adjustScalarBytes(bytes) {
42
+ // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar,
43
+ // set the three least significant bits of the first byte
44
+ bytes[0] &= 248; // 0b1111_1000
45
+ // and the most significant bit of the last to zero,
46
+ bytes[31] &= 127; // 0b0111_1111
47
+ // set the second most significant bit of the last byte to 1
48
+ bytes[31] |= 64; // 0b0100_0000
49
+ return bytes;
50
+ }
51
+ // sqrt(u/v)
52
+ function uvRatio(u, v) {
53
+ const P = ED25519_P;
54
+ const v3 = (0, modular_js_1.mod)(v * v * v, P); // v³
55
+ const v7 = (0, modular_js_1.mod)(v3 * v3 * v, P); // v⁷
56
+ // (p+3)/8 and (p-5)/8
57
+ const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
58
+ let x = (0, modular_js_1.mod)(u * v3 * pow, P); // (uv³)(uv⁷)^(p-5)/8
59
+ const vx2 = (0, modular_js_1.mod)(v * x * x, P); // vx²
60
+ const root1 = x; // First root candidate
61
+ const root2 = (0, modular_js_1.mod)(x * ED25519_SQRT_M1, P); // Second root candidate
62
+ const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root
63
+ const useRoot2 = vx2 === (0, modular_js_1.mod)(-u, P); // If vx² = -u, set x <-- x * 2^((p-1)/4)
64
+ const noRoot = vx2 === (0, modular_js_1.mod)(-u * ED25519_SQRT_M1, P); // There is no valid root, vx² = -u√(-1)
65
+ if (useRoot1)
66
+ x = root1;
67
+ if (useRoot2 || noRoot)
68
+ x = root2; // We return root2 anyway, for const-time
69
+ if ((0, modular_js_1.isNegativeLE)(x, P))
70
+ x = (0, modular_js_1.mod)(-x, P);
71
+ return { isValid: useRoot1 || useRoot2, value: x };
72
+ }
73
+ // Just in case
74
+ exports.ED25519_TORSION_SUBGROUP = [
75
+ '0100000000000000000000000000000000000000000000000000000000000000',
76
+ 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a',
77
+ '0000000000000000000000000000000000000000000000000000000000000080',
78
+ '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05',
79
+ 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
80
+ '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85',
81
+ '0000000000000000000000000000000000000000000000000000000000000000',
82
+ 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
83
+ ];
84
+ const Fp = (0, modular_js_1.Fp)(ED25519_P);
85
+ const ED25519_DEF = {
86
+ // Param: a
87
+ a: BigInt(-1),
88
+ // Equal to -121665/121666 over finite field.
89
+ // Negative number is P - number, and division is invert(number, P)
90
+ d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
91
+ // Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
92
+ Fp,
93
+ // Subgroup order: how many points ed25519 has
94
+ // 2n ** 252n + 27742317777372353535851937790883648493n;
95
+ n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
96
+ // Cofactor
97
+ h: BigInt(8),
98
+ // Base point (x, y) aka generator point
99
+ Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
100
+ Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
101
+ hash: sha512_1.sha512,
102
+ randomBytes: utils_1.randomBytes,
103
+ adjustScalarBytes,
104
+ // dom2
105
+ // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
106
+ // Constant-time, u/√v
107
+ uvRatio,
108
+ htfDefaults: {
109
+ DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
110
+ p: Fp.ORDER,
111
+ m: 1,
112
+ k: 128,
113
+ expand: true,
114
+ hash: sha512_1.sha512,
115
+ },
116
+ mapToCurve: (scalars) => {
117
+ throw new Error('Not supported yet');
118
+ // const { x, y } = calcElligatorRistrettoMap(scalars[0]).toAffine();
119
+ // return { x, y };
120
+ },
121
+ };
122
+ exports.ed25519 = (0, edwards_js_1.twistedEdwards)(ED25519_DEF);
123
+ function ed25519_domain(data, ctx, phflag) {
124
+ if (ctx.length > 255)
125
+ throw new Error('Context is too big');
126
+ return (0, utils_1.concatBytes)((0, utils_1.utf8ToBytes)('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
127
+ }
128
+ exports.ed25519ctx = (0, edwards_js_1.twistedEdwards)({ ...ED25519_DEF, domain: ed25519_domain });
129
+ exports.ed25519ph = (0, edwards_js_1.twistedEdwards)({
130
+ ...ED25519_DEF,
131
+ domain: ed25519_domain,
132
+ preHash: sha512_1.sha512,
133
+ });
134
+ exports.x25519 = (0, montgomery_js_1.montgomery)({
135
+ P: ED25519_P,
136
+ a24: BigInt('121665'),
137
+ montgomeryBits: 255,
138
+ nByteLength: 32,
139
+ Gu: '0900000000000000000000000000000000000000000000000000000000000000',
140
+ powPminus2: (x) => {
141
+ const P = ED25519_P;
142
+ // x^(p-2) aka x^(2^255-21)
143
+ const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
144
+ return (0, modular_js_1.mod)((0, modular_js_1.pow2)(pow_p_5_8, BigInt(3), P) * b2, P);
145
+ },
146
+ adjustScalarBytes,
147
+ });
148
+ function assertRstPoint(other) {
149
+ if (!(other instanceof RistrettoPoint))
150
+ throw new TypeError('RistrettoPoint expected');
151
+ }
152
+ // √(-1) aka √(a) aka 2^((p-1)/4)
153
+ const SQRT_M1 = BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752');
154
+ // √(ad - 1)
155
+ const SQRT_AD_MINUS_ONE = BigInt('25063068953384623474111414158702152701244531502492656460079210482610430750235');
156
+ // 1 / √(a-d)
157
+ const INVSQRT_A_MINUS_D = BigInt('54469307008909316920995813868745141605393597292927456921205312896311721017578');
158
+ // 1-d²
159
+ const ONE_MINUS_D_SQ = BigInt('1159843021668779879193775521855586647937357759715417654439879720876111806838');
160
+ // (d-1)²
161
+ const D_MINUS_ONE_SQ = BigInt('40440834346308536858101042469323190826248399146238708352240133220865137265952');
162
+ // Calculates 1/√(number)
163
+ const invertSqrt = (number) => uvRatio(_1n, number);
164
+ const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
165
+ const bytes255ToNumberLE = (bytes) => exports.ed25519.utils.mod((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_255B);
166
+ // Computes Elligator map for Ristretto
167
+ // https://ristretto.group/formulas/elligator.html
168
+ function calcElligatorRistrettoMap(r0) {
169
+ const { d } = exports.ed25519.CURVE;
170
+ const P = exports.ed25519.CURVE.Fp.ORDER;
171
+ const { mod } = exports.ed25519.utils;
172
+ const r = mod(SQRT_M1 * r0 * r0); // 1
173
+ const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
174
+ let c = BigInt(-1); // 3
175
+ const D = mod((c - d * r) * mod(r + d)); // 4
176
+ let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D); // 5
177
+ let s_ = mod(s * r0); // 6
178
+ if (!(0, modular_js_1.isNegativeLE)(s_, P))
179
+ s_ = mod(-s_);
180
+ if (!Ns_D_is_sq)
181
+ s = s_; // 7
182
+ if (!Ns_D_is_sq)
183
+ c = r; // 8
184
+ const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D); // 9
185
+ const s2 = s * s;
186
+ const W0 = mod((s + s) * D); // 10
187
+ const W1 = mod(Nt * SQRT_AD_MINUS_ONE); // 11
188
+ const W2 = mod(_1n - s2); // 12
189
+ const W3 = mod(_1n + s2); // 13
190
+ return new exports.ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
191
+ }
192
+ /**
193
+ * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be
194
+ * a source of bugs for protocols like ring signatures. Ristretto was created to solve this.
195
+ * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
196
+ * but it should work in its own namespace: do not combine those two.
197
+ * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
198
+ */
199
+ class RistrettoPoint {
200
+ // Private property to discourage combining ExtendedPoint + RistrettoPoint
201
+ // Always use Ristretto encoding/decoding instead.
202
+ constructor(ep) {
203
+ this.ep = ep;
204
+ }
205
+ /**
206
+ * Takes uniform output of 64-bit hash function like sha512 and converts it to `RistrettoPoint`.
207
+ * The hash-to-group operation applies Elligator twice and adds the results.
208
+ * **Note:** this is one-way map, there is no conversion from point to hash.
209
+ * https://ristretto.group/formulas/elligator.html
210
+ * @param hex 64-bit output of a hash function
211
+ */
212
+ static hashToCurve(hex) {
213
+ hex = (0, utils_js_1.ensureBytes)(hex, 64);
214
+ const r1 = bytes255ToNumberLE(hex.slice(0, 32));
215
+ const R1 = calcElligatorRistrettoMap(r1);
216
+ const r2 = bytes255ToNumberLE(hex.slice(32, 64));
217
+ const R2 = calcElligatorRistrettoMap(r2);
218
+ return new RistrettoPoint(R1.add(R2));
219
+ }
220
+ /**
221
+ * Converts ristretto-encoded string to ristretto point.
222
+ * https://ristretto.group/formulas/decoding.html
223
+ * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
224
+ */
225
+ static fromHex(hex) {
226
+ hex = (0, utils_js_1.ensureBytes)(hex, 32);
227
+ const { a, d } = exports.ed25519.CURVE;
228
+ const P = exports.ed25519.CURVE.Fp.ORDER;
229
+ const { mod } = exports.ed25519.utils;
230
+ const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint';
231
+ const s = bytes255ToNumberLE(hex);
232
+ // 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
233
+ // 3. Check that s is non-negative, or else abort
234
+ if (!(0, utils_js_1.equalBytes)((0, utils_js_1.numberToBytesLE)(s, 32), hex) || (0, modular_js_1.isNegativeLE)(s, P))
235
+ throw new Error(emsg);
236
+ const s2 = mod(s * s);
237
+ const u1 = mod(_1n + a * s2); // 4 (a is -1)
238
+ const u2 = mod(_1n - a * s2); // 5
239
+ const u1_2 = mod(u1 * u1);
240
+ const u2_2 = mod(u2 * u2);
241
+ const v = mod(a * d * u1_2 - u2_2); // 6
242
+ const { isValid, value: I } = invertSqrt(mod(v * u2_2)); // 7
243
+ const Dx = mod(I * u2); // 8
244
+ const Dy = mod(I * Dx * v); // 9
245
+ let x = mod((s + s) * Dx); // 10
246
+ if ((0, modular_js_1.isNegativeLE)(x, P))
247
+ x = mod(-x); // 10
248
+ const y = mod(u1 * Dy); // 11
249
+ const t = mod(x * y); // 12
250
+ if (!isValid || (0, modular_js_1.isNegativeLE)(t, P) || y === _0n)
251
+ throw new Error(emsg);
252
+ return new RistrettoPoint(new exports.ed25519.ExtendedPoint(x, y, _1n, t));
253
+ }
254
+ /**
255
+ * Encodes ristretto point to Uint8Array.
256
+ * https://ristretto.group/formulas/encoding.html
257
+ */
258
+ toRawBytes() {
259
+ let { x, y, z, t } = this.ep;
260
+ const P = exports.ed25519.CURVE.Fp.ORDER;
261
+ const { mod } = exports.ed25519.utils;
262
+ const u1 = mod(mod(z + y) * mod(z - y)); // 1
263
+ const u2 = mod(x * y); // 2
264
+ // Square root always exists
265
+ const u2sq = mod(u2 * u2);
266
+ const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)); // 3
267
+ const D1 = mod(invsqrt * u1); // 4
268
+ const D2 = mod(invsqrt * u2); // 5
269
+ const zInv = mod(D1 * D2 * t); // 6
270
+ let D; // 7
271
+ if ((0, modular_js_1.isNegativeLE)(t * zInv, P)) {
272
+ let _x = mod(y * SQRT_M1);
273
+ let _y = mod(x * SQRT_M1);
274
+ x = _x;
275
+ y = _y;
276
+ D = mod(D1 * INVSQRT_A_MINUS_D);
277
+ }
278
+ else {
279
+ D = D2; // 8
280
+ }
281
+ if ((0, modular_js_1.isNegativeLE)(x * zInv, P))
282
+ y = mod(-y); // 9
283
+ let s = mod((z - y) * D); // 10 (check footer's note, no sqrt(-a))
284
+ if ((0, modular_js_1.isNegativeLE)(s, P))
285
+ s = mod(-s);
286
+ return (0, utils_js_1.numberToBytesLE)(s, 32); // 11
287
+ }
288
+ toHex() {
289
+ return (0, utils_js_1.bytesToHex)(this.toRawBytes());
290
+ }
291
+ toString() {
292
+ return this.toHex();
293
+ }
294
+ // Compare one point to another.
295
+ equals(other) {
296
+ assertRstPoint(other);
297
+ const a = this.ep;
298
+ const b = other.ep;
299
+ const { mod } = exports.ed25519.utils;
300
+ // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
301
+ const one = mod(a.x * b.y) === mod(a.y * b.x);
302
+ const two = mod(a.y * b.y) === mod(a.x * b.x);
303
+ return one || two;
304
+ }
305
+ add(other) {
306
+ assertRstPoint(other);
307
+ return new RistrettoPoint(this.ep.add(other.ep));
308
+ }
309
+ subtract(other) {
310
+ assertRstPoint(other);
311
+ return new RistrettoPoint(this.ep.subtract(other.ep));
312
+ }
313
+ multiply(scalar) {
314
+ return new RistrettoPoint(this.ep.multiply(scalar));
315
+ }
316
+ multiplyUnsafe(scalar) {
317
+ return new RistrettoPoint(this.ep.multiplyUnsafe(scalar));
318
+ }
319
+ }
320
+ exports.RistrettoPoint = RistrettoPoint;
321
+ RistrettoPoint.BASE = new RistrettoPoint(exports.ed25519.ExtendedPoint.BASE);
322
+ RistrettoPoint.ZERO = new RistrettoPoint(exports.ed25519.ExtendedPoint.ZERO);
package/lib/ed448.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare const ed448: import("./abstract/edwards.js").CurveFn;
2
+ export declare const ed448ph: import("./abstract/edwards.js").CurveFn;
3
+ export declare const x448: import("./abstract/montgomery.js").CurveFn;
package/lib/ed448.js ADDED
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.x448 = exports.ed448ph = exports.ed448 = void 0;
4
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
+ const sha3_1 = require("@noble/hashes/sha3");
6
+ const utils_1 = require("@noble/hashes/utils");
7
+ const edwards_js_1 = require("./abstract/edwards.js");
8
+ const modular_js_1 = require("./abstract/modular.js");
9
+ const montgomery_js_1 = require("./abstract/montgomery.js");
10
+ /**
11
+ * Edwards448 (not Ed448-Goldilocks) curve with following addons:
12
+ * * X448 ECDH
13
+ * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2
14
+ */
15
+ const shake256_114 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 114 }));
16
+ const shake256_64 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 64 }));
17
+ const ed448P = BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439');
18
+ // powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
19
+ // Used for efficient square root calculation.
20
+ // ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]
21
+ function ed448_pow_Pminus3div4(x) {
22
+ const P = ed448P;
23
+ // prettier-ignore
24
+ const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _11n = BigInt(11);
25
+ // prettier-ignore
26
+ const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);
27
+ const b2 = (x * x * x) % P;
28
+ const b3 = (b2 * b2 * x) % P;
29
+ const b6 = ((0, modular_js_1.pow2)(b3, _3n, P) * b3) % P;
30
+ const b9 = ((0, modular_js_1.pow2)(b6, _3n, P) * b3) % P;
31
+ const b11 = ((0, modular_js_1.pow2)(b9, _2n, P) * b2) % P;
32
+ const b22 = ((0, modular_js_1.pow2)(b11, _11n, P) * b11) % P;
33
+ const b44 = ((0, modular_js_1.pow2)(b22, _22n, P) * b22) % P;
34
+ const b88 = ((0, modular_js_1.pow2)(b44, _44n, P) * b44) % P;
35
+ const b176 = ((0, modular_js_1.pow2)(b88, _88n, P) * b88) % P;
36
+ const b220 = ((0, modular_js_1.pow2)(b176, _44n, P) * b44) % P;
37
+ const b222 = ((0, modular_js_1.pow2)(b220, _2n, P) * b2) % P;
38
+ const b223 = ((0, modular_js_1.pow2)(b222, _1n, P) * x) % P;
39
+ return ((0, modular_js_1.pow2)(b223, _223n, P) * b222) % P;
40
+ }
41
+ function adjustScalarBytes(bytes) {
42
+ // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most
43
+ // significant bit of the last byte to 1.
44
+ bytes[0] &= 252; // 0b11111100
45
+ // and the most significant bit of the last byte to 1.
46
+ bytes[55] |= 128; // 0b10000000
47
+ // NOTE: is is NOOP for 56 bytes scalars (X25519/X448)
48
+ bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
49
+ return bytes;
50
+ }
51
+ const ED448_DEF = {
52
+ // Param: a
53
+ a: BigInt(1),
54
+ // -39081. Negative number is P - number
55
+ d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
56
+ // Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n
57
+ Fp: (0, modular_js_1.Fp)(ed448P, 456),
58
+ // Subgroup order: how many points ed448 has; 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
59
+ n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
60
+ nBitLength: 456,
61
+ // Cofactor
62
+ h: BigInt(4),
63
+ // Base point (x, y) aka generator point
64
+ Gx: BigInt('224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710'),
65
+ Gy: BigInt('298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660'),
66
+ // SHAKE256(dom4(phflag,context)||x, 114)
67
+ hash: shake256_114,
68
+ randomBytes: utils_1.randomBytes,
69
+ adjustScalarBytes,
70
+ // dom4
71
+ domain: (data, ctx, phflag) => {
72
+ if (ctx.length > 255)
73
+ throw new Error(`Context is too big: ${ctx.length}`);
74
+ return (0, utils_1.concatBytes)((0, utils_1.utf8ToBytes)('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
75
+ },
76
+ // Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.
77
+ // Uses algo from RFC8032 5.1.3.
78
+ uvRatio: (u, v) => {
79
+ const P = ed448P;
80
+ // https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.3
81
+ // To compute the square root of (u/v), the first step is to compute the
82
+ // candidate root x = (u/v)^((p+1)/4). This can be done using the
83
+ // following trick, to use a single modular powering for both the
84
+ // inversion of v and the square root:
85
+ // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p)
86
+ const u2v = (0, modular_js_1.mod)(u * u * v, P); // u²v
87
+ const u3v = (0, modular_js_1.mod)(u2v * u, P); // u³v
88
+ const u5v3 = (0, modular_js_1.mod)(u3v * u2v * v, P); // u⁵v³
89
+ const root = ed448_pow_Pminus3div4(u5v3);
90
+ const x = (0, modular_js_1.mod)(u3v * root, P);
91
+ // Verify that root is exists
92
+ const x2 = (0, modular_js_1.mod)(x * x, P); // x²
93
+ // If vx² = u, the recovered x-coordinate is x. Otherwise, no
94
+ // square root exists, and the decoding fails.
95
+ return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x };
96
+ },
97
+ };
98
+ exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF);
99
+ // NOTE: there is no ed448ctx, since ed448 supports ctx by default
100
+ exports.ed448ph = (0, edwards_js_1.twistedEdwards)({ ...ED448_DEF, preHash: shake256_64 });
101
+ exports.x448 = (0, montgomery_js_1.montgomery)({
102
+ a24: BigInt(39081),
103
+ montgomeryBits: 448,
104
+ nByteLength: 57,
105
+ P: ed448P,
106
+ Gu: '0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
107
+ powPminus2: (x) => {
108
+ const P = ed448P;
109
+ const Pminus3div4 = ed448_pow_Pminus3div4(x);
110
+ const Pminus3 = (0, modular_js_1.pow2)(Pminus3div4, BigInt(2), P);
111
+ return (0, modular_js_1.mod)(Pminus3 * x, P); // Pminus3 * x = Pminus2
112
+ },
113
+ adjustScalarBytes,
114
+ // The 4-isogeny maps between the Montgomery curve and this Edwards
115
+ // curve are:
116
+ // (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
117
+ // (x, y) = (4*v*(u^2 - 1)/(u^4 - 2*u^2 + 4*v^2 + 1),
118
+ // -(u^5 - 2*u^3 - 4*u*v^2 + u)/
119
+ // (u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u))
120
+ // xyToU: (p: PointType) => {
121
+ // const P = ed448P;
122
+ // const { x, y } = p;
123
+ // if (x === _0n) throw new Error(`Point with x=0 doesn't have mapping`);
124
+ // const invX = invert(x * x, P); // x^2
125
+ // const u = mod(y * y * invX, P); // (y^2/x^2)
126
+ // return numberToBytesLE(u, 56);
127
+ // },
128
+ });
@@ -0,0 +1,15 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ import { hmac } from '@noble/hashes/hmac';
3
+ import { concatBytes, randomBytes } from '@noble/hashes/utils';
4
+ import { weierstrass } from './abstract/weierstrass.js';
5
+ export function getHash(hash) {
6
+ return {
7
+ hash,
8
+ hmac: (key, ...msgs) => hmac(hash, key, concatBytes(...msgs)),
9
+ randomBytes,
10
+ };
11
+ }
12
+ export function createCurve(curveDef, defHash) {
13
+ const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) });
14
+ return Object.freeze({ ...create(defHash), create });
15
+ }
@@ -1,3 +1,4 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
2
  // Barreto-Lynn-Scott Curves. A family of pairing friendly curves, with embedding degree = 12 or 24
2
3
  // NOTE: only 12 supported for now
3
4
  // Constructed from pair of weierstrass curves, based pairing logic
@@ -5,7 +6,7 @@ import * as mod from './modular.js';
5
6
  import { ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitGet } from './utils.js';
6
7
  // Types
7
8
  import { hexToBytes, bytesToHex } from './utils.js';
8
- import { stringToBytes, hash_to_field, expand_message_xmd } from './hashToCurve.js';
9
+ import { stringToBytes, hash_to_field, expand_message_xmd } from './hash-to-curve.js';
9
10
  import { weierstrassPoints } from './weierstrass.js';
10
11
  export function bls(CURVE) {
11
12
  // Fields looks pretty specific for curve, so for now we need to pass them with options
@@ -27,33 +28,33 @@ export function bls(CURVE) {
27
28
  // Double
28
29
  let t0 = Fp2.square(Ry); // Ry²
29
30
  let t1 = Fp2.square(Rz); // Rz²
30
- let t2 = Fp2.multiplyByB(Fp2.multiply(t1, 3n)); // 3 * T1 * B
31
- let t3 = Fp2.multiply(t2, 3n); // 3 * T2
32
- let t4 = Fp2.subtract(Fp2.subtract(Fp2.square(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
31
+ let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
32
+ let t3 = Fp2.mul(t2, 3n); // 3 * T2
33
+ let t4 = Fp2.sub(Fp2.sub(Fp2.square(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
33
34
  ell_coeff.push([
34
- Fp2.subtract(t2, t0),
35
- Fp2.multiply(Fp2.square(Rx), 3n),
35
+ Fp2.sub(t2, t0),
36
+ Fp2.mul(Fp2.square(Rx), 3n),
36
37
  Fp2.negate(t4), // -T4
37
38
  ]);
38
- Rx = Fp2.div(Fp2.multiply(Fp2.multiply(Fp2.subtract(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
39
- Ry = Fp2.subtract(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.multiply(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
40
- Rz = Fp2.multiply(t0, t4); // T0 * T4
39
+ Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
40
+ Ry = Fp2.sub(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
41
+ Rz = Fp2.mul(t0, t4); // T0 * T4
41
42
  if (bitGet(CURVE.x, i)) {
42
43
  // Addition
43
- let t0 = Fp2.subtract(Ry, Fp2.multiply(Qy, Rz)); // Ry - Qy * Rz
44
- let t1 = Fp2.subtract(Rx, Fp2.multiply(Qx, Rz)); // Rx - Qx * Rz
44
+ let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
45
+ let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
45
46
  ell_coeff.push([
46
- Fp2.subtract(Fp2.multiply(t0, Qx), Fp2.multiply(t1, Qy)),
47
+ Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)),
47
48
  Fp2.negate(t0),
48
49
  t1, // T1
49
50
  ]);
50
51
  let t2 = Fp2.square(t1); // T1²
51
- let t3 = Fp2.multiply(t2, t1); // T2 * T1
52
- let t4 = Fp2.multiply(t2, Rx); // T2 * Rx
53
- let t5 = Fp2.add(Fp2.subtract(t3, Fp2.multiply(t4, 2n)), Fp2.multiply(Fp2.square(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
54
- Rx = Fp2.multiply(t1, t5); // T1 * T5
55
- Ry = Fp2.subtract(Fp2.multiply(Fp2.subtract(t4, t5), t0), Fp2.multiply(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
56
- Rz = Fp2.multiply(Rz, t3); // Rz * T3
52
+ let t3 = Fp2.mul(t2, t1); // T2 * T1
53
+ let t4 = Fp2.mul(t2, Rx); // T2 * Rx
54
+ let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.square(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
55
+ Rx = Fp2.mul(t1, t5); // T1 * T5
56
+ Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
57
+ Rz = Fp2.mul(Rz, t3); // Rz * T3
57
58
  }
58
59
  }
59
60
  return ell_coeff;
@@ -64,11 +65,11 @@ export function bls(CURVE) {
64
65
  let f12 = Fp12.ONE;
65
66
  for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
66
67
  const E = ell[j];
67
- f12 = Fp12.multiplyBy014(f12, E[0], Fp2.multiply(E[1], Px), Fp2.multiply(E[2], Py));
68
+ f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
68
69
  if (bitGet(CURVE.x, i)) {
69
70
  j += 1;
70
71
  const F = ell[j];
71
- f12 = Fp12.multiplyBy014(f12, F[0], Fp2.multiply(F[1], Px), Fp2.multiply(F[2], Py));
72
+ f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
72
73
  }
73
74
  if (i !== 0)
74
75
  f12 = Fp12.square(f12);
@@ -217,7 +218,7 @@ export function bls(CURVE) {
217
218
  // and do one exp after multiplying 2 points.
218
219
  const ePHm = pairing(P.negate(), Hm, false);
219
220
  const eGS = pairing(G, S, false);
220
- const exp = Fp12.finalExponentiate(Fp12.multiply(eGS, ePHm));
221
+ const exp = Fp12.finalExponentiate(Fp12.mul(eGS, ePHm));
221
222
  return Fp12.equals(exp, Fp12.ONE);
222
223
  }
223
224
  function aggregatePublicKeys(publicKeys) {
@@ -225,7 +226,7 @@ export function bls(CURVE) {
225
226
  throw new Error('Expected non-empty array');
226
227
  const agg = publicKeys
227
228
  .map(normP1)
228
- .reduce((sum, p) => sum.add(G1.JacobianPoint.fromAffine(p)), G1.JacobianPoint.ZERO);
229
+ .reduce((sum, p) => sum.add(G1.ProjectivePoint.fromAffine(p)), G1.ProjectivePoint.ZERO);
229
230
  const aggAffine = agg.toAffine();
230
231
  if (publicKeys[0] instanceof G1.Point) {
231
232
  aggAffine.assertValidity();
@@ -239,7 +240,7 @@ export function bls(CURVE) {
239
240
  throw new Error('Expected non-empty array');
240
241
  const agg = signatures
241
242
  .map(normP2)
242
- .reduce((sum, s) => sum.add(G2.JacobianPoint.fromAffine(s)), G2.JacobianPoint.ZERO);
243
+ .reduce((sum, s) => sum.add(G2.ProjectivePoint.fromAffine(s)), G2.ProjectivePoint.ZERO);
243
244
  const aggAffine = agg.toAffine();
244
245
  if (signatures[0] instanceof G2.Point) {
245
246
  aggAffine.assertValidity();
@@ -266,7 +267,7 @@ export function bls(CURVE) {
266
267
  paired.push(pairing(groupPublicKey, message, false));
267
268
  }
268
269
  paired.push(pairing(G1.Point.BASE.negate(), sig, false));
269
- const product = paired.reduce((a, b) => Fp12.multiply(a, b), Fp12.ONE);
270
+ const product = paired.reduce((a, b) => Fp12.mul(a, b), Fp12.ONE);
270
271
  const exp = Fp12.finalExponentiate(product);
271
272
  return Fp12.equals(exp, Fp12.ONE);
272
273
  }