@ohos-ports/crypto 0.0.0-stage → 0.3.1-beta.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/LICENSE +7 -0
- package/README.md +60 -2
- package/dist/bech32.d.ts +53 -0
- package/dist/bech32.js +187 -0
- package/dist/blake2b.d.ts +7 -0
- package/dist/blake2b.js +213 -0
- package/dist/bls12_318.d.ts +48 -0
- package/dist/bls12_318.js +268 -0
- package/dist/ed25519.d.ts +55 -0
- package/dist/ed25519.js +721 -0
- package/dist/hasGlobalWebCrypto.d.ts +1 -0
- package/dist/hasGlobalWebCrypto.js +21 -0
- package/dist/hmacSHA512.d.ts +6 -0
- package/dist/hmacSHA512.js +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +30 -0
- package/dist/keccak.d.ts +4 -0
- package/dist/keccak.js +43 -0
- package/dist/kes/constants.d.ts +2 -0
- package/dist/kes/constants.js +5 -0
- package/dist/kes/index.d.ts +0 -0
- package/dist/kes/index.js +0 -0
- package/dist/kes/macro/sum_kes.d.ts +15 -0
- package/dist/kes/macro/sum_kes.js +9 -0
- package/dist/kes/singleKes.d.ts +0 -0
- package/dist/kes/singleKes.js +0 -0
- package/dist/noble/_assert.d.ts +23 -0
- package/dist/noble/_assert.js +55 -0
- package/dist/noble/_md.d.ts +29 -0
- package/dist/noble/_md.js +170 -0
- package/dist/noble/_shortw_utils.d.ts +61 -0
- package/dist/noble/_shortw_utils.js +63 -0
- package/dist/noble/_u64.d.ts +28 -0
- package/dist/noble/_u64.js +116 -0
- package/dist/noble/abstract/bls.d.ts +119 -0
- package/dist/noble/abstract/bls.js +334 -0
- package/dist/noble/abstract/curve.d.ts +83 -0
- package/dist/noble/abstract/curve.js +319 -0
- package/dist/noble/abstract/edwards.d.ts +85 -0
- package/dist/noble/abstract/edwards.js +508 -0
- package/dist/noble/abstract/hash-to-curve.d.ts +57 -0
- package/dist/noble/abstract/hash-to-curve.js +220 -0
- package/dist/noble/abstract/modular.d.ts +122 -0
- package/dist/noble/abstract/modular.js +455 -0
- package/dist/noble/abstract/montgomery.d.ts +28 -0
- package/dist/noble/abstract/montgomery.js +172 -0
- package/dist/noble/abstract/utils.d.ts +106 -0
- package/dist/noble/abstract/utils.js +442 -0
- package/dist/noble/bls12_381.d.ts +95 -0
- package/dist/noble/bls12_381.js +1434 -0
- package/dist/noble/crypto.d.ts +1 -0
- package/dist/noble/crypto.js +4 -0
- package/dist/noble/curves/curve.d.ts +69 -0
- package/dist/noble/curves/curve.js +167 -0
- package/dist/noble/curves/modular.d.ts +122 -0
- package/dist/noble/curves/modular.js +442 -0
- package/dist/noble/curves/utils.d.ts +93 -0
- package/dist/noble/curves/utils.js +385 -0
- package/dist/noble/curves/weierstrass.d.ts +240 -0
- package/dist/noble/curves/weierstrass.js +1178 -0
- package/dist/noble/ed25519.d.ts +100 -0
- package/dist/noble/ed25519.js +494 -0
- package/dist/noble/hmac.d.ts +25 -0
- package/dist/noble/hmac.js +101 -0
- package/dist/noble/index.d.ts +2 -0
- package/dist/noble/index.js +20 -0
- package/dist/noble/keccak.d.ts +58 -0
- package/dist/noble/keccak.js +289 -0
- package/dist/noble/ripemd_160.d.ts +20 -0
- package/dist/noble/ripemd_160.js +147 -0
- package/dist/noble/secp256k1.d.ts +98 -0
- package/dist/noble/secp256k1.js +309 -0
- package/dist/noble/sha256.d.ts +34 -0
- package/dist/noble/sha256.js +146 -0
- package/dist/noble/sha512.d.ts +66 -0
- package/dist/noble/sha512.js +301 -0
- package/dist/noble/utils.d.ts +90 -0
- package/dist/noble/utils.js +278 -0
- package/dist/ripemd_160.d.ts +1 -0
- package/dist/ripemd_160.js +23 -0
- package/dist/rust_vrf_reimpl/curves.d.ts +162 -0
- package/dist/rust_vrf_reimpl/curves.js +4225 -0
- package/dist/rust_vrf_reimpl/vrf03.d.ts +60 -0
- package/dist/rust_vrf_reimpl/vrf03.js +373 -0
- package/dist/rust_vrf_reimpl/vrf10.d.ts +73 -0
- package/dist/rust_vrf_reimpl/vrf10.js +468 -0
- package/dist/rust_vrf_reimpl/vrf10_batch.d.ts +53 -0
- package/dist/rust_vrf_reimpl/vrf10_batch.js +245 -0
- package/dist/secp256k1.d.ts +4 -0
- package/dist/secp256k1.js +33 -0
- package/dist/sha2_256.d.ts +16 -0
- package/dist/sha2_256.js +403 -0
- package/dist/sha2_512.d.ts +16 -0
- package/dist/sha2_512.js +256 -0
- package/dist/sha3.d.ts +17 -0
- package/dist/sha3.js +181 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.js +120 -0
- package/dist/utils/assert.d.ts +3 -0
- package/dist/utils/assert.js +55 -0
- package/dist/utils/base32.d.ts +5 -0
- package/dist/utils/base32.js +52 -0
- package/dist/utils/bigintToBuffer.d.ts +1 -0
- package/dist/utils/bigintToBuffer.js +27 -0
- package/dist/utils/bytesToHex.d.ts +2 -0
- package/dist/utils/bytesToHex.js +15 -0
- package/dist/utils/getRandomValues.d.ts +4 -0
- package/dist/utils/getRandomValues.js +12 -0
- package/dist/utils/hexToBytes.d.ts +2 -0
- package/dist/utils/hexToBytes.js +14 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/positiveMod.d.ts +1 -0
- package/dist/utils/positiveMod.js +11 -0
- package/dist/utils/promisifySync.d.ts +0 -0
- package/dist/utils/promisifySync.js +0 -0
- package/dist/utils/rotr32.d.ts +2 -0
- package/dist/utils/rotr32.js +7 -0
- package/dist/vrf.d.ts +74 -0
- package/dist/vrf.js +286 -0
- package/package.json +49 -4
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
THIS IMPLEMENTATION WAS TAKEN FROM `@noble/hashes`
|
|
4
|
+
|
|
5
|
+
original source: https://github.com/paulmillr/noble-curves/blob/38a4ca1e6b0a80c60b11bbb6b3d71e3bfabd5bbb/src/abstract/modular.ts
|
|
6
|
+
|
|
7
|
+
it was modified and adapted to this repository
|
|
8
|
+
|
|
9
|
+
the main reason for copying over and not using as dependency is because of different target in the `tsconfig.json`
|
|
10
|
+
|
|
11
|
+
`@noble/hashes` targets es2020, which tends to cause problems with some other (older) packages sometimes
|
|
12
|
+
|
|
13
|
+
this repo targets ES5+
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.mapHashToField = exports.getMinHashLength = exports.getFieldBytesLength = exports.hashToPrivateScalar = exports.FpSqrtEven = exports.FpSqrtOdd = exports.Field = exports.nLength = exports.FpIsSquare = exports.FpDiv = exports.FpInvertBatch = exports.FpPow = exports.validateField = exports.isNegativeLE = exports.FpSqrt = exports.tonelliShanks = exports.invert = exports.pow2 = exports.pow = exports.mod = void 0;
|
|
17
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
18
|
+
// Utilities for modular arithmetics and finite fields
|
|
19
|
+
var utils_1 = require("./utils.js");
|
|
20
|
+
// prettier-ignore
|
|
21
|
+
var _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
|
22
|
+
// prettier-ignore
|
|
23
|
+
var _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
|
|
24
|
+
// prettier-ignore
|
|
25
|
+
var _9n = BigInt(9), _16n = BigInt(16);
|
|
26
|
+
// Calculates a modulo b
|
|
27
|
+
function mod(a, b) {
|
|
28
|
+
var result = a % b;
|
|
29
|
+
return result >= _0n ? result : b + result;
|
|
30
|
+
}
|
|
31
|
+
exports.mod = mod;
|
|
32
|
+
/**
|
|
33
|
+
* Efficiently raise num to power and do modular division.
|
|
34
|
+
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
|
35
|
+
* @example
|
|
36
|
+
* pow(2n, 6n, 11n) // 64n % 11n == 9n
|
|
37
|
+
*/
|
|
38
|
+
// TODO: use field version && remove
|
|
39
|
+
function pow(num, power, modulo) {
|
|
40
|
+
if (modulo <= _0n || power < _0n)
|
|
41
|
+
throw new Error('Expected power/modulo > 0');
|
|
42
|
+
if (modulo === _1n)
|
|
43
|
+
return _0n;
|
|
44
|
+
var res = _1n;
|
|
45
|
+
while (power > _0n) {
|
|
46
|
+
if (power & _1n)
|
|
47
|
+
res = (res * num) % modulo;
|
|
48
|
+
num = (num * num) % modulo;
|
|
49
|
+
power >>= _1n;
|
|
50
|
+
}
|
|
51
|
+
return res;
|
|
52
|
+
}
|
|
53
|
+
exports.pow = pow;
|
|
54
|
+
// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
|
|
55
|
+
function pow2(x, power, modulo) {
|
|
56
|
+
var res = x;
|
|
57
|
+
while (power-- > _0n) {
|
|
58
|
+
res *= res;
|
|
59
|
+
res %= modulo;
|
|
60
|
+
}
|
|
61
|
+
return res;
|
|
62
|
+
}
|
|
63
|
+
exports.pow2 = pow2;
|
|
64
|
+
// Inverses number over modulo
|
|
65
|
+
function invert(number, modulo) {
|
|
66
|
+
if (number === _0n || modulo <= _0n) {
|
|
67
|
+
throw new Error("invert: expected positive integers, got n=".concat(number, " mod=").concat(modulo));
|
|
68
|
+
}
|
|
69
|
+
// Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
|
|
70
|
+
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
|
|
71
|
+
var a = mod(number, modulo);
|
|
72
|
+
var b = modulo;
|
|
73
|
+
// prettier-ignore
|
|
74
|
+
var x = _0n, y = _1n, u = _1n, v = _0n;
|
|
75
|
+
while (a !== _0n) {
|
|
76
|
+
// JIT applies optimization if those two lines follow each other
|
|
77
|
+
var q = b / a;
|
|
78
|
+
var r = b % a;
|
|
79
|
+
var m = x - u * q;
|
|
80
|
+
var n = y - v * q;
|
|
81
|
+
// prettier-ignore
|
|
82
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
83
|
+
}
|
|
84
|
+
var gcd = b;
|
|
85
|
+
if (gcd !== _1n)
|
|
86
|
+
throw new Error('invert: does not exist');
|
|
87
|
+
return mod(x, modulo);
|
|
88
|
+
}
|
|
89
|
+
exports.invert = invert;
|
|
90
|
+
/**
|
|
91
|
+
* Tonelli-Shanks square root search algorithm.
|
|
92
|
+
* 1. https://eprint.iacr.org/2012/685.pdf (page 12)
|
|
93
|
+
* 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
|
|
94
|
+
* Will start an infinite loop if field order P is not prime.
|
|
95
|
+
* @param P field order
|
|
96
|
+
* @returns function that takes field Fp (created from P) and number n
|
|
97
|
+
*/
|
|
98
|
+
function tonelliShanks(P) {
|
|
99
|
+
// Legendre constant: used to calculate Legendre symbol (a | p),
|
|
100
|
+
// which denotes the value of a^((p-1)/2) (mod p).
|
|
101
|
+
// (a | p) ≡ 1 if a is a square (mod p)
|
|
102
|
+
// (a | p) ≡ -1 if a is not a square (mod p)
|
|
103
|
+
// (a | p) ≡ 0 if a ≡ 0 (mod p)
|
|
104
|
+
var legendreC = (P - _1n) / _2n;
|
|
105
|
+
var Q, S, Z;
|
|
106
|
+
// Step 1: By factoring out powers of 2 from p - 1,
|
|
107
|
+
// find q and s such that p - 1 = q*(2^s) with q odd
|
|
108
|
+
for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++)
|
|
109
|
+
;
|
|
110
|
+
// Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
|
|
111
|
+
for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++)
|
|
112
|
+
;
|
|
113
|
+
// Fast-path
|
|
114
|
+
if (S === 1) {
|
|
115
|
+
var p1div4_1 = (P + _1n) / _4n;
|
|
116
|
+
return function tonelliFast(Fp, n) {
|
|
117
|
+
var root = Fp.pow(n, p1div4_1);
|
|
118
|
+
if (!Fp.eql(Fp.sqr(root), n))
|
|
119
|
+
throw new Error('Cannot find square root');
|
|
120
|
+
return root;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Slow-path
|
|
124
|
+
var Q1div2 = (Q + _1n) / _2n;
|
|
125
|
+
return function tonelliSlow(Fp, n) {
|
|
126
|
+
// Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1
|
|
127
|
+
if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))
|
|
128
|
+
throw new Error('Cannot find square root');
|
|
129
|
+
var r = S;
|
|
130
|
+
// TODO: will fail at Fp2/etc
|
|
131
|
+
var g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b
|
|
132
|
+
var x = Fp.pow(n, Q1div2); // first guess at the square root
|
|
133
|
+
var b = Fp.pow(n, Q); // first guess at the fudge factor
|
|
134
|
+
while (!Fp.eql(b, Fp.ONE)) {
|
|
135
|
+
if (Fp.eql(b, Fp.ZERO))
|
|
136
|
+
return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)
|
|
137
|
+
// Find m such b^(2^m)==1
|
|
138
|
+
var m = 1;
|
|
139
|
+
for (var t2 = Fp.sqr(b); m < r; m++) {
|
|
140
|
+
if (Fp.eql(t2, Fp.ONE))
|
|
141
|
+
break;
|
|
142
|
+
t2 = Fp.sqr(t2); // t2 *= t2
|
|
143
|
+
}
|
|
144
|
+
// NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow
|
|
145
|
+
var ge = Fp.pow(g, _1n << BigInt(r - m - 1)); // ge = 2^(r-m-1)
|
|
146
|
+
g = Fp.sqr(ge); // g = ge * ge
|
|
147
|
+
x = Fp.mul(x, ge); // x *= ge
|
|
148
|
+
b = Fp.mul(b, g); // b *= g
|
|
149
|
+
r = m;
|
|
150
|
+
}
|
|
151
|
+
return x;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
exports.tonelliShanks = tonelliShanks;
|
|
155
|
+
function FpSqrt(P) {
|
|
156
|
+
// NOTE: different algorithms can give different roots, it is up to user to decide which one they want.
|
|
157
|
+
// For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
|
158
|
+
// P ≡ 3 (mod 4)
|
|
159
|
+
// √n = n^((P+1)/4)
|
|
160
|
+
if (P % _4n === _3n) {
|
|
161
|
+
// Not all roots possible!
|
|
162
|
+
// const ORDER =
|
|
163
|
+
// 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
|
|
164
|
+
// const NUM = 72057594037927816n;
|
|
165
|
+
var p1div4_2 = (P + _1n) / _4n;
|
|
166
|
+
return function sqrt3mod4(Fp, n) {
|
|
167
|
+
var root = Fp.pow(n, p1div4_2);
|
|
168
|
+
// Throw if root**2 != n
|
|
169
|
+
if (!Fp.eql(Fp.sqr(root), n))
|
|
170
|
+
throw new Error('Cannot find square root');
|
|
171
|
+
return root;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)
|
|
175
|
+
if (P % _8n === _5n) {
|
|
176
|
+
var c1_1 = (P - _5n) / _8n;
|
|
177
|
+
return function sqrt5mod8(Fp, n) {
|
|
178
|
+
var n2 = Fp.mul(n, _2n);
|
|
179
|
+
var v = Fp.pow(n2, c1_1);
|
|
180
|
+
var nv = Fp.mul(n, v);
|
|
181
|
+
var i = Fp.mul(Fp.mul(nv, _2n), v);
|
|
182
|
+
var root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
|
183
|
+
if (!Fp.eql(Fp.sqr(root), n))
|
|
184
|
+
throw new Error('Cannot find square root');
|
|
185
|
+
return root;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
// P ≡ 9 (mod 16)
|
|
189
|
+
if (P % _16n === _9n) {
|
|
190
|
+
// NOTE: tonelli is too slow for bls-Fp2 calculations even on start
|
|
191
|
+
// Means we cannot use sqrt for constants at all!
|
|
192
|
+
//
|
|
193
|
+
// const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
|
194
|
+
// const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
|
|
195
|
+
// const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
|
|
196
|
+
// const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
|
|
197
|
+
// sqrt = (x) => {
|
|
198
|
+
// let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4
|
|
199
|
+
// let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1
|
|
200
|
+
// const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1
|
|
201
|
+
// let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1
|
|
202
|
+
// const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x
|
|
203
|
+
// const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x
|
|
204
|
+
// tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
|
|
205
|
+
// tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
|
|
206
|
+
// const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x
|
|
207
|
+
// return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2
|
|
208
|
+
// }
|
|
209
|
+
}
|
|
210
|
+
// Other cases: Tonelli-Shanks algorithm
|
|
211
|
+
return tonelliShanks(P);
|
|
212
|
+
}
|
|
213
|
+
exports.FpSqrt = FpSqrt;
|
|
214
|
+
// Little-endian check for first LE bit (last BE bit);
|
|
215
|
+
var isNegativeLE = function (num, modulo) { return (mod(num, modulo) & _1n) === _1n; };
|
|
216
|
+
exports.isNegativeLE = isNegativeLE;
|
|
217
|
+
// prettier-ignore
|
|
218
|
+
var FIELD_FIELDS = [
|
|
219
|
+
'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',
|
|
220
|
+
'eql', 'add', 'sub', 'mul', 'pow', 'div',
|
|
221
|
+
'addN', 'subN', 'mulN', 'sqrN'
|
|
222
|
+
];
|
|
223
|
+
function validateField(field) {
|
|
224
|
+
var initial = {
|
|
225
|
+
ORDER: 'bigint',
|
|
226
|
+
MASK: 'bigint',
|
|
227
|
+
BYTES: 'isSafeInteger',
|
|
228
|
+
BITS: 'isSafeInteger',
|
|
229
|
+
};
|
|
230
|
+
var opts = FIELD_FIELDS.reduce(function (map, val) {
|
|
231
|
+
map[val] = 'function';
|
|
232
|
+
return map;
|
|
233
|
+
}, initial);
|
|
234
|
+
return (0, utils_1.validateObject)(field, opts);
|
|
235
|
+
}
|
|
236
|
+
exports.validateField = validateField;
|
|
237
|
+
// Generic field functions
|
|
238
|
+
/**
|
|
239
|
+
* Same as `pow` but for Fp: non-constant-time.
|
|
240
|
+
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
|
241
|
+
*/
|
|
242
|
+
function FpPow(f, num, power) {
|
|
243
|
+
// Should have same speed as pow for bigints
|
|
244
|
+
// TODO: benchmark!
|
|
245
|
+
if (power < _0n)
|
|
246
|
+
throw new Error('Expected power > 0');
|
|
247
|
+
if (power === _0n)
|
|
248
|
+
return f.ONE;
|
|
249
|
+
if (power === _1n)
|
|
250
|
+
return num;
|
|
251
|
+
var p = f.ONE;
|
|
252
|
+
var d = num;
|
|
253
|
+
while (power > _0n) {
|
|
254
|
+
if (power & _1n)
|
|
255
|
+
p = f.mul(p, d);
|
|
256
|
+
d = f.sqr(d);
|
|
257
|
+
power >>= _1n;
|
|
258
|
+
}
|
|
259
|
+
return p;
|
|
260
|
+
}
|
|
261
|
+
exports.FpPow = FpPow;
|
|
262
|
+
/**
|
|
263
|
+
* Efficiently invert an array of Field elements.
|
|
264
|
+
* `inv(0)` will return `undefined` here: make sure to throw an error.
|
|
265
|
+
*/
|
|
266
|
+
function FpInvertBatch(f, nums) {
|
|
267
|
+
var tmp = new Array(nums.length);
|
|
268
|
+
// Walk from first to last, multiply them by each other MOD p
|
|
269
|
+
var lastMultiplied = nums.reduce(function (acc, num, i) {
|
|
270
|
+
if (f.is0(num))
|
|
271
|
+
return acc;
|
|
272
|
+
tmp[i] = acc;
|
|
273
|
+
return f.mul(acc, num);
|
|
274
|
+
}, f.ONE);
|
|
275
|
+
// Invert last element
|
|
276
|
+
var inverted = f.inv(lastMultiplied);
|
|
277
|
+
// Walk from last to first, multiply them by inverted each other MOD p
|
|
278
|
+
nums.reduceRight(function (acc, num, i) {
|
|
279
|
+
if (f.is0(num))
|
|
280
|
+
return acc;
|
|
281
|
+
tmp[i] = f.mul(acc, tmp[i]);
|
|
282
|
+
return f.mul(acc, num);
|
|
283
|
+
}, inverted);
|
|
284
|
+
return tmp;
|
|
285
|
+
}
|
|
286
|
+
exports.FpInvertBatch = FpInvertBatch;
|
|
287
|
+
function FpDiv(f, lhs, rhs) {
|
|
288
|
+
return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs));
|
|
289
|
+
}
|
|
290
|
+
exports.FpDiv = FpDiv;
|
|
291
|
+
// This function returns True whenever the value x is a square in the field F.
|
|
292
|
+
function FpIsSquare(f) {
|
|
293
|
+
var legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic
|
|
294
|
+
return function (x) {
|
|
295
|
+
var p = f.pow(x, legendreConst);
|
|
296
|
+
return f.eql(p, f.ZERO) || f.eql(p, f.ONE);
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
exports.FpIsSquare = FpIsSquare;
|
|
300
|
+
// CURVE.n lengths
|
|
301
|
+
function nLength(n, nBitLength) {
|
|
302
|
+
// Bit size, byte size of CURVE.n
|
|
303
|
+
var _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
|
|
304
|
+
var nByteLength = Math.ceil(_nBitLength / 8);
|
|
305
|
+
return { nBitLength: _nBitLength, nByteLength: nByteLength };
|
|
306
|
+
}
|
|
307
|
+
exports.nLength = nLength;
|
|
308
|
+
/**
|
|
309
|
+
* Initializes a finite field over prime. **Non-primes are not supported.**
|
|
310
|
+
* Do not init in loop: slow. Very fragile: always run a benchmark on a change.
|
|
311
|
+
* Major performance optimizations:
|
|
312
|
+
* * a) denormalized operations like mulN instead of mul
|
|
313
|
+
* * b) same object shape: never add or remove keys
|
|
314
|
+
* * c) Object.freeze
|
|
315
|
+
* @param ORDER prime positive bigint
|
|
316
|
+
* @param bitLen how many bits the field consumes
|
|
317
|
+
* @param isLE (def: false) if encoding / decoding should be in little-endian
|
|
318
|
+
* @param redef optional faster redefinitions of sqrt and other methods
|
|
319
|
+
*/
|
|
320
|
+
function Field(ORDER, bitLen, isLE, redef) {
|
|
321
|
+
if (isLE === void 0) { isLE = false; }
|
|
322
|
+
if (redef === void 0) { redef = {}; }
|
|
323
|
+
if (ORDER <= _0n)
|
|
324
|
+
throw new Error("Expected Field ORDER > 0, got ".concat(ORDER));
|
|
325
|
+
var _a = nLength(ORDER, bitLen), BITS = _a.nBitLength, BYTES = _a.nByteLength;
|
|
326
|
+
if (BYTES > 2048)
|
|
327
|
+
throw new Error('Field lengths over 2048 bytes are not supported');
|
|
328
|
+
var sqrtP = FpSqrt(ORDER);
|
|
329
|
+
var f = Object.freeze({
|
|
330
|
+
ORDER: ORDER,
|
|
331
|
+
BITS: BITS,
|
|
332
|
+
BYTES: BYTES,
|
|
333
|
+
MASK: (0, utils_1.bitMask)(BITS),
|
|
334
|
+
ZERO: _0n,
|
|
335
|
+
ONE: _1n,
|
|
336
|
+
create: function (num) { return mod(num, ORDER); },
|
|
337
|
+
isValid: function (num) {
|
|
338
|
+
if (typeof num !== 'bigint')
|
|
339
|
+
throw new Error("Invalid field element: expected bigint, got ".concat(typeof num));
|
|
340
|
+
return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible
|
|
341
|
+
},
|
|
342
|
+
is0: function (num) { return num === _0n; },
|
|
343
|
+
isOdd: function (num) { return (num & _1n) === _1n; },
|
|
344
|
+
neg: function (num) { return mod(-num, ORDER); },
|
|
345
|
+
eql: function (lhs, rhs) { return lhs === rhs; },
|
|
346
|
+
sqr: function (num) { return mod(num * num, ORDER); },
|
|
347
|
+
add: function (lhs, rhs) { return mod(lhs + rhs, ORDER); },
|
|
348
|
+
sub: function (lhs, rhs) { return mod(lhs - rhs, ORDER); },
|
|
349
|
+
mul: function (lhs, rhs) { return mod(lhs * rhs, ORDER); },
|
|
350
|
+
pow: function (num, power) { return FpPow(f, num, power); },
|
|
351
|
+
div: function (lhs, rhs) { return mod(lhs * invert(rhs, ORDER), ORDER); },
|
|
352
|
+
// Same as above, but doesn't normalize
|
|
353
|
+
sqrN: function (num) { return num * num; },
|
|
354
|
+
addN: function (lhs, rhs) { return lhs + rhs; },
|
|
355
|
+
subN: function (lhs, rhs) { return lhs - rhs; },
|
|
356
|
+
mulN: function (lhs, rhs) { return lhs * rhs; },
|
|
357
|
+
inv: function (num) { return invert(num, ORDER); },
|
|
358
|
+
sqrt: redef.sqrt || (function (n) { return sqrtP(f, n); }),
|
|
359
|
+
invertBatch: function (lst) { return FpInvertBatch(f, lst); },
|
|
360
|
+
// TODO: do we really need constant cmov?
|
|
361
|
+
// We don't have const-time bigints anyway, so probably will be not very useful
|
|
362
|
+
cmov: function (a, b, c) { return (c ? b : a); },
|
|
363
|
+
toBytes: function (num) { return (isLE ? (0, utils_1.numberToBytesLE)(num, BYTES) : (0, utils_1.numberToBytesBE)(num, BYTES)); },
|
|
364
|
+
fromBytes: function (bytes) {
|
|
365
|
+
if (bytes.length !== BYTES)
|
|
366
|
+
throw new Error("Fp.fromBytes: expected ".concat(BYTES, ", got ").concat(bytes.length));
|
|
367
|
+
return isLE ? (0, utils_1.bytesToNumberLE)(bytes) : (0, utils_1.bytesToNumberBE)(bytes);
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
return Object.freeze(f);
|
|
371
|
+
}
|
|
372
|
+
exports.Field = Field;
|
|
373
|
+
function FpSqrtOdd(Fp, elm) {
|
|
374
|
+
if (!Fp.isOdd)
|
|
375
|
+
throw new Error("Field doesn't have isOdd");
|
|
376
|
+
var root = Fp.sqrt(elm);
|
|
377
|
+
return Fp.isOdd(root) ? root : Fp.neg(root);
|
|
378
|
+
}
|
|
379
|
+
exports.FpSqrtOdd = FpSqrtOdd;
|
|
380
|
+
function FpSqrtEven(Fp, elm) {
|
|
381
|
+
if (!Fp.isOdd)
|
|
382
|
+
throw new Error("Field doesn't have isOdd");
|
|
383
|
+
var root = Fp.sqrt(elm);
|
|
384
|
+
return Fp.isOdd(root) ? Fp.neg(root) : root;
|
|
385
|
+
}
|
|
386
|
+
exports.FpSqrtEven = FpSqrtEven;
|
|
387
|
+
/**
|
|
388
|
+
* "Constant-time" private key generation utility.
|
|
389
|
+
* Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).
|
|
390
|
+
* Which makes it slightly more biased, less secure.
|
|
391
|
+
* @deprecated use mapKeyToField instead
|
|
392
|
+
*/
|
|
393
|
+
function hashToPrivateScalar(hash, groupOrder, isLE) {
|
|
394
|
+
if (isLE === void 0) { isLE = false; }
|
|
395
|
+
hash = (0, utils_1.ensureBytes)('privateHash', hash);
|
|
396
|
+
var hashLen = hash.length;
|
|
397
|
+
var minLen = nLength(groupOrder).nByteLength + 8;
|
|
398
|
+
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
399
|
+
throw new Error("hashToPrivateScalar: expected ".concat(minLen, "-1024 bytes of input, got ").concat(hashLen));
|
|
400
|
+
var num = isLE ? (0, utils_1.bytesToNumberLE)(hash) : (0, utils_1.bytesToNumberBE)(hash);
|
|
401
|
+
return mod(num, groupOrder - _1n) + _1n;
|
|
402
|
+
}
|
|
403
|
+
exports.hashToPrivateScalar = hashToPrivateScalar;
|
|
404
|
+
/**
|
|
405
|
+
* Returns total number of bytes consumed by the field element.
|
|
406
|
+
* For example, 32 bytes for usual 256-bit weierstrass curve.
|
|
407
|
+
* @param fieldOrder number of field elements, usually CURVE.n
|
|
408
|
+
* @returns byte length of field
|
|
409
|
+
*/
|
|
410
|
+
function getFieldBytesLength(fieldOrder) {
|
|
411
|
+
if (typeof fieldOrder !== 'bigint')
|
|
412
|
+
throw new Error('field order must be bigint');
|
|
413
|
+
var bitLength = fieldOrder.toString(2).length;
|
|
414
|
+
return Math.ceil(bitLength / 8);
|
|
415
|
+
}
|
|
416
|
+
exports.getFieldBytesLength = getFieldBytesLength;
|
|
417
|
+
/**
|
|
418
|
+
* Returns minimal amount of bytes that can be safely reduced
|
|
419
|
+
* by field order.
|
|
420
|
+
* Should be 2^-128 for 128-bit curve such as P256.
|
|
421
|
+
* @param fieldOrder number of field elements, usually CURVE.n
|
|
422
|
+
* @returns byte length of target hash
|
|
423
|
+
*/
|
|
424
|
+
function getMinHashLength(fieldOrder) {
|
|
425
|
+
var length = getFieldBytesLength(fieldOrder);
|
|
426
|
+
return length + Math.ceil(length / 2);
|
|
427
|
+
}
|
|
428
|
+
exports.getMinHashLength = getMinHashLength;
|
|
429
|
+
/**
|
|
430
|
+
* "Constant-time" private key generation utility.
|
|
431
|
+
* Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF
|
|
432
|
+
* and convert them into private scalar, with the modulo bias being negligible.
|
|
433
|
+
* Needs at least 48 bytes of input for 32-byte private key.
|
|
434
|
+
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
|
435
|
+
* FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
|
|
436
|
+
* RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
|
|
437
|
+
* @param hash hash output from SHA3 or a similar function
|
|
438
|
+
* @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
|
|
439
|
+
* @param isLE interpret hash bytes as LE num
|
|
440
|
+
* @returns valid private scalar
|
|
441
|
+
*/
|
|
442
|
+
function mapHashToField(key, fieldOrder, isLE) {
|
|
443
|
+
if (isLE === void 0) { isLE = false; }
|
|
444
|
+
var len = key.length;
|
|
445
|
+
var fieldLen = getFieldBytesLength(fieldOrder);
|
|
446
|
+
var minLen = getMinHashLength(fieldOrder);
|
|
447
|
+
// No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
|
|
448
|
+
if (len < 16 || len < minLen || len > 1024)
|
|
449
|
+
throw new Error("expected ".concat(minLen, "-1024 bytes of input, got ").concat(len));
|
|
450
|
+
var num = isLE ? (0, utils_1.bytesToNumberBE)(key) : (0, utils_1.bytesToNumberLE)(key);
|
|
451
|
+
// `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
|
|
452
|
+
var reduced = mod(num, fieldOrder - _1n) + _1n;
|
|
453
|
+
return isLE ? (0, utils_1.numberToBytesLE)(reduced, fieldLen) : (0, utils_1.numberToBytesBE)(reduced, fieldLen);
|
|
454
|
+
}
|
|
455
|
+
exports.mapHashToField = mapHashToField;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
type Hex = string | Uint8Array;
|
|
2
|
+
export type CurveType = {
|
|
3
|
+
P: bigint;
|
|
4
|
+
nByteLength: number;
|
|
5
|
+
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
|
|
6
|
+
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
|
|
7
|
+
a: bigint;
|
|
8
|
+
montgomeryBits: number;
|
|
9
|
+
powPminus2?: (x: bigint) => bigint;
|
|
10
|
+
xyToU?: (x: bigint, y: bigint) => bigint;
|
|
11
|
+
Gu: bigint;
|
|
12
|
+
randomBytes?: (bytesLength?: number) => Uint8Array;
|
|
13
|
+
};
|
|
14
|
+
export type CurveFn = {
|
|
15
|
+
scalarMult: (scalar: Hex, u: Hex) => Uint8Array;
|
|
16
|
+
scalarMultBase: (scalar: Hex) => Uint8Array;
|
|
17
|
+
getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array;
|
|
18
|
+
getPublicKey: (privateKey: Hex) => Uint8Array;
|
|
19
|
+
utils: {
|
|
20
|
+
randomPrivateKey: () => Uint8Array;
|
|
21
|
+
};
|
|
22
|
+
GuBytes: Uint8Array;
|
|
23
|
+
};
|
|
24
|
+
export type InternalCurveFn = CurveFn & {
|
|
25
|
+
encodeUCoordinate: (u: bigint) => Uint8Array;
|
|
26
|
+
};
|
|
27
|
+
export declare function montgomery(curveDef: CurveType): InternalCurveFn;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.montgomery = void 0;
|
|
15
|
+
/**
|
|
16
|
+
* Montgomery curve methods. It's not really whole montgomery curve,
|
|
17
|
+
* just bunch of very specific methods for X25519 / X448 from
|
|
18
|
+
* [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748)
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
22
|
+
var modular_js_1 = require("./modular.js");
|
|
23
|
+
var utils_1 = require("./utils.js");
|
|
24
|
+
var _0n = BigInt(0);
|
|
25
|
+
var _1n = BigInt(1);
|
|
26
|
+
function validateOpts(curve) {
|
|
27
|
+
(0, utils_1.validateObject)(curve, {
|
|
28
|
+
a: 'bigint',
|
|
29
|
+
}, {
|
|
30
|
+
montgomeryBits: 'isSafeInteger',
|
|
31
|
+
nByteLength: 'isSafeInteger',
|
|
32
|
+
adjustScalarBytes: 'function',
|
|
33
|
+
domain: 'function',
|
|
34
|
+
powPminus2: 'function',
|
|
35
|
+
Gu: 'bigint',
|
|
36
|
+
});
|
|
37
|
+
// Set defaults
|
|
38
|
+
return Object.freeze(__assign({}, curve));
|
|
39
|
+
}
|
|
40
|
+
// Uses only one coordinate instead of two
|
|
41
|
+
function montgomery(curveDef) {
|
|
42
|
+
var CURVE = validateOpts(curveDef);
|
|
43
|
+
var P = CURVE.P;
|
|
44
|
+
var modP = function (n) { return (0, modular_js_1.mod)(n, P); };
|
|
45
|
+
var montgomeryBits = CURVE.montgomeryBits;
|
|
46
|
+
var montgomeryBytes = Math.ceil(montgomeryBits / 8);
|
|
47
|
+
var fieldLen = CURVE.nByteLength;
|
|
48
|
+
var adjustScalarBytes = CURVE.adjustScalarBytes || (function (bytes) { return bytes; });
|
|
49
|
+
var powPminus2 = CURVE.powPminus2 || (function (x) { return (0, modular_js_1.pow)(x, P - BigInt(2), P); });
|
|
50
|
+
// cswap from RFC7748. But it is not from RFC7748!
|
|
51
|
+
/*
|
|
52
|
+
cswap(swap, x_2, x_3):
|
|
53
|
+
dummy = mask(swap) AND (x_2 XOR x_3)
|
|
54
|
+
x_2 = x_2 XOR dummy
|
|
55
|
+
x_3 = x_3 XOR dummy
|
|
56
|
+
Return (x_2, x_3)
|
|
57
|
+
Where mask(swap) is the all-1 or all-0 word of the same length as x_2
|
|
58
|
+
and x_3, computed, e.g., as mask(swap) = 0 - swap.
|
|
59
|
+
*/
|
|
60
|
+
function cswap(swap, x_2, x_3) {
|
|
61
|
+
var dummy = modP(swap * (x_2 - x_3));
|
|
62
|
+
x_2 = modP(x_2 - dummy);
|
|
63
|
+
x_3 = modP(x_3 + dummy);
|
|
64
|
+
return [x_2, x_3];
|
|
65
|
+
}
|
|
66
|
+
// x25519 from 4
|
|
67
|
+
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519
|
|
68
|
+
var a24 = (CURVE.a - BigInt(2)) / BigInt(4);
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* @param pointU u coordinate (x) on Montgomery Curve 25519
|
|
72
|
+
* @param scalar by which the point would be multiplied
|
|
73
|
+
* @returns new Point on Montgomery curve
|
|
74
|
+
*/
|
|
75
|
+
function montgomeryLadder(u, scalar) {
|
|
76
|
+
(0, utils_1.aInRange)('u', u, _0n, P);
|
|
77
|
+
(0, utils_1.aInRange)('scalar', scalar, _0n, P);
|
|
78
|
+
// Section 5: Implementations MUST accept non-canonical values and process them as
|
|
79
|
+
// if they had been reduced modulo the field prime.
|
|
80
|
+
var k = scalar;
|
|
81
|
+
var x_1 = u;
|
|
82
|
+
var x_2 = _1n;
|
|
83
|
+
var z_2 = _0n;
|
|
84
|
+
var x_3 = u;
|
|
85
|
+
var z_3 = _1n;
|
|
86
|
+
var swap = _0n;
|
|
87
|
+
var sw;
|
|
88
|
+
for (var t = BigInt(montgomeryBits - 1); t >= _0n; t--) {
|
|
89
|
+
var k_t = (k >> t) & _1n;
|
|
90
|
+
swap ^= k_t;
|
|
91
|
+
sw = cswap(swap, x_2, x_3);
|
|
92
|
+
x_2 = sw[0];
|
|
93
|
+
x_3 = sw[1];
|
|
94
|
+
sw = cswap(swap, z_2, z_3);
|
|
95
|
+
z_2 = sw[0];
|
|
96
|
+
z_3 = sw[1];
|
|
97
|
+
swap = k_t;
|
|
98
|
+
var A = x_2 + z_2;
|
|
99
|
+
var AA = modP(A * A);
|
|
100
|
+
var B = x_2 - z_2;
|
|
101
|
+
var BB = modP(B * B);
|
|
102
|
+
var E = AA - BB;
|
|
103
|
+
var C = x_3 + z_3;
|
|
104
|
+
var D = x_3 - z_3;
|
|
105
|
+
var DA = modP(D * A);
|
|
106
|
+
var CB = modP(C * B);
|
|
107
|
+
var dacb = DA + CB;
|
|
108
|
+
var da_cb = DA - CB;
|
|
109
|
+
x_3 = modP(dacb * dacb);
|
|
110
|
+
z_3 = modP(x_1 * modP(da_cb * da_cb));
|
|
111
|
+
x_2 = modP(AA * BB);
|
|
112
|
+
z_2 = modP(E * (AA + modP(a24 * E)));
|
|
113
|
+
}
|
|
114
|
+
// (x_2, x_3) = cswap(swap, x_2, x_3)
|
|
115
|
+
sw = cswap(swap, x_2, x_3);
|
|
116
|
+
x_2 = sw[0];
|
|
117
|
+
x_3 = sw[1];
|
|
118
|
+
// (z_2, z_3) = cswap(swap, z_2, z_3)
|
|
119
|
+
sw = cswap(swap, z_2, z_3);
|
|
120
|
+
z_2 = sw[0];
|
|
121
|
+
z_3 = sw[1];
|
|
122
|
+
// z_2^(p - 2)
|
|
123
|
+
var z2 = powPminus2(z_2);
|
|
124
|
+
// Return x_2 * (z_2^(p - 2))
|
|
125
|
+
return modP(x_2 * z2);
|
|
126
|
+
}
|
|
127
|
+
function encodeUCoordinate(u) {
|
|
128
|
+
return (0, utils_1.numberToBytesLE)(modP(u), montgomeryBytes);
|
|
129
|
+
}
|
|
130
|
+
function decodeUCoordinate(uEnc) {
|
|
131
|
+
// Section 5: When receiving such an array, implementations of X25519
|
|
132
|
+
// MUST mask the most significant bit in the final byte.
|
|
133
|
+
var u = (0, utils_1.ensureBytes)('u coordinate', uEnc, montgomeryBytes);
|
|
134
|
+
if (fieldLen === 32)
|
|
135
|
+
u[31] &= 127; // 0b0111_1111
|
|
136
|
+
return (0, utils_1.bytesToNumberLE)(u);
|
|
137
|
+
}
|
|
138
|
+
function decodeScalar(n) {
|
|
139
|
+
var bytes = (0, utils_1.ensureBytes)('scalar', n);
|
|
140
|
+
var len = bytes.length;
|
|
141
|
+
if (len !== montgomeryBytes && len !== fieldLen) {
|
|
142
|
+
var valid = '' + montgomeryBytes + ' or ' + fieldLen;
|
|
143
|
+
throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len);
|
|
144
|
+
}
|
|
145
|
+
return (0, utils_1.bytesToNumberLE)(adjustScalarBytes(bytes));
|
|
146
|
+
}
|
|
147
|
+
function scalarMult(scalar, u) {
|
|
148
|
+
var pointU = decodeUCoordinate(u);
|
|
149
|
+
var _scalar = decodeScalar(scalar);
|
|
150
|
+
var pu = montgomeryLadder(pointU, _scalar);
|
|
151
|
+
// The result was not contributory
|
|
152
|
+
// https://cr.yp.to/ecdh.html#validate
|
|
153
|
+
if (pu === _0n)
|
|
154
|
+
throw new Error('invalid private or public key received');
|
|
155
|
+
return encodeUCoordinate(pu);
|
|
156
|
+
}
|
|
157
|
+
// Computes public key from private. By doing scalar multiplication of base point.
|
|
158
|
+
var GuBytes = encodeUCoordinate(CURVE.Gu);
|
|
159
|
+
function scalarMultBase(scalar) {
|
|
160
|
+
return scalarMult(scalar, GuBytes);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
scalarMult: scalarMult,
|
|
164
|
+
scalarMultBase: scalarMultBase,
|
|
165
|
+
getSharedSecret: function (privateKey, publicKey) { return scalarMult(privateKey, publicKey); },
|
|
166
|
+
getPublicKey: function (privateKey) { return scalarMultBase(privateKey); },
|
|
167
|
+
utils: { randomPrivateKey: function () { return CURVE.randomBytes(CURVE.nByteLength); } },
|
|
168
|
+
GuBytes: GuBytes,
|
|
169
|
+
encodeUCoordinate: encodeUCoordinate
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
exports.montgomery = montgomery;
|