js-ecutils
Version:
JavaScript Library for Elliptic Curve Cryptography: key exchanges (Diffie-Hellman, Massey-Omura), ECDSA signatures, and Koblitz encoding. Suitable for crypto education and secure systems.
221 lines (210 loc) • 30.7 kB
JavaScript
"use strict";
var _globals = require("@jest/globals");
var _point = require("./core/point");
var _curve = require("./core/curve");
var _math = require("./utils/math");
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
// ---------------------------------------------------------------------------
// Educational examples on small curves
//
// These tests use "toy" curves with small primes to illustrate elliptic
// curve concepts with values that can be verified by hand.
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// E: y² = x³ + x + 1 over F₂₃ (n = 28, cofactor h = 1)
//
// Points used:
// P = (0, 1) — satisfies 1² ≡ 0³ + 0 + 1 ≡ 1 (mod 23) ✓
// Q = (6, 19) — satisfies 19² = 361 ≡ 16 ≡ 6³ + 6 + 1 = 223 ≡ 16 (mod 23) ✓
//
// Hand-calculated results:
// P + Q: λ = (19-1)·(6-0)⁻¹ = 18·4 = 72 ≡ 3 (mod 23)
// x₃ = 3² - 0 - 6 = 3 (mod 23)
// y₃ = 3·(0-3) - 1 = -10 ≡ 13 (mod 23)
// → (3, 13)
//
// 2·P: λ = (3·0²+1)·(2·1)⁻¹ = 1·12 = 12 (mod 23)
// x₃ = 12² - 0 = 144 ≡ 6 (mod 23)
// y₃ = 12·(0-6) - 1 = -73 ≡ 19 (mod 23)
// → (6, 19)
//
// -P: (0, -1 mod 23) = (0, 22)
// ---------------------------------------------------------------------------
(0, _globals.describe)('Educational: E/F₂₃ y² = x³ + x + 1', function () {
var curve = new _curve.CurveParams({
p: 23n,
a: 1n,
b: 1n,
n: 28n,
h: 1n,
coord: _curve.CoordinateSystem.AFFINE
});
var P = new _point.Point(0n, 1n, curve);
var Q = new _point.Point(6n, 19n, curve);
(0, _globals.test)('P(0,1) + Q(6,19) = (3, 13)', function () {
var R = P.add(Q);
(0, _globals.expect)(R.x).toBe(3n);
(0, _globals.expect)(R.y).toBe(13n);
});
(0, _globals.test)('2·P(0,1) = (6, 19)', function () {
var R = P.mul(2n);
(0, _globals.expect)(R.x).toBe(6n);
(0, _globals.expect)(R.y).toBe(19n);
});
(0, _globals.test)('3·P = 2·P + P (scalar multiplication consistency)', function () {
var R2 = P.mul(2n);
var R3manual = R2.add(P);
var R3 = P.mul(3n);
(0, _globals.expect)(R3.x).toBe(R3manual.x);
(0, _globals.expect)(R3.y).toBe(R3manual.y);
});
(0, _globals.test)('28·P = O (n·P is the identity)', function () {
(0, _globals.expect)(P.mul(28n).isIdentity).toBe(true);
});
(0, _globals.test)('P + (-P) = O (additive inverse)', function () {
(0, _globals.expect)(P.add(P.neg()).isIdentity).toBe(true);
});
(0, _globals.test)('-P(0,1) = (0, 22)', function () {
var neg = P.neg();
(0, _globals.expect)(neg.x).toBe(0n);
(0, _globals.expect)(neg.y).toBe(22n);
});
});
// ---------------------------------------------------------------------------
// E: y² = x³ + 2 over F₇ (n = 9, cofactor h = 1)
//
// Known points:
// (0, 3): 3² = 9 ≡ 2 ≡ 0³ + 2 (mod 7) ✓
// (0, 4): 4² = 16 ≡ 2 ≡ 0³ + 2 (mod 7) ✓
// (3, 1): 1² = 1 ≡ 3³ + 2 = 29 ≡ 1 (mod 7) ✓
// ---------------------------------------------------------------------------
(0, _globals.describe)('Educational: E/F₇ y² = x³ + 2', function () {
var curve = new _curve.CurveParams({
p: 7n,
a: 0n,
b: 2n,
n: 9n,
h: 1n,
coord: _curve.CoordinateSystem.AFFINE
});
(0, _globals.test)('(0,3) and (0,4) lie on the curve', function () {
(0, _globals.expect)(new _point.Point(0n, 3n, curve).isOnCurve()).toBe(true);
(0, _globals.expect)(new _point.Point(0n, 4n, curve).isOnCurve()).toBe(true);
});
(0, _globals.test)('point addition produces a valid curve point', function () {
var P = new _point.Point(0n, 3n, curve);
var Q = new _point.Point(3n, 1n, curve);
var R = P.add(Q);
(0, _globals.expect)(R.isOnCurve() || R.isIdentity).toBe(true);
});
});
// ---------------------------------------------------------------------------
// Quadratic residues and point compression (educational)
//
// Point compression stores (x, parity_of_y) instead of (x, y).
// Decompression recovers y by computing √(x³ + ax + b) mod p and
// selecting the root matching the parity bit.
// ---------------------------------------------------------------------------
(0, _globals.describe)('Educational: quadratic residues and point compression', function () {
// QR(F₂₃) = {1, 2, 3, 4, 6, 8, 9, 12, 13, 16, 18}
(0, _globals.test)('QR set of F₂₃ matches expected values', function () {
var expectedQR = new Set([1n, 2n, 3n, 4n, 6n, 8n, 9n, 12n, 13n, 16n, 18n]);
for (var a = 1n; a < 23n; a++) {
(0, _globals.expect)((0, _math.isQuadraticResidue)(a, 23n)).toBe(expectedQR.has(a));
}
});
// √4 mod 23: r² ≡ 4 (mod 23) → r ∈ {2, 21}
(0, _globals.test)('√4 mod 23 equals 2 or 21', function () {
var r = (0, _math.modularSqrt)(4n, 23n);
(0, _globals.expect)([2n, 21n]).toContain(r);
(0, _globals.expect)(r * r % 23n).toBe(4n);
});
// compress → (x, parity), decompress → Point(x, y)
(0, _globals.test)('compress/decompress roundtrip on Z₂₃ curve', function () {
var curve = new _curve.CurveParams({
p: 23n,
a: 1n,
b: 1n,
n: 28n,
h: 1n
});
var P = new _point.Point(0n, 1n, curve);
var _P$compress = P.compress(),
_P$compress2 = _slicedToArray(_P$compress, 2),
x = _P$compress2[0],
parity = _P$compress2[1];
var recovered = _point.Point.decompress(x, parity, curve);
(0, _globals.expect)(recovered.x).toBe(P.x);
(0, _globals.expect)(recovered.y).toBe(P.y);
});
});
// ---------------------------------------------------------------------------
// Jacobian vs Affine arithmetic (educational)
//
// Jacobian coordinates (X, Y, Z) avoid modular inversions during
// intermediate operations, converting back only at the end:
// x = X / Z², y = Y / Z³
//
// Both coordinate systems must produce identical affine results.
// ---------------------------------------------------------------------------
(0, _globals.describe)('Educational: Jacobian vs Affine arithmetic', function () {
(0, _globals.test)('addition gives the same result in both coordinate systems', function () {
var affineCurve = new _curve.CurveParams({
p: 23n,
a: 1n,
b: 1n,
n: 28n,
h: 1n,
coord: _curve.CoordinateSystem.AFFINE
});
var jacobianCurve = new _curve.CurveParams({
p: 23n,
a: 1n,
b: 1n,
n: 28n,
h: 1n,
coord: _curve.CoordinateSystem.JACOBIAN
});
var Pa = new _point.Point(0n, 1n, affineCurve);
var Qa = new _point.Point(6n, 19n, affineCurve);
var Ra = Pa.add(Qa);
var Pj = new _point.Point(0n, 1n, jacobianCurve);
var Qj = new _point.Point(6n, 19n, jacobianCurve);
var Rj = Pj.add(Qj);
(0, _globals.expect)(Ra.x).toBe(Rj.x);
(0, _globals.expect)(Ra.y).toBe(Rj.y);
});
(0, _globals.test)('scalar multiplication gives the same result for k ∈ {2, 5, 13, 27}', function () {
var affineCurve = new _curve.CurveParams({
p: 23n,
a: 1n,
b: 1n,
n: 28n,
h: 1n,
coord: _curve.CoordinateSystem.AFFINE
});
var jacobianCurve = new _curve.CurveParams({
p: 23n,
a: 1n,
b: 1n,
n: 28n,
h: 1n,
coord: _curve.CoordinateSystem.JACOBIAN
});
var Pa = new _point.Point(0n, 1n, affineCurve);
var Pj = new _point.Point(0n, 1n, jacobianCurve);
for (var _i = 0, _arr = [2n, 5n, 13n, 27n]; _i < _arr.length; _i++) {
var k = _arr[_i];
var Ra = Pa.mul(k);
var Rj = Pj.mul(k);
(0, _globals.expect)(Ra.x).toBe(Rj.x);
(0, _globals.expect)(Ra.y).toBe(Rj.y);
}
});
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZ2xvYmFscyIsInJlcXVpcmUiLCJfcG9pbnQiLCJfY3VydmUiLCJfbWF0aCIsIl9zbGljZWRUb0FycmF5IiwiciIsImUiLCJfYXJyYXlXaXRoSG9sZXMiLCJfaXRlcmFibGVUb0FycmF5TGltaXQiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJfbm9uSXRlcmFibGVSZXN0IiwiVHlwZUVycm9yIiwiYSIsIl9hcnJheUxpa2VUb0FycmF5IiwidCIsInRvU3RyaW5nIiwiY2FsbCIsInNsaWNlIiwiY29uc3RydWN0b3IiLCJuYW1lIiwiQXJyYXkiLCJmcm9tIiwidGVzdCIsImxlbmd0aCIsIm4iLCJsIiwiU3ltYm9sIiwiaXRlcmF0b3IiLCJpIiwidSIsImYiLCJvIiwibmV4dCIsIk9iamVjdCIsImRvbmUiLCJwdXNoIiwidmFsdWUiLCJpc0FycmF5IiwiZGVzY3JpYmUiLCJjdXJ2ZSIsIkN1cnZlUGFyYW1zIiwicCIsImIiLCJoIiwiY29vcmQiLCJDb29yZGluYXRlU3lzdGVtIiwiQUZGSU5FIiwiUCIsIlBvaW50IiwiUSIsIlIiLCJhZGQiLCJleHBlY3QiLCJ4IiwidG9CZSIsInkiLCJtdWwiLCJSMiIsIlIzbWFudWFsIiwiUjMiLCJpc0lkZW50aXR5IiwibmVnIiwiaXNPbkN1cnZlIiwiZXhwZWN0ZWRRUiIsIlNldCIsImlzUXVhZHJhdGljUmVzaWR1ZSIsImhhcyIsIm1vZHVsYXJTcXJ0IiwidG9Db250YWluIiwiX1AkY29tcHJlc3MiLCJjb21wcmVzcyIsIl9QJGNvbXByZXNzMiIsInBhcml0eSIsInJlY292ZXJlZCIsImRlY29tcHJlc3MiLCJhZmZpbmVDdXJ2ZSIsImphY29iaWFuQ3VydmUiLCJKQUNPQklBTiIsIlBhIiwiUWEiLCJSYSIsIlBqIiwiUWoiLCJSaiIsIl9pIiwiX2FyciIsImsiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvZWR1Y2F0aW9uYWwudGVzdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0ZXN0LCBleHBlY3QsIGRlc2NyaWJlIH0gZnJvbSAnQGplc3QvZ2xvYmFscydcbmltcG9ydCB7IFBvaW50IH0gZnJvbSAnLi9jb3JlL3BvaW50J1xuaW1wb3J0IHsgQ3VydmVQYXJhbXMsIENvb3JkaW5hdGVTeXN0ZW0gfSBmcm9tICcuL2NvcmUvY3VydmUnXG5pbXBvcnQgeyBpc1F1YWRyYXRpY1Jlc2lkdWUsIG1vZHVsYXJTcXJ0IH0gZnJvbSAnLi91dGlscy9tYXRoJ1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIEVkdWNhdGlvbmFsIGV4YW1wbGVzIG9uIHNtYWxsIGN1cnZlc1xuLy9cbi8vIFRoZXNlIHRlc3RzIHVzZSBcInRveVwiIGN1cnZlcyB3aXRoIHNtYWxsIHByaW1lcyB0byBpbGx1c3RyYXRlIGVsbGlwdGljXG4vLyBjdXJ2ZSBjb25jZXB0cyB3aXRoIHZhbHVlcyB0aGF0IGNhbiBiZSB2ZXJpZmllZCBieSBoYW5kLlxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gRTogecKyID0geMKzICsgeCArIDEgIG92ZXIgRuKCguKCgyAgIChuID0gMjgsIGNvZmFjdG9yIGggPSAxKVxuLy9cbi8vIFBvaW50cyB1c2VkOlxuLy8gICBQID0gKDAsIDEpICAgIOKAlCBzYXRpc2ZpZXMgMcKyIOKJoSAwwrMgKyAwICsgMSDiiaEgMSAobW9kIDIzKSDinJNcbi8vICAgUSA9ICg2LCAxOSkgICDigJQgc2F0aXNmaWVzIDE5wrIgPSAzNjEg4omhIDE2IOKJoSA2wrMgKyA2ICsgMSA9IDIyMyDiiaEgMTYgKG1vZCAyMykg4pyTXG4vL1xuLy8gSGFuZC1jYWxjdWxhdGVkIHJlc3VsdHM6XG4vLyAgIFAgKyBROiAgzrsgPSAoMTktMSnCtyg2LTAp4oG7wrkgPSAxOMK3NCA9IDcyIOKJoSAzIChtb2QgMjMpXG4vLyAgICAgICAgICAgeOKCgyA9IDPCsiAtIDAgLSA2ID0gMyAobW9kIDIzKVxuLy8gICAgICAgICAgIHnigoMgPSAzwrcoMC0zKSAtIDEgPSAtMTAg4omhIDEzIChtb2QgMjMpXG4vLyAgICAgICAgICAg4oaSICgzLCAxMylcbi8vXG4vLyAgIDLCt1A6ICAgIM67ID0gKDPCtzDCsisxKcK3KDLCtzEp4oG7wrkgPSAxwrcxMiA9IDEyIChtb2QgMjMpXG4vLyAgICAgICAgICAgeOKCgyA9IDEywrIgLSAwID0gMTQ0IOKJoSA2IChtb2QgMjMpXG4vLyAgICAgICAgICAgeeKCgyA9IDEywrcoMC02KSAtIDEgPSAtNzMg4omhIDE5IChtb2QgMjMpXG4vLyAgICAgICAgICAg4oaSICg2LCAxOSlcbi8vXG4vLyAgIC1QOiAgICAgKDAsIC0xIG1vZCAyMykgPSAoMCwgMjIpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZGVzY3JpYmUoJ0VkdWNhdGlvbmFsOiBFL0bigoLigoMgIHnCsiA9IHjCsyArIHggKyAxJywgKCkgPT4ge1xuICBjb25zdCBjdXJ2ZSA9IG5ldyBDdXJ2ZVBhcmFtcyh7XG4gICAgcDogMjNuLFxuICAgIGE6IDFuLFxuICAgIGI6IDFuLFxuICAgIG46IDI4bixcbiAgICBoOiAxbixcbiAgICBjb29yZDogQ29vcmRpbmF0ZVN5c3RlbS5BRkZJTkUsXG4gIH0pXG4gIGNvbnN0IFAgPSBuZXcgUG9pbnQoMG4sIDFuLCBjdXJ2ZSlcbiAgY29uc3QgUSA9IG5ldyBQb2ludCg2biwgMTluLCBjdXJ2ZSlcblxuICB0ZXN0KCdQKDAsMSkgKyBRKDYsMTkpID0gKDMsIDEzKScsICgpID0+IHtcbiAgICBjb25zdCBSID0gUC5hZGQoUSlcbiAgICBleHBlY3QoUi54KS50b0JlKDNuKVxuICAgIGV4cGVjdChSLnkpLnRvQmUoMTNuKVxuICB9KVxuXG4gIHRlc3QoJzLCt1AoMCwxKSA9ICg2LCAxOSknLCAoKSA9PiB7XG4gICAgY29uc3QgUiA9IFAubXVsKDJuKVxuICAgIGV4cGVjdChSLngpLnRvQmUoNm4pXG4gICAgZXhwZWN0KFIueSkudG9CZSgxOW4pXG4gIH0pXG5cbiAgdGVzdCgnM8K3UCA9IDLCt1AgKyBQICAoc2NhbGFyIG11bHRpcGxpY2F0aW9uIGNvbnNpc3RlbmN5KScsICgpID0+IHtcbiAgICBjb25zdCBSMiA9IFAubXVsKDJuKVxuICAgIGNvbnN0IFIzbWFudWFsID0gUjIuYWRkKFApXG4gICAgY29uc3QgUjMgPSBQLm11bCgzbilcbiAgICBleHBlY3QoUjMueCkudG9CZShSM21hbnVhbC54KVxuICAgIGV4cGVjdChSMy55KS50b0JlKFIzbWFudWFsLnkpXG4gIH0pXG5cbiAgdGVzdCgnMjjCt1AgPSBPICAobsK3UCBpcyB0aGUgaWRlbnRpdHkpJywgKCkgPT4ge1xuICAgIGV4cGVjdChQLm11bCgyOG4pLmlzSWRlbnRpdHkpLnRvQmUodHJ1ZSlcbiAgfSlcblxuICB0ZXN0KCdQICsgKC1QKSA9IE8gIChhZGRpdGl2ZSBpbnZlcnNlKScsICgpID0+IHtcbiAgICBleHBlY3QoUC5hZGQoUC5uZWcoKSkuaXNJZGVudGl0eSkudG9CZSh0cnVlKVxuICB9KVxuXG4gIHRlc3QoJy1QKDAsMSkgPSAoMCwgMjIpJywgKCkgPT4ge1xuICAgIGNvbnN0IG5lZyA9IFAubmVnKClcbiAgICBleHBlY3QobmVnLngpLnRvQmUoMG4pXG4gICAgZXhwZWN0KG5lZy55KS50b0JlKDIybilcbiAgfSlcbn0pXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gRTogecKyID0geMKzICsgMiAgb3ZlciBG4oKHICAgKG4gPSA5LCBjb2ZhY3RvciBoID0gMSlcbi8vXG4vLyBLbm93biBwb2ludHM6XG4vLyAgICgwLCAzKTogM8KyID0gOSDiiaEgMiDiiaEgMMKzICsgMiAobW9kIDcpICDinJNcbi8vICAgKDAsIDQpOiA0wrIgPSAxNiDiiaEgMiDiiaEgMMKzICsgMiAobW9kIDcpICDinJNcbi8vICAgKDMsIDEpOiAxwrIgPSAxIOKJoSAzwrMgKyAyID0gMjkg4omhIDEgKG1vZCA3KSAg4pyTXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZGVzY3JpYmUoJ0VkdWNhdGlvbmFsOiBFL0bigocgIHnCsiA9IHjCsyArIDInLCAoKSA9PiB7XG4gIGNvbnN0IGN1cnZlID0gbmV3IEN1cnZlUGFyYW1zKHtcbiAgICBwOiA3bixcbiAgICBhOiAwbixcbiAgICBiOiAybixcbiAgICBuOiA5bixcbiAgICBoOiAxbixcbiAgICBjb29yZDogQ29vcmRpbmF0ZVN5c3RlbS5BRkZJTkUsXG4gIH0pXG5cbiAgdGVzdCgnKDAsMykgYW5kICgwLDQpIGxpZSBvbiB0aGUgY3VydmUnLCAoKSA9PiB7XG4gICAgZXhwZWN0KG5ldyBQb2ludCgwbiwgM24sIGN1cnZlKS5pc09uQ3VydmUoKSkudG9CZSh0cnVlKVxuICAgIGV4cGVjdChuZXcgUG9pbnQoMG4sIDRuLCBjdXJ2ZSkuaXNPbkN1cnZlKCkpLnRvQmUodHJ1ZSlcbiAgfSlcblxuICB0ZXN0KCdwb2ludCBhZGRpdGlvbiBwcm9kdWNlcyBhIHZhbGlkIGN1cnZlIHBvaW50JywgKCkgPT4ge1xuICAgIGNvbnN0IFAgPSBuZXcgUG9pbnQoMG4sIDNuLCBjdXJ2ZSlcbiAgICBjb25zdCBRID0gbmV3IFBvaW50KDNuLCAxbiwgY3VydmUpXG4gICAgY29uc3QgUiA9IFAuYWRkKFEpXG4gICAgZXhwZWN0KFIuaXNPbkN1cnZlKCkgfHwgUi5pc0lkZW50aXR5KS50b0JlKHRydWUpXG4gIH0pXG59KVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFF1YWRyYXRpYyByZXNpZHVlcyBhbmQgcG9pbnQgY29tcHJlc3Npb24gKGVkdWNhdGlvbmFsKVxuLy9cbi8vIFBvaW50IGNvbXByZXNzaW9uIHN0b3JlcyAoeCwgcGFyaXR5X29mX3kpIGluc3RlYWQgb2YgKHgsIHkpLlxuLy8gRGVjb21wcmVzc2lvbiByZWNvdmVycyB5IGJ5IGNvbXB1dGluZyDiiJooeMKzICsgYXggKyBiKSBtb2QgcCBhbmRcbi8vIHNlbGVjdGluZyB0aGUgcm9vdCBtYXRjaGluZyB0aGUgcGFyaXR5IGJpdC5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5kZXNjcmliZSgnRWR1Y2F0aW9uYWw6IHF1YWRyYXRpYyByZXNpZHVlcyBhbmQgcG9pbnQgY29tcHJlc3Npb24nLCAoKSA9PiB7XG4gIC8vIFFSKEbigoLigoMpID0gezEsIDIsIDMsIDQsIDYsIDgsIDksIDEyLCAxMywgMTYsIDE4fVxuICB0ZXN0KCdRUiBzZXQgb2YgRuKCguKCgyBtYXRjaGVzIGV4cGVjdGVkIHZhbHVlcycsICgpID0+IHtcbiAgICBjb25zdCBleHBlY3RlZFFSID0gbmV3IFNldChbMW4sIDJuLCAzbiwgNG4sIDZuLCA4biwgOW4sIDEybiwgMTNuLCAxNm4sIDE4bl0pXG4gICAgZm9yIChsZXQgYSA9IDFuOyBhIDwgMjNuOyBhKyspIHtcbiAgICAgIGV4cGVjdChpc1F1YWRyYXRpY1Jlc2lkdWUoYSwgMjNuKSkudG9CZShleHBlY3RlZFFSLmhhcyhhKSlcbiAgICB9XG4gIH0pXG5cbiAgLy8g4oiaNCBtb2QgMjM6ICBywrIg4omhIDQgKG1vZCAyMykgIOKGkiAgciDiiIggezIsIDIxfVxuICB0ZXN0KCfiiJo0IG1vZCAyMyBlcXVhbHMgMiBvciAyMScsICgpID0+IHtcbiAgICBjb25zdCByID0gbW9kdWxhclNxcnQoNG4sIDIzbilcbiAgICBleHBlY3QoWzJuLCAyMW5dKS50b0NvbnRhaW4ocilcbiAgICBleHBlY3QoKHIgKiByKSAlIDIzbikudG9CZSg0bilcbiAgfSlcblxuICAvLyBjb21wcmVzcyDihpIgKHgsIHBhcml0eSksICBkZWNvbXByZXNzIOKGkiBQb2ludCh4LCB5KVxuICB0ZXN0KCdjb21wcmVzcy9kZWNvbXByZXNzIHJvdW5kdHJpcCBvbiBa4oKC4oKDIGN1cnZlJywgKCkgPT4ge1xuICAgIGNvbnN0IGN1cnZlID0gbmV3IEN1cnZlUGFyYW1zKHtcbiAgICAgIHA6IDIzbixcbiAgICAgIGE6IDFuLFxuICAgICAgYjogMW4sXG4gICAgICBuOiAyOG4sXG4gICAgICBoOiAxbixcbiAgICB9KVxuICAgIGNvbnN0IFAgPSBuZXcgUG9pbnQoMG4sIDFuLCBjdXJ2ZSlcbiAgICBjb25zdCBbeCwgcGFyaXR5XSA9IFAuY29tcHJlc3MoKVxuICAgIGNvbnN0IHJlY292ZXJlZCA9IFBvaW50LmRlY29tcHJlc3MoeCwgcGFyaXR5LCBjdXJ2ZSlcbiAgICBleHBlY3QocmVjb3ZlcmVkLngpLnRvQmUoUC54KVxuICAgIGV4cGVjdChyZWNvdmVyZWQueSkudG9CZShQLnkpXG4gIH0pXG59KVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIEphY29iaWFuIHZzIEFmZmluZSBhcml0aG1ldGljIChlZHVjYXRpb25hbClcbi8vXG4vLyBKYWNvYmlhbiBjb29yZGluYXRlcyAoWCwgWSwgWikgYXZvaWQgbW9kdWxhciBpbnZlcnNpb25zIGR1cmluZ1xuLy8gaW50ZXJtZWRpYXRlIG9wZXJhdGlvbnMsIGNvbnZlcnRpbmcgYmFjayBvbmx5IGF0IHRoZSBlbmQ6XG4vLyAgIHggPSBYIC8gWsKyLCAgIHkgPSBZIC8gWsKzXG4vL1xuLy8gQm90aCBjb29yZGluYXRlIHN5c3RlbXMgbXVzdCBwcm9kdWNlIGlkZW50aWNhbCBhZmZpbmUgcmVzdWx0cy5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5kZXNjcmliZSgnRWR1Y2F0aW9uYWw6IEphY29iaWFuIHZzIEFmZmluZSBhcml0aG1ldGljJywgKCkgPT4ge1xuICB0ZXN0KCdhZGRpdGlvbiBnaXZlcyB0aGUgc2FtZSByZXN1bHQgaW4gYm90aCBjb29yZGluYXRlIHN5c3RlbXMnLCAoKSA9PiB7XG4gICAgY29uc3QgYWZmaW5lQ3VydmUgPSBuZXcgQ3VydmVQYXJhbXMoe1xuICAgICAgcDogMjNuLFxuICAgICAgYTogMW4sXG4gICAgICBiOiAxbixcbiAgICAgIG46IDI4bixcbiAgICAgIGg6IDFuLFxuICAgICAgY29vcmQ6IENvb3JkaW5hdGVTeXN0ZW0uQUZGSU5FLFxuICAgIH0pXG4gICAgY29uc3QgamFjb2JpYW5DdXJ2ZSA9IG5ldyBDdXJ2ZVBhcmFtcyh7XG4gICAgICBwOiAyM24sXG4gICAgICBhOiAxbixcbiAgICAgIGI6IDFuLFxuICAgICAgbjogMjhuLFxuICAgICAgaDogMW4sXG4gICAgICBjb29yZDogQ29vcmRpbmF0ZVN5c3RlbS5KQUNPQklBTixcbiAgICB9KVxuICAgIGNvbnN0IFBhID0gbmV3IFBvaW50KDBuLCAxbiwgYWZmaW5lQ3VydmUpXG4gICAgY29uc3QgUWEgPSBuZXcgUG9pbnQoNm4sIDE5biwgYWZmaW5lQ3VydmUpXG4gICAgY29uc3QgUmEgPSBQYS5hZGQoUWEpXG5cbiAgICBjb25zdCBQaiA9IG5ldyBQb2ludCgwbiwgMW4sIGphY29iaWFuQ3VydmUpXG4gICAgY29uc3QgUWogPSBuZXcgUG9pbnQoNm4sIDE5biwgamFjb2JpYW5DdXJ2ZSlcbiAgICBjb25zdCBSaiA9IFBqLmFkZChRailcblxuICAgIGV4cGVjdChSYS54KS50b0JlKFJqLngpXG4gICAgZXhwZWN0KFJhLnkpLnRvQmUoUmoueSlcbiAgfSlcblxuICB0ZXN0KCdzY2FsYXIgbXVsdGlwbGljYXRpb24gZ2l2ZXMgdGhlIHNhbWUgcmVzdWx0IGZvciBrIOKIiCB7MiwgNSwgMTMsIDI3fScsICgpID0+IHtcbiAgICBjb25zdCBhZmZpbmVDdXJ2ZSA9IG5ldyBDdXJ2ZVBhcmFtcyh7XG4gICAgICBwOiAyM24sXG4gICAgICBhOiAxbixcbiAgICAgIGI6IDFuLFxuICAgICAgbjogMjhuLFxuICAgICAgaDogMW4sXG4gICAgICBjb29yZDogQ29vcmRpbmF0ZVN5c3RlbS5BRkZJTkUsXG4gICAgfSlcbiAgICBjb25zdCBqYWNvYmlhbkN1cnZlID0gbmV3IEN1cnZlUGFyYW1zKHtcbiAgICAgIHA6IDIzbixcbiAgICAgIGE6IDFuLFxuICAgICAgYjogMW4sXG4gICAgICBuOiAyOG4sXG4gICAgICBoOiAxbixcbiAgICAgIGNvb3JkOiBDb29yZGluYXRlU3lzdGVtLkpBQ09CSUFOLFxuICAgIH0pXG4gICAgY29uc3QgUGEgPSBuZXcgUG9pbnQoMG4sIDFuLCBhZmZpbmVDdXJ2ZSlcbiAgICBjb25zdCBQaiA9IG5ldyBQb2ludCgwbiwgMW4sIGphY29iaWFuQ3VydmUpXG5cbiAgICBmb3IgKGNvbnN0IGsgb2YgWzJuLCA1biwgMTNuLCAyN25dKSB7XG4gICAgICBjb25zdCBSYSA9IFBhLm11bChrKVxuICAgICAgY29uc3QgUmogPSBQai5tdWwoaylcbiAgICAgIGV4cGVjdChSYS54KS50b0JlKFJqLngpXG4gICAgICBleHBlY3QoUmEueSkudG9CZShSai55KVxuICAgIH1cbiAgfSlcbn0pXG4iXSwibWFwcGluZ3MiOiI7O0FBQUEsSUFBQUEsUUFBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsTUFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsTUFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsS0FBQSxHQUFBSCxPQUFBO0FBQThELFNBQUFJLGVBQUFDLENBQUEsRUFBQUMsQ0FBQSxXQUFBQyxlQUFBLENBQUFGLENBQUEsS0FBQUcscUJBQUEsQ0FBQUgsQ0FBQSxFQUFBQyxDQUFB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