@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.
- package/README.md +49 -8
- package/lib/_shortw_utils.d.ts +11 -26
- package/lib/abstract/bls.d.ts +51 -35
- package/lib/abstract/bls.js +77 -139
- package/lib/abstract/{group.d.ts → curve.d.ts} +31 -1
- package/lib/abstract/{group.js → curve.js} +39 -2
- package/lib/abstract/edwards.d.ts +30 -81
- package/lib/abstract/edwards.js +225 -420
- package/lib/abstract/hash-to-curve.d.ts +25 -6
- package/lib/abstract/hash-to-curve.js +40 -12
- package/lib/abstract/modular.d.ts +20 -7
- package/lib/abstract/modular.js +80 -51
- package/lib/abstract/montgomery.js +3 -4
- package/lib/abstract/poseidon.d.ts +29 -0
- package/lib/abstract/poseidon.js +115 -0
- package/lib/abstract/utils.d.ts +5 -34
- package/lib/abstract/utils.js +23 -63
- package/lib/abstract/weierstrass.d.ts +56 -79
- package/lib/abstract/weierstrass.js +509 -641
- package/lib/bls12-381.d.ts +1 -0
- package/lib/bls12-381.js +75 -65
- package/lib/bn.js +1 -1
- package/lib/ed25519.d.ts +7 -5
- package/lib/ed25519.js +87 -84
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +88 -84
- package/lib/esm/abstract/bls.js +77 -139
- package/lib/esm/abstract/{group.js → curve.js} +37 -1
- package/lib/esm/abstract/edwards.js +223 -418
- package/lib/esm/abstract/hash-to-curve.js +38 -11
- package/lib/esm/abstract/modular.js +77 -50
- package/lib/esm/abstract/montgomery.js +4 -7
- package/lib/esm/abstract/poseidon.js +109 -0
- package/lib/esm/abstract/utils.js +21 -59
- package/lib/esm/abstract/weierstrass.js +508 -640
- package/lib/esm/bls12-381.js +86 -76
- package/lib/esm/bn.js +1 -1
- package/lib/esm/ed25519.js +85 -83
- package/lib/esm/ed448.js +86 -83
- package/lib/esm/jubjub.js +6 -5
- package/lib/esm/p256.js +11 -9
- package/lib/esm/p384.js +11 -9
- package/lib/esm/p521.js +13 -12
- package/lib/esm/secp256k1.js +118 -157
- package/lib/esm/stark.js +104 -39
- package/lib/jubjub.d.ts +3 -2
- package/lib/jubjub.js +6 -5
- package/lib/p192.d.ts +22 -52
- package/lib/p224.d.ts +22 -52
- package/lib/p256.d.ts +25 -52
- package/lib/p256.js +13 -10
- package/lib/p384.d.ts +25 -52
- package/lib/p384.js +13 -10
- package/lib/p521.d.ts +25 -52
- package/lib/p521.js +15 -13
- package/lib/secp256k1.d.ts +26 -42
- package/lib/secp256k1.js +118 -157
- package/lib/stark.d.ts +36 -21
- package/lib/stark.js +107 -39
- package/package.json +14 -9
package/lib/esm/ed25519.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
96
|
-
let tv2 = Fp.
|
|
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.
|
|
103
|
-
tv2 = Fp.
|
|
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.
|
|
161
|
+
tv2 = Fp.sqr(y11); // 19. tv2 = y11^2
|
|
111
162
|
tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
|
|
112
|
-
let e1 = Fp.
|
|
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.
|
|
170
|
+
tv2 = Fp.sqr(y21); // 28. tv2 = y21^2
|
|
120
171
|
tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
|
|
121
|
-
let e2 = Fp.
|
|
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.
|
|
174
|
+
tv2 = Fp.sqr(y1); // 32. tv2 = y1^2
|
|
124
175
|
tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
|
|
125
|
-
let e3 = Fp.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
358
|
-
const
|
|
359
|
-
const
|
|
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(
|
|
362
|
-
const two = mod(
|
|
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
|
|
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 {
|
|
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
|
|
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:
|
|
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.
|
|
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
|
|
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 };
|