@noble/curves 0.4.0 → 0.5.1
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 +254 -162
- package/lib/_shortw_utils.d.ts +75 -0
- package/lib/_shortw_utils.js +20 -0
- package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
- package/lib/{bls.js → abstract/bls.js} +28 -27
- package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
- package/lib/{edwards.js → abstract/edwards.js} +45 -4
- package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
- package/lib/{group.js → abstract/group.js} +4 -3
- package/lib/abstract/hash-to-curve.d.ts +28 -0
- package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +46 -11
- package/lib/{modular.d.ts → abstract/modular.d.ts} +13 -16
- package/lib/abstract/modular.js +337 -0
- package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
- package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
- package/lib/{utils.d.ts → abstract/utils.d.ts} +4 -2
- package/lib/{utils.js → abstract/utils.js} +1 -1
- package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
- package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
- package/lib/bls12-381.d.ts +66 -0
- package/lib/bls12-381.js +1132 -0
- package/lib/bn.d.ts +7 -0
- package/lib/bn.js +24 -0
- package/lib/ed25519.d.ts +48 -0
- package/lib/ed25519.js +385 -0
- package/lib/ed448.d.ts +3 -0
- package/lib/ed448.js +211 -0
- package/lib/esm/_shortw_utils.js +15 -0
- package/lib/esm/{bls.js → abstract/bls.js} +25 -24
- package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
- package/lib/esm/{group.js → abstract/group.js} +4 -3
- package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +43 -10
- package/lib/esm/abstract/modular.js +319 -0
- package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
- package/lib/esm/{utils.js → abstract/utils.js} +1 -1
- package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
- package/lib/esm/bls12-381.js +1129 -0
- package/lib/esm/bn.js +21 -0
- package/lib/esm/ed25519.js +381 -0
- package/lib/esm/ed448.js +208 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/jubjub.js +52 -0
- package/lib/esm/p192.js +21 -0
- package/lib/esm/p224.js +21 -0
- package/lib/esm/p256.js +39 -0
- package/lib/esm/p384.js +44 -0
- package/lib/esm/p521.js +58 -0
- package/lib/esm/pasta.js +29 -0
- package/lib/esm/secp256k1.js +293 -0
- package/lib/esm/stark.js +224 -0
- package/lib/index.d.ts +0 -0
- package/lib/index.js +2 -0
- package/lib/jubjub.d.ts +7 -0
- package/lib/jubjub.js +57 -0
- package/lib/p192.d.ts +130 -0
- package/lib/p192.js +24 -0
- package/lib/p224.d.ts +130 -0
- package/lib/p224.js +24 -0
- package/lib/p256.d.ts +130 -0
- package/lib/p256.js +42 -0
- package/lib/p384.d.ts +130 -0
- package/lib/p384.js +47 -0
- package/lib/p521.d.ts +131 -0
- package/lib/p521.js +61 -0
- package/lib/pasta.d.ts +4 -0
- package/lib/pasta.js +32 -0
- package/lib/secp256k1.d.ts +96 -0
- package/lib/secp256k1.js +297 -0
- package/lib/stark.d.ts +72 -0
- package/lib/stark.js +245 -0
- package/package.json +146 -50
- package/index.js +0 -1
- package/lib/esm/modular.js +0 -252
- package/lib/hashToCurve.d.ts +0 -13
- package/lib/modular.js +0 -267
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
+
// TODO: remove circular imports
|
|
3
|
+
import * as utils from './utils.js';
|
|
4
|
+
// Utilities for modular arithmetics and finite fields
|
|
5
|
+
// prettier-ignore
|
|
6
|
+
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
|
7
|
+
// prettier-ignore
|
|
8
|
+
const _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
|
|
9
|
+
// prettier-ignore
|
|
10
|
+
const _9n = BigInt(9), _16n = BigInt(16);
|
|
11
|
+
// Calculates a modulo b
|
|
12
|
+
export function mod(a, b) {
|
|
13
|
+
const result = a % b;
|
|
14
|
+
return result >= _0n ? result : b + result;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Efficiently exponentiate num to power and do modular division.
|
|
18
|
+
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
|
19
|
+
* @example
|
|
20
|
+
* powMod(2n, 6n, 11n) // 64n % 11n == 9n
|
|
21
|
+
*/
|
|
22
|
+
// TODO: use field version && remove
|
|
23
|
+
export function pow(num, power, modulo) {
|
|
24
|
+
if (modulo <= _0n || power < _0n)
|
|
25
|
+
throw new Error('Expected power/modulo > 0');
|
|
26
|
+
if (modulo === _1n)
|
|
27
|
+
return _0n;
|
|
28
|
+
let res = _1n;
|
|
29
|
+
while (power > _0n) {
|
|
30
|
+
if (power & _1n)
|
|
31
|
+
res = (res * num) % modulo;
|
|
32
|
+
num = (num * num) % modulo;
|
|
33
|
+
power >>= _1n;
|
|
34
|
+
}
|
|
35
|
+
return res;
|
|
36
|
+
}
|
|
37
|
+
// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
|
|
38
|
+
// TODO: Fp version?
|
|
39
|
+
export function pow2(x, power, modulo) {
|
|
40
|
+
let res = x;
|
|
41
|
+
while (power-- > _0n) {
|
|
42
|
+
res *= res;
|
|
43
|
+
res %= modulo;
|
|
44
|
+
}
|
|
45
|
+
return res;
|
|
46
|
+
}
|
|
47
|
+
// Inverses number over modulo
|
|
48
|
+
export function invert(number, modulo) {
|
|
49
|
+
if (number === _0n || modulo <= _0n) {
|
|
50
|
+
throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
|
|
51
|
+
}
|
|
52
|
+
// Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
|
|
53
|
+
let a = mod(number, modulo);
|
|
54
|
+
let b = modulo;
|
|
55
|
+
// prettier-ignore
|
|
56
|
+
let x = _0n, y = _1n, u = _1n, v = _0n;
|
|
57
|
+
while (a !== _0n) {
|
|
58
|
+
const q = b / a;
|
|
59
|
+
const r = b % a;
|
|
60
|
+
const m = x - u * q;
|
|
61
|
+
const n = y - v * q;
|
|
62
|
+
// prettier-ignore
|
|
63
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
64
|
+
}
|
|
65
|
+
const gcd = b;
|
|
66
|
+
if (gcd !== _1n)
|
|
67
|
+
throw new Error('invert: does not exist');
|
|
68
|
+
return mod(x, modulo);
|
|
69
|
+
}
|
|
70
|
+
// Tonelli-Shanks algorithm
|
|
71
|
+
// https://eprint.iacr.org/2012/685.pdf (page 12)
|
|
72
|
+
export function tonelliShanks(P) {
|
|
73
|
+
// Legendre constant: used to calculate Legendre symbol (a | p),
|
|
74
|
+
// which denotes the value of a^((p-1)/2) (mod p).
|
|
75
|
+
// (a | p) ≡ 1 if a is a square (mod p)
|
|
76
|
+
// (a | p) ≡ -1 if a is not a square (mod p)
|
|
77
|
+
// (a | p) ≡ 0 if a ≡ 0 (mod p)
|
|
78
|
+
const legendreC = (P - _1n) / _2n;
|
|
79
|
+
let Q, S, Z;
|
|
80
|
+
// Step 1: By factoring out powers of 2 from p - 1,
|
|
81
|
+
// find q and s such that p - 1 = q2s with q odd
|
|
82
|
+
for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++)
|
|
83
|
+
;
|
|
84
|
+
// Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
|
|
85
|
+
for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++)
|
|
86
|
+
;
|
|
87
|
+
// Fast-path
|
|
88
|
+
if (S === 1) {
|
|
89
|
+
const p1div4 = (P + _1n) / _4n;
|
|
90
|
+
return function tonelliFast(Fp, n) {
|
|
91
|
+
const root = Fp.pow(n, p1div4);
|
|
92
|
+
if (!Fp.equals(Fp.square(root), n))
|
|
93
|
+
throw new Error('Cannot find square root');
|
|
94
|
+
return root;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Slow-path
|
|
98
|
+
const Q1div2 = (Q + _1n) / _2n;
|
|
99
|
+
return function tonelliSlow(Fp, n) {
|
|
100
|
+
// Step 0: Check that n is indeed a square: (n | p) must be ≡ 1
|
|
101
|
+
if (Fp.pow(n, legendreC) !== Fp.ONE)
|
|
102
|
+
throw new Error('Cannot find square root');
|
|
103
|
+
let s = S;
|
|
104
|
+
let c = pow(Z, Q, P);
|
|
105
|
+
let r = Fp.pow(n, Q1div2);
|
|
106
|
+
let t = Fp.pow(n, Q);
|
|
107
|
+
let t2 = Fp.ZERO;
|
|
108
|
+
while (!Fp.equals(Fp.sub(t, Fp.ONE), Fp.ZERO)) {
|
|
109
|
+
t2 = Fp.square(t);
|
|
110
|
+
let i;
|
|
111
|
+
for (i = 1; i < s; i++) {
|
|
112
|
+
// stop if t2-1 == 0
|
|
113
|
+
if (Fp.equals(Fp.sub(t2, Fp.ONE), Fp.ZERO))
|
|
114
|
+
break;
|
|
115
|
+
// t2 *= t2
|
|
116
|
+
t2 = Fp.square(t2);
|
|
117
|
+
}
|
|
118
|
+
let b = pow(c, BigInt(1 << (s - i - 1)), P);
|
|
119
|
+
r = Fp.mul(r, b);
|
|
120
|
+
c = mod(b * b, P);
|
|
121
|
+
t = Fp.mul(t, c);
|
|
122
|
+
s = i;
|
|
123
|
+
}
|
|
124
|
+
return r;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function FpSqrt(P) {
|
|
128
|
+
// NOTE: different algorithms can give different roots, it is up to user to decide which one they want.
|
|
129
|
+
// For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
|
130
|
+
// P ≡ 3 (mod 4)
|
|
131
|
+
// √n = n^((P+1)/4)
|
|
132
|
+
if (P % _4n === _3n) {
|
|
133
|
+
// Not all roots possible!
|
|
134
|
+
// const ORDER =
|
|
135
|
+
// 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
|
|
136
|
+
// const NUM = 72057594037927816n;
|
|
137
|
+
const p1div4 = (P + _1n) / _4n;
|
|
138
|
+
return function sqrt3mod4(Fp, n) {
|
|
139
|
+
const root = Fp.pow(n, p1div4);
|
|
140
|
+
// Throw if root**2 != n
|
|
141
|
+
if (!Fp.equals(Fp.square(root), n))
|
|
142
|
+
throw new Error('Cannot find square root');
|
|
143
|
+
return root;
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)
|
|
147
|
+
if (P % _8n === _5n) {
|
|
148
|
+
const c1 = (P - _5n) / _8n;
|
|
149
|
+
return function sqrt5mod8(Fp, n) {
|
|
150
|
+
const n2 = Fp.mul(n, _2n);
|
|
151
|
+
const v = Fp.pow(n2, c1);
|
|
152
|
+
const nv = Fp.mul(n, v);
|
|
153
|
+
const i = Fp.mul(Fp.mul(nv, _2n), v);
|
|
154
|
+
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
|
155
|
+
if (!Fp.equals(Fp.square(root), n))
|
|
156
|
+
throw new Error('Cannot find square root');
|
|
157
|
+
return root;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// P ≡ 9 (mod 16)
|
|
161
|
+
if (P % _16n === _9n) {
|
|
162
|
+
// NOTE: tonelli is too slow for bls-Fp2 calculations even on start
|
|
163
|
+
// Means we cannot use sqrt for constants at all!
|
|
164
|
+
//
|
|
165
|
+
// const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
|
166
|
+
// const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
|
|
167
|
+
// const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
|
|
168
|
+
// const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
|
|
169
|
+
// sqrt = (x) => {
|
|
170
|
+
// let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4
|
|
171
|
+
// let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1
|
|
172
|
+
// const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1
|
|
173
|
+
// let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1
|
|
174
|
+
// const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x
|
|
175
|
+
// const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x
|
|
176
|
+
// tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
|
|
177
|
+
// tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
|
|
178
|
+
// const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x
|
|
179
|
+
// return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2
|
|
180
|
+
// }
|
|
181
|
+
}
|
|
182
|
+
// Other cases: Tonelli-Shanks algorithm
|
|
183
|
+
return tonelliShanks(P);
|
|
184
|
+
}
|
|
185
|
+
// Little-endian check for first LE bit (last BE bit);
|
|
186
|
+
export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
|
|
187
|
+
// prettier-ignore
|
|
188
|
+
const FIELD_FIELDS = [
|
|
189
|
+
'create', 'isValid', 'isZero', 'negate', 'invert', 'sqrt', 'square',
|
|
190
|
+
'equals', 'add', 'sub', 'mul', 'pow', 'div',
|
|
191
|
+
'addN', 'subN', 'mulN', 'squareN'
|
|
192
|
+
];
|
|
193
|
+
export function validateField(field) {
|
|
194
|
+
for (const i of ['ORDER', 'MASK']) {
|
|
195
|
+
if (typeof field[i] !== 'bigint')
|
|
196
|
+
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
|
|
197
|
+
}
|
|
198
|
+
for (const i of ['BYTES', 'BITS']) {
|
|
199
|
+
if (typeof field[i] !== 'number')
|
|
200
|
+
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
|
|
201
|
+
}
|
|
202
|
+
for (const i of FIELD_FIELDS) {
|
|
203
|
+
if (typeof field[i] !== 'function')
|
|
204
|
+
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Generic field functions
|
|
208
|
+
export function FpPow(f, num, power) {
|
|
209
|
+
// Should have same speed as pow for bigints
|
|
210
|
+
// TODO: benchmark!
|
|
211
|
+
if (power < _0n)
|
|
212
|
+
throw new Error('Expected power > 0');
|
|
213
|
+
if (power === _0n)
|
|
214
|
+
return f.ONE;
|
|
215
|
+
if (power === _1n)
|
|
216
|
+
return num;
|
|
217
|
+
let p = f.ONE;
|
|
218
|
+
let d = num;
|
|
219
|
+
while (power > _0n) {
|
|
220
|
+
if (power & _1n)
|
|
221
|
+
p = f.mul(p, d);
|
|
222
|
+
d = f.square(d);
|
|
223
|
+
power >>= 1n;
|
|
224
|
+
}
|
|
225
|
+
return p;
|
|
226
|
+
}
|
|
227
|
+
export function FpInvertBatch(f, nums) {
|
|
228
|
+
const tmp = new Array(nums.length);
|
|
229
|
+
// Walk from first to last, multiply them by each other MOD p
|
|
230
|
+
const lastMultiplied = nums.reduce((acc, num, i) => {
|
|
231
|
+
if (f.isZero(num))
|
|
232
|
+
return acc;
|
|
233
|
+
tmp[i] = acc;
|
|
234
|
+
return f.mul(acc, num);
|
|
235
|
+
}, f.ONE);
|
|
236
|
+
// Invert last element
|
|
237
|
+
const inverted = f.invert(lastMultiplied);
|
|
238
|
+
// Walk from last to first, multiply them by inverted each other MOD p
|
|
239
|
+
nums.reduceRight((acc, num, i) => {
|
|
240
|
+
if (f.isZero(num))
|
|
241
|
+
return acc;
|
|
242
|
+
tmp[i] = f.mul(acc, tmp[i]);
|
|
243
|
+
return f.mul(acc, num);
|
|
244
|
+
}, inverted);
|
|
245
|
+
return tmp;
|
|
246
|
+
}
|
|
247
|
+
export function FpDiv(f, lhs, rhs) {
|
|
248
|
+
return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
|
|
249
|
+
}
|
|
250
|
+
// This function returns True whenever the value x is a square in the field F.
|
|
251
|
+
export function FpIsSquare(f) {
|
|
252
|
+
const legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic
|
|
253
|
+
return (x) => {
|
|
254
|
+
const p = f.pow(x, legendreConst);
|
|
255
|
+
return f.equals(p, f.ZERO) || f.equals(p, f.ONE);
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
|
|
259
|
+
if (ORDER <= _0n)
|
|
260
|
+
throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);
|
|
261
|
+
const { nBitLength: BITS, nByteLength: BYTES } = utils.nLength(ORDER, bitLen);
|
|
262
|
+
if (BYTES > 2048)
|
|
263
|
+
throw new Error('Field lengths over 2048 bytes are not supported');
|
|
264
|
+
const sqrtP = FpSqrt(ORDER);
|
|
265
|
+
const f = Object.freeze({
|
|
266
|
+
ORDER,
|
|
267
|
+
BITS,
|
|
268
|
+
BYTES,
|
|
269
|
+
MASK: utils.bitMask(BITS),
|
|
270
|
+
ZERO: _0n,
|
|
271
|
+
ONE: _1n,
|
|
272
|
+
create: (num) => mod(num, ORDER),
|
|
273
|
+
isValid: (num) => {
|
|
274
|
+
if (typeof num !== 'bigint')
|
|
275
|
+
throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
|
|
276
|
+
return _0n <= num && num < ORDER;
|
|
277
|
+
},
|
|
278
|
+
isZero: (num) => num === _0n,
|
|
279
|
+
isOdd: (num) => (num & _1n) === _1n,
|
|
280
|
+
negate: (num) => mod(-num, ORDER),
|
|
281
|
+
equals: (lhs, rhs) => lhs === rhs,
|
|
282
|
+
square: (num) => mod(num * num, ORDER),
|
|
283
|
+
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
|
|
284
|
+
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
|
|
285
|
+
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
|
|
286
|
+
pow: (num, power) => FpPow(f, num, power),
|
|
287
|
+
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
|
|
288
|
+
// Same as above, but doesn't normalize
|
|
289
|
+
squareN: (num) => num * num,
|
|
290
|
+
addN: (lhs, rhs) => lhs + rhs,
|
|
291
|
+
subN: (lhs, rhs) => lhs - rhs,
|
|
292
|
+
mulN: (lhs, rhs) => lhs * rhs,
|
|
293
|
+
invert: (num) => invert(num, ORDER),
|
|
294
|
+
sqrt: redef.sqrt || ((n) => sqrtP(f, n)),
|
|
295
|
+
invertBatch: (lst) => FpInvertBatch(f, lst),
|
|
296
|
+
// TODO: do we really need constant cmov?
|
|
297
|
+
// We don't have const-time bigints anyway, so probably will be not very useful
|
|
298
|
+
cmov: (a, b, c) => (c ? b : a),
|
|
299
|
+
toBytes: (num) => isLE ? utils.numberToBytesLE(num, BYTES) : utils.numberToBytesBE(num, BYTES),
|
|
300
|
+
fromBytes: (bytes) => {
|
|
301
|
+
if (bytes.length !== BYTES)
|
|
302
|
+
throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);
|
|
303
|
+
return isLE ? utils.bytesToNumberLE(bytes) : utils.bytesToNumberBE(bytes);
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
return Object.freeze(f);
|
|
307
|
+
}
|
|
308
|
+
export function FpSqrtOdd(Fp, elm) {
|
|
309
|
+
if (!Fp.isOdd)
|
|
310
|
+
throw new Error(`Field doesn't have isOdd`);
|
|
311
|
+
const root = Fp.sqrt(elm);
|
|
312
|
+
return Fp.isOdd(root) ? root : Fp.negate(root);
|
|
313
|
+
}
|
|
314
|
+
export function FpSqrtEven(Fp, elm) {
|
|
315
|
+
if (!Fp.isOdd)
|
|
316
|
+
throw new Error(`Field doesn't have isOdd`);
|
|
317
|
+
const root = Fp.sqrt(elm);
|
|
318
|
+
return Fp.isOdd(root) ? Fp.negate(root) : root;
|
|
319
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
1
2
|
import * as mod from './modular.js';
|
|
2
3
|
import { ensureBytes, numberToBytesLE, bytesToNumberLE,
|
|
3
4
|
// nLength,
|
|
@@ -161,8 +162,14 @@ export function montgomery(curveDef) {
|
|
|
161
162
|
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
|
|
162
163
|
return bytesToNumberLE(adjustScalarBytes(bytes));
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
/**
|
|
166
|
+
* Computes shared secret between private key "scalar" and public key's "u" (x) coordinate.
|
|
167
|
+
* We can get 'y' coordinate from 'u',
|
|
168
|
+
* but Point.fromHex also wants 'x' coordinate oddity flag,
|
|
169
|
+
* and we cannot get 'x' without knowing 'v'.
|
|
170
|
+
* Need to add generic conversion between twisted edwards and complimentary curve for JubJub.
|
|
171
|
+
*/
|
|
172
|
+
function scalarMult(scalar, u) {
|
|
166
173
|
const pointU = decodeUCoordinate(u);
|
|
167
174
|
const _scalar = decodeScalar(scalar);
|
|
168
175
|
const pu = montgomeryLadder(pointU, _scalar);
|
|
@@ -172,17 +179,19 @@ export function montgomery(curveDef) {
|
|
|
172
179
|
throw new Error('Invalid private or public key received');
|
|
173
180
|
return encodeUCoordinate(pu);
|
|
174
181
|
}
|
|
175
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Computes public key from private.
|
|
184
|
+
* Executes scalar multiplication of curve's base point by scalar.
|
|
185
|
+
* @param scalar private key
|
|
186
|
+
* @returns new public key
|
|
187
|
+
*/
|
|
176
188
|
function scalarMultBase(scalar) {
|
|
177
|
-
return scalarMult(CURVE.Gu
|
|
189
|
+
return scalarMult(scalar, CURVE.Gu);
|
|
178
190
|
}
|
|
179
191
|
return {
|
|
180
|
-
// NOTE: we can get 'y' coordinate from 'u', but Point.fromHex also wants 'x' coordinate oddity flag, and we cannot get 'x' without knowing 'v'
|
|
181
|
-
// Need to add generic conversion between twisted edwards and complimentary curve for JubJub
|
|
182
192
|
scalarMult,
|
|
183
193
|
scalarMultBase,
|
|
184
|
-
|
|
185
|
-
// getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(publicKey, privateKey),
|
|
194
|
+
getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey),
|
|
186
195
|
getPublicKey: (privateKey) => scalarMultBase(privateKey),
|
|
187
196
|
Gu: CURVE.Gu,
|
|
188
197
|
};
|