@noble/curves 0.5.1 → 0.6.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 (60) hide show
  1. package/README.md +49 -8
  2. package/lib/_shortw_utils.d.ts +11 -26
  3. package/lib/abstract/bls.d.ts +51 -35
  4. package/lib/abstract/bls.js +77 -139
  5. package/lib/abstract/{group.d.ts → curve.d.ts} +31 -1
  6. package/lib/abstract/{group.js → curve.js} +39 -2
  7. package/lib/abstract/edwards.d.ts +30 -81
  8. package/lib/abstract/edwards.js +225 -420
  9. package/lib/abstract/hash-to-curve.d.ts +25 -6
  10. package/lib/abstract/hash-to-curve.js +40 -12
  11. package/lib/abstract/modular.d.ts +20 -7
  12. package/lib/abstract/modular.js +80 -51
  13. package/lib/abstract/montgomery.js +3 -4
  14. package/lib/abstract/poseidon.d.ts +29 -0
  15. package/lib/abstract/poseidon.js +115 -0
  16. package/lib/abstract/utils.d.ts +5 -34
  17. package/lib/abstract/utils.js +23 -63
  18. package/lib/abstract/weierstrass.d.ts +56 -79
  19. package/lib/abstract/weierstrass.js +509 -641
  20. package/lib/bls12-381.d.ts +1 -0
  21. package/lib/bls12-381.js +75 -65
  22. package/lib/bn.js +1 -1
  23. package/lib/ed25519.d.ts +7 -5
  24. package/lib/ed25519.js +87 -84
  25. package/lib/ed448.d.ts +3 -0
  26. package/lib/ed448.js +88 -84
  27. package/lib/esm/abstract/bls.js +77 -139
  28. package/lib/esm/abstract/{group.js → curve.js} +37 -1
  29. package/lib/esm/abstract/edwards.js +223 -418
  30. package/lib/esm/abstract/hash-to-curve.js +38 -11
  31. package/lib/esm/abstract/modular.js +77 -50
  32. package/lib/esm/abstract/montgomery.js +4 -7
  33. package/lib/esm/abstract/poseidon.js +109 -0
  34. package/lib/esm/abstract/utils.js +21 -59
  35. package/lib/esm/abstract/weierstrass.js +508 -640
  36. package/lib/esm/bls12-381.js +86 -76
  37. package/lib/esm/bn.js +1 -1
  38. package/lib/esm/ed25519.js +85 -83
  39. package/lib/esm/ed448.js +86 -83
  40. package/lib/esm/jubjub.js +6 -5
  41. package/lib/esm/p256.js +11 -9
  42. package/lib/esm/p384.js +11 -9
  43. package/lib/esm/p521.js +13 -12
  44. package/lib/esm/secp256k1.js +118 -157
  45. package/lib/esm/stark.js +104 -39
  46. package/lib/jubjub.d.ts +3 -2
  47. package/lib/jubjub.js +6 -5
  48. package/lib/p192.d.ts +22 -52
  49. package/lib/p224.d.ts +22 -52
  50. package/lib/p256.d.ts +25 -52
  51. package/lib/p256.js +13 -10
  52. package/lib/p384.d.ts +25 -52
  53. package/lib/p384.js +13 -10
  54. package/lib/p521.d.ts +25 -52
  55. package/lib/p521.js +15 -13
  56. package/lib/secp256k1.d.ts +26 -42
  57. package/lib/secp256k1.js +118 -157
  58. package/lib/stark.d.ts +36 -21
  59. package/lib/stark.js +107 -39
  60. package/package.json +14 -9
@@ -5,6 +5,7 @@ import { twistedEdwards } from './abstract/edwards.js';
5
5
  import { montgomery } from './abstract/montgomery.js';
6
6
  import { mod, pow2, isNegativeLE, Fp as Field, FpSqrtEven } from './abstract/modular.js';
7
7
  import { ensureBytes, equalBytes, bytesToHex, bytesToNumberLE, numberToBytesLE, } from './abstract/utils.js';
8
+ import * as htf from './abstract/hash-to-curve.js';
8
9
  /**
9
10
  * ed25519 Twisted Edwards curve with following addons:
10
11
  * - X25519 ECDH
@@ -79,57 +80,107 @@ export const ED25519_TORSION_SUBGROUP = [
79
80
  'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
80
81
  ];
81
82
  const Fp = Field(ED25519_P, undefined, true);
83
+ const ED25519_DEF = {
84
+ // Param: a
85
+ a: BigInt(-1),
86
+ // Equal to -121665/121666 over finite field.
87
+ // Negative number is P - number, and division is invert(number, P)
88
+ d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
89
+ // Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
90
+ Fp,
91
+ // Subgroup order: how many points ed25519 has
92
+ // 2n ** 252n + 27742317777372353535851937790883648493n;
93
+ n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
94
+ // Cofactor
95
+ h: BigInt(8),
96
+ // Base point (x, y) aka generator point
97
+ Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
98
+ Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
99
+ hash: sha512,
100
+ randomBytes,
101
+ adjustScalarBytes,
102
+ // dom2
103
+ // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
104
+ // Constant-time, u/√v
105
+ uvRatio,
106
+ };
107
+ export const ed25519 = twistedEdwards(ED25519_DEF);
108
+ function ed25519_domain(data, ctx, phflag) {
109
+ if (ctx.length > 255)
110
+ throw new Error('Context is too big');
111
+ return concatBytes(utf8ToBytes('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
112
+ }
113
+ export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
114
+ export const ed25519ph = twistedEdwards({
115
+ ...ED25519_DEF,
116
+ domain: ed25519_domain,
117
+ preHash: sha512,
118
+ });
119
+ export const x25519 = montgomery({
120
+ P: ED25519_P,
121
+ a24: BigInt('121665'),
122
+ montgomeryBits: 255,
123
+ nByteLength: 32,
124
+ Gu: '0900000000000000000000000000000000000000000000000000000000000000',
125
+ powPminus2: (x) => {
126
+ const P = ED25519_P;
127
+ // x^(p-2) aka x^(2^255-21)
128
+ const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
129
+ return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
130
+ },
131
+ adjustScalarBytes,
132
+ });
82
133
  // Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
83
134
  // NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
84
135
  // SageMath returns different root first and everything falls apart
85
136
  const ELL2_C1 = (Fp.ORDER + BigInt(3)) / BigInt(8); // 1. c1 = (q + 3) / 8 # Integer arithmetic
86
137
  const ELL2_C2 = Fp.pow(_2n, ELL2_C1); // 2. c2 = 2^c1
87
- const ELL2_C3 = Fp.sqrt(Fp.negate(Fp.ONE)); // 3. c3 = sqrt(-1)
138
+ const ELL2_C3 = Fp.sqrt(Fp.neg(Fp.ONE)); // 3. c3 = sqrt(-1)
88
139
  const ELL2_C4 = (Fp.ORDER - BigInt(5)) / BigInt(8); // 4. c4 = (q - 5) / 8 # Integer arithmetic
89
140
  const ELL2_J = BigInt(486662);
90
141
  // prettier-ignore
91
142
  function map_to_curve_elligator2_curve25519(u) {
92
- let tv1 = Fp.square(u); // 1. tv1 = u^2
143
+ let tv1 = Fp.sqr(u); // 1. tv1 = u^2
93
144
  tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
94
145
  let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
95
- let x1n = Fp.negate(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
96
- let tv2 = Fp.square(xd); // 5. tv2 = xd^2
146
+ let x1n = Fp.neg(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
147
+ let tv2 = Fp.sqr(xd); // 5. tv2 = xd^2
97
148
  let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
98
149
  let gx1 = Fp.mul(tv1, ELL2_J); // 7. gx1 = J * tv1 # x1n + J * xd
99
150
  gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
100
151
  gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
101
152
  gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
102
- let tv3 = Fp.square(gxd); // 11. tv3 = gxd^2
103
- tv2 = Fp.square(tv3); // 12. tv2 = tv3^2 # gxd^4
153
+ let tv3 = Fp.sqr(gxd); // 11. tv3 = gxd^2
154
+ tv2 = Fp.sqr(tv3); // 12. tv2 = tv3^2 # gxd^4
104
155
  tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
105
156
  tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
106
157
  tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
107
158
  let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
108
159
  y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
109
160
  let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
110
- tv2 = Fp.square(y11); // 19. tv2 = y11^2
161
+ tv2 = Fp.sqr(y11); // 19. tv2 = y11^2
111
162
  tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
112
- let e1 = Fp.equals(tv2, gx1); // 21. e1 = tv2 == gx1
163
+ let e1 = Fp.eql(tv2, gx1); // 21. e1 = tv2 == gx1
113
164
  let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
114
165
  let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
115
166
  let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
116
167
  y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
117
168
  let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
118
169
  let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
119
- tv2 = Fp.square(y21); // 28. tv2 = y21^2
170
+ tv2 = Fp.sqr(y21); // 28. tv2 = y21^2
120
171
  tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
121
- let e2 = Fp.equals(tv2, gx2); // 30. e2 = tv2 == gx2
172
+ let e2 = Fp.eql(tv2, gx2); // 30. e2 = tv2 == gx2
122
173
  let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
123
- tv2 = Fp.square(y1); // 32. tv2 = y1^2
174
+ tv2 = Fp.sqr(y1); // 32. tv2 = y1^2
124
175
  tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
125
- let e3 = Fp.equals(tv2, gx1); // 34. e3 = tv2 == gx1
176
+ let e3 = Fp.eql(tv2, gx1); // 34. e3 = tv2 == gx1
126
177
  let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
127
178
  let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
128
179
  let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
129
- y = Fp.cmov(y, Fp.negate(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
180
+ y = Fp.cmov(y, Fp.neg(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
130
181
  return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1)
131
182
  }
132
- const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.negate(BigInt(486664))); // sgn0(c1) MUST equal 0
183
+ const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.neg(BigInt(486664))); // sgn0(c1) MUST equal 0
133
184
  function map_to_curve_elligator2_edwards25519(u) {
134
185
  const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) = map_to_curve_elligator2_curve25519(u)
135
186
  let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
@@ -138,7 +189,7 @@ function map_to_curve_elligator2_edwards25519(u) {
138
189
  let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
139
190
  let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
140
191
  let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
141
- let e = Fp.equals(tv1, Fp.ZERO); // 8. e = tv1 == 0
192
+ let e = Fp.eql(tv1, Fp.ZERO); // 8. e = tv1 == 0
142
193
  xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
143
194
  xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
144
195
  yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
@@ -146,68 +197,19 @@ function map_to_curve_elligator2_edwards25519(u) {
146
197
  const inv = Fp.invertBatch([xd, yd]); // batch division
147
198
  return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
148
199
  }
149
- const ED25519_DEF = {
150
- // Param: a
151
- a: BigInt(-1),
152
- // Equal to -121665/121666 over finite field.
153
- // Negative number is P - number, and division is invert(number, P)
154
- d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
155
- // Finite field 𝔽p over which we'll do calculations; 2n ** 255n - 19n
156
- Fp,
157
- // Subgroup order: how many points ed25519 has
158
- // 2n ** 252n + 27742317777372353535851937790883648493n;
159
- n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
160
- // Cofactor
161
- h: BigInt(8),
162
- // Base point (x, y) aka generator point
163
- Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
164
- Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
200
+ const { hashToCurve, encodeToCurve } = htf.hashToCurve(ed25519.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), {
201
+ DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
202
+ encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_',
203
+ p: Fp.ORDER,
204
+ m: 1,
205
+ k: 128,
206
+ expand: 'xmd',
165
207
  hash: sha512,
166
- randomBytes,
167
- adjustScalarBytes,
168
- // dom2
169
- // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
170
- // Constant-time, u/√v
171
- uvRatio,
172
- htfDefaults: {
173
- DST: 'edwards25519_XMD:SHA-512_ELL2_RO_',
174
- p: Fp.ORDER,
175
- m: 1,
176
- k: 128,
177
- expand: 'xmd',
178
- hash: sha512,
179
- },
180
- mapToCurve: (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]),
181
- };
182
- export const ed25519 = twistedEdwards(ED25519_DEF);
183
- function ed25519_domain(data, ctx, phflag) {
184
- if (ctx.length > 255)
185
- throw new Error('Context is too big');
186
- return concatBytes(utf8ToBytes('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
187
- }
188
- export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
189
- export const ed25519ph = twistedEdwards({
190
- ...ED25519_DEF,
191
- domain: ed25519_domain,
192
- preHash: sha512,
193
- });
194
- export const x25519 = montgomery({
195
- P: ED25519_P,
196
- a24: BigInt('121665'),
197
- montgomeryBits: 255,
198
- nByteLength: 32,
199
- Gu: '0900000000000000000000000000000000000000000000000000000000000000',
200
- powPminus2: (x) => {
201
- const P = ED25519_P;
202
- // x^(p-2) aka x^(2^255-21)
203
- const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
204
- return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
205
- },
206
- adjustScalarBytes,
207
208
  });
209
+ export { hashToCurve, encodeToCurve };
208
210
  function assertRstPoint(other) {
209
211
  if (!(other instanceof RistrettoPoint))
210
- throw new TypeError('RistrettoPoint expected');
212
+ throw new Error('RistrettoPoint expected');
211
213
  }
212
214
  // √(-1) aka √(a) aka 2^((p-1)/4)
213
215
  const SQRT_M1 = BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752');
@@ -222,13 +224,13 @@ const D_MINUS_ONE_SQ = BigInt('4044083434630853685810104246932319082624839914623
222
224
  // Calculates 1/√(number)
223
225
  const invertSqrt = (number) => uvRatio(_1n, number);
224
226
  const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
225
- const bytes255ToNumberLE = (bytes) => ed25519.utils.mod(bytesToNumberLE(bytes) & MAX_255B);
227
+ const bytes255ToNumberLE = (bytes) => ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
226
228
  // Computes Elligator map for Ristretto
227
229
  // https://ristretto.group/formulas/elligator.html
228
230
  function calcElligatorRistrettoMap(r0) {
229
231
  const { d } = ed25519.CURVE;
230
232
  const P = ed25519.CURVE.Fp.ORDER;
231
- const { mod } = ed25519.utils;
233
+ const mod = ed25519.CURVE.Fp.create;
232
234
  const r = mod(SQRT_M1 * r0 * r0); // 1
233
235
  const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
234
236
  let c = BigInt(-1); // 3
@@ -286,7 +288,7 @@ export class RistrettoPoint {
286
288
  hex = ensureBytes(hex, 32);
287
289
  const { a, d } = ed25519.CURVE;
288
290
  const P = ed25519.CURVE.Fp.ORDER;
289
- const { mod } = ed25519.utils;
291
+ const mod = ed25519.CURVE.Fp.create;
290
292
  const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint';
291
293
  const s = bytes255ToNumberLE(hex);
292
294
  // 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
@@ -316,9 +318,9 @@ export class RistrettoPoint {
316
318
  * https://ristretto.group/formulas/encoding.html
317
319
  */
318
320
  toRawBytes() {
319
- let { x, y, z, t } = this.ep;
321
+ let { ex: x, ey: y, ez: z, et: t } = this.ep;
320
322
  const P = ed25519.CURVE.Fp.ORDER;
321
- const { mod } = ed25519.utils;
323
+ const mod = ed25519.CURVE.Fp.create;
322
324
  const u1 = mod(mod(z + y) * mod(z - y)); // 1
323
325
  const u2 = mod(x * y); // 2
324
326
  // Square root always exists
@@ -354,12 +356,12 @@ export class RistrettoPoint {
354
356
  // Compare one point to another.
355
357
  equals(other) {
356
358
  assertRstPoint(other);
357
- const a = this.ep;
358
- const b = other.ep;
359
- const { mod } = ed25519.utils;
359
+ const { ex: X1, ey: Y1 } = this.ep;
360
+ const { ex: X2, ey: Y2 } = this.ep;
361
+ const mod = ed25519.CURVE.Fp.create;
360
362
  // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
361
- const one = mod(a.x * b.y) === mod(a.y * b.x);
362
- const two = mod(a.y * b.y) === mod(a.x * b.x);
363
+ const one = mod(X1 * Y2) === mod(Y1 * X2);
364
+ const two = mod(Y1 * Y2) === mod(X1 * X2);
363
365
  return one || two;
364
366
  }
365
367
  add(other) {
package/lib/esm/ed448.js CHANGED
@@ -4,6 +4,7 @@ import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/h
4
4
  import { twistedEdwards } from './abstract/edwards.js';
5
5
  import { mod, pow2, Fp as Field } from './abstract/modular.js';
6
6
  import { montgomery } from './abstract/montgomery.js';
7
+ import * as htf from './abstract/hash-to-curve.js';
7
8
  /**
8
9
  * Edwards448 (not Ed448-Goldilocks) curve with following addons:
9
10
  * * X448 ECDH
@@ -46,79 +47,6 @@ function adjustScalarBytes(bytes) {
46
47
  return bytes;
47
48
  }
48
49
  const Fp = Field(ed448P, 456, true);
49
- // Hash To Curve Elligator2 Map
50
- const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
51
- const ELL2_J = BigInt(156326);
52
- function map_to_curve_elligator2_curve448(u) {
53
- let tv1 = Fp.square(u); // 1. tv1 = u^2
54
- let e1 = Fp.equals(tv1, Fp.ONE); // 2. e1 = tv1 == 1
55
- tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
56
- let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
57
- let x1n = Fp.negate(ELL2_J); // 5. x1n = -J
58
- let tv2 = Fp.square(xd); // 6. tv2 = xd^2
59
- let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
60
- let gx1 = Fp.mul(tv1, Fp.negate(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
61
- gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
62
- gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
63
- gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
64
- let tv3 = Fp.square(gxd); // 12. tv3 = gxd^2
65
- tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
66
- tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
67
- let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
68
- y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
69
- let x2n = Fp.mul(x1n, Fp.negate(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
70
- let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
71
- y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
72
- tv2 = Fp.square(y1); // 20. tv2 = y1^2
73
- tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
74
- let e2 = Fp.equals(tv2, gx1); // 22. e2 = tv2 == gx1
75
- let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
76
- let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
77
- let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
78
- y = Fp.cmov(y, Fp.negate(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
79
- return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
80
- }
81
- function map_to_curve_elligator2_edwards448(u) {
82
- let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
83
- let xn2 = Fp.square(xn); // 2. xn2 = xn^2
84
- let xd2 = Fp.square(xd); // 3. xd2 = xd^2
85
- let xd4 = Fp.square(xd2); // 4. xd4 = xd2^2
86
- let yn2 = Fp.square(yn); // 5. yn2 = yn^2
87
- let yd2 = Fp.square(yd); // 6. yd2 = yd^2
88
- let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
89
- let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
90
- xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
91
- xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
92
- xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
93
- xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
94
- tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
95
- tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
96
- let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
97
- let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
98
- tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
99
- let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
100
- tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
101
- let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
102
- let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
103
- yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
104
- yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
105
- tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
106
- tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
107
- tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
108
- tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
109
- tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
110
- let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
111
- tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
112
- yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
113
- tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
114
- let e = Fp.equals(tv1, Fp.ZERO); // 33. e = tv1 == 0
115
- xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
116
- xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
117
- yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
118
- yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
119
- const inv = Fp.invertBatch([xEd, yEd]); // batch division
120
- return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
121
- }
122
50
  const ED448_DEF = {
123
51
  // Param: a
124
52
  a: BigInt(1),
@@ -126,7 +54,8 @@ const ED448_DEF = {
126
54
  d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
127
55
  // Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n
128
56
  Fp,
129
- // Subgroup order: how many points ed448 has; 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
57
+ // Subgroup order: how many points curve has;
58
+ // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
130
59
  n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
131
60
  nBitLength: 456,
132
61
  // Cofactor
@@ -165,15 +94,6 @@ const ED448_DEF = {
165
94
  // square root exists, and the decoding fails.
166
95
  return { isValid: mod(x2 * v, P) === u, value: x };
167
96
  },
168
- htfDefaults: {
169
- DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
170
- p: Fp.ORDER,
171
- m: 1,
172
- k: 224,
173
- expand: 'xof',
174
- hash: shake256,
175
- },
176
- mapToCurve: (scalars) => map_to_curve_elligator2_edwards448(scalars[0]),
177
97
  };
178
98
  export const ed448 = twistedEdwards(ED448_DEF);
179
99
  // NOTE: there is no ed448ctx, since ed448 supports ctx by default
@@ -206,3 +126,86 @@ export const x448 = montgomery({
206
126
  // return numberToBytesLE(u, 56);
207
127
  // },
208
128
  });
129
+ // Hash To Curve Elligator2 Map
130
+ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
131
+ const ELL2_J = BigInt(156326);
132
+ function map_to_curve_elligator2_curve448(u) {
133
+ let tv1 = Fp.sqr(u); // 1. tv1 = u^2
134
+ let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1
135
+ tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
136
+ let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
137
+ let x1n = Fp.neg(ELL2_J); // 5. x1n = -J
138
+ let tv2 = Fp.sqr(xd); // 6. tv2 = xd^2
139
+ let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
140
+ let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
141
+ gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
142
+ gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
143
+ gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
144
+ let tv3 = Fp.sqr(gxd); // 12. tv3 = gxd^2
145
+ tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
146
+ tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
147
+ let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
148
+ y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
149
+ let x2n = Fp.mul(x1n, Fp.neg(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
150
+ let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
151
+ y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
152
+ tv2 = Fp.sqr(y1); // 20. tv2 = y1^2
153
+ tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
154
+ let e2 = Fp.eql(tv2, gx1); // 22. e2 = tv2 == gx1
155
+ let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
156
+ let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
157
+ let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
158
+ y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
159
+ return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
160
+ }
161
+ function map_to_curve_elligator2_edwards448(u) {
162
+ let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
163
+ let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2
164
+ let xd2 = Fp.sqr(xd); // 3. xd2 = xd^2
165
+ let xd4 = Fp.sqr(xd2); // 4. xd4 = xd2^2
166
+ let yn2 = Fp.sqr(yn); // 5. yn2 = yn^2
167
+ let yd2 = Fp.sqr(yd); // 6. yd2 = yd^2
168
+ let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
169
+ let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
170
+ xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
171
+ xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
172
+ xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
173
+ xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
174
+ tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
175
+ tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
176
+ let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
177
+ let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
178
+ tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
179
+ let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
180
+ tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
181
+ let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
182
+ let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
183
+ yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
184
+ yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
185
+ tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
186
+ tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
187
+ tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
188
+ tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
189
+ tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
190
+ let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
191
+ tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
192
+ yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
193
+ tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
194
+ let e = Fp.eql(tv1, Fp.ZERO); // 33. e = tv1 == 0
195
+ xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
196
+ xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
197
+ yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
198
+ yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
199
+ const inv = Fp.invertBatch([xEd, yEd]); // batch division
200
+ return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
201
+ }
202
+ const { hashToCurve, encodeToCurve } = htf.hashToCurve(ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), {
203
+ DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
204
+ encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_',
205
+ p: Fp.ORDER,
206
+ m: 1,
207
+ k: 224,
208
+ expand: 'xof',
209
+ hash: shake256,
210
+ });
211
+ export { hashToCurve, encodeToCurve };
package/lib/esm/jubjub.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- import { sha256 } from '@noble/hashes/sha256';
2
+ import { sha512 } from '@noble/hashes/sha512';
3
3
  import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils';
4
4
  import { twistedEdwards } from './abstract/edwards.js';
5
5
  import { blake2s } from '@noble/hashes/blake2s';
@@ -7,22 +7,23 @@ import { Fp } from './abstract/modular.js';
7
7
  /**
8
8
  * jubjub Twisted Edwards curve.
9
9
  * https://neuromancer.sk/std/other/JubJub
10
+ * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them.
10
11
  */
11
12
  export const jubjub = twistedEdwards({
12
13
  // Params: a, d
13
14
  a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'),
14
15
  d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'),
15
16
  // Finite field 𝔽p over which we'll do calculations
17
+ // Same value as bls12-381 Fr (not Fp)
16
18
  Fp: Fp(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')),
17
- // Subgroup order: how many points ed25519 has
18
- // 2n ** 252n + 27742317777372353535851937790883648493n;
19
+ // Subgroup order: how many points curve has
19
20
  n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'),
20
21
  // Cofactor
21
22
  h: BigInt(8),
22
23
  // Base point (x, y) aka generator point
23
24
  Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'),
24
25
  Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'),
25
- hash: sha256,
26
+ hash: sha512,
26
27
  randomBytes,
27
28
  });
28
29
  const GH_FIRST_BLOCK = utf8ToBytes('096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0');
@@ -32,7 +33,7 @@ export function groupHash(tag, personalization) {
32
33
  h.update(GH_FIRST_BLOCK);
33
34
  h.update(tag);
34
35
  // NOTE: returns ExtendedPoint, in case it will be multiplied later
35
- let p = jubjub.ExtendedPoint.fromAffine(jubjub.Point.fromHex(h.digest()));
36
+ let p = jubjub.ExtendedPoint.fromHex(h.digest());
36
37
  // NOTE: cannot replace with isSmallOrder, returns Point*8
37
38
  p = p.multiply(jubjub.CURVE.h);
38
39
  if (p.equals(jubjub.ExtendedPoint.ZERO))
package/lib/esm/p256.js CHANGED
@@ -3,6 +3,7 @@ import { createCurve } from './_shortw_utils.js';
3
3
  import { sha256 } from '@noble/hashes/sha256';
4
4
  import { Fp as Field } from './abstract/modular.js';
5
5
  import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
6
+ import * as htf from './abstract/hash-to-curve.js';
6
7
  // NIST secp256r1 aka P256
7
8
  // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
8
9
  // Field over which we'll do calculations; 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
@@ -26,14 +27,15 @@ export const P256 = createCurve({
26
27
  Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
27
28
  h: BigInt(1),
28
29
  lowS: false,
29
- mapToCurve: (scalars) => mapSWU(scalars[0]),
30
- htfDefaults: {
31
- DST: 'P256_XMD:SHA-256_SSWU_RO_',
32
- p: Fp.ORDER,
33
- m: 1,
34
- k: 128,
35
- expand: 'xmd',
36
- hash: sha256,
37
- },
38
30
  }, sha256);
39
31
  export const secp256r1 = P256;
32
+ const { hashToCurve, encodeToCurve } = htf.hashToCurve(secp256r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {
33
+ DST: 'P256_XMD:SHA-256_SSWU_RO_',
34
+ encodeDST: 'P256_XMD:SHA-256_SSWU_NU_',
35
+ p: Fp.ORDER,
36
+ m: 1,
37
+ k: 128,
38
+ expand: 'xmd',
39
+ hash: sha256,
40
+ });
41
+ export { hashToCurve, encodeToCurve };
package/lib/esm/p384.js CHANGED
@@ -3,6 +3,7 @@ import { createCurve } from './_shortw_utils.js';
3
3
  import { sha384 } from '@noble/hashes/sha512';
4
4
  import { Fp as Field } from './abstract/modular.js';
5
5
  import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
6
+ import * as htf from './abstract/hash-to-curve.js';
6
7
  // NIST secp384r1 aka P384
7
8
  // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384
8
9
  // Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
@@ -31,14 +32,15 @@ export const P384 = createCurve({
31
32
  Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
32
33
  h: BigInt(1),
33
34
  lowS: false,
34
- mapToCurve: (scalars) => mapSWU(scalars[0]),
35
- htfDefaults: {
36
- DST: 'P384_XMD:SHA-384_SSWU_RO_',
37
- p: Fp.ORDER,
38
- m: 1,
39
- k: 192,
40
- expand: 'xmd',
41
- hash: sha384,
42
- },
43
35
  }, sha384);
44
36
  export const secp384r1 = P384;
37
+ const { hashToCurve, encodeToCurve } = htf.hashToCurve(secp384r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {
38
+ DST: 'P384_XMD:SHA-384_SSWU_RO_',
39
+ encodeDST: 'P384_XMD:SHA-384_SSWU_NU_',
40
+ p: Fp.ORDER,
41
+ m: 1,
42
+ k: 192,
43
+ expand: 'xmd',
44
+ hash: sha384,
45
+ });
46
+ export { hashToCurve, encodeToCurve };
package/lib/esm/p521.js CHANGED
@@ -4,6 +4,7 @@ import { sha512 } from '@noble/hashes/sha512';
4
4
  import { bytesToHex } from './abstract/utils.js';
5
5
  import { Fp as Field } from './abstract/modular.js';
6
6
  import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
7
+ import * as htf from './abstract/hash-to-curve.js';
7
8
  // NIST secp521r1 aka P521
8
9
  // Note that it's 521, which differs from 512 of its hash function.
9
10
  // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521
@@ -32,8 +33,7 @@ export const P521 = createCurve({
32
33
  Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
33
34
  h: BigInt(1),
34
35
  lowS: false,
35
- // P521 keys could be 130, 131, 132 bytes - which doesn't play nicely.
36
- // We ensure all keys are 132 bytes.
36
+ // P521 keys could be 130, 131, 132 bytes. We normalize to 132 bytes.
37
37
  // Does not replace validation; invalid keys would still be rejected.
38
38
  normalizePrivateKey(key) {
39
39
  if (typeof key === 'bigint')
@@ -43,16 +43,17 @@ export const P521 = createCurve({
43
43
  if (typeof key !== 'string' || !([130, 131, 132].includes(key.length))) {
44
44
  throw new Error('Invalid key');
45
45
  }
46
- return key.padStart(66 * 2, '0');
47
- },
48
- mapToCurve: (scalars) => mapSWU(scalars[0]),
49
- htfDefaults: {
50
- DST: 'P521_XMD:SHA-512_SSWU_RO_',
51
- p: Fp.ORDER,
52
- m: 1,
53
- k: 256,
54
- expand: 'xmd',
55
- hash: sha512,
46
+ return key.padStart(66 * 2, '0'); // ensure it's always 132 bytes
56
47
  },
57
48
  }, sha512);
58
49
  export const secp521r1 = P521;
50
+ const { hashToCurve, encodeToCurve } = htf.hashToCurve(secp521r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {
51
+ DST: 'P521_XMD:SHA-512_SSWU_RO_',
52
+ encodeDST: 'P521_XMD:SHA-512_SSWU_NU_',
53
+ p: Fp.ORDER,
54
+ m: 1,
55
+ k: 256,
56
+ expand: 'xmd',
57
+ hash: sha512,
58
+ });
59
+ export { hashToCurve, encodeToCurve };