@bitgo/sdk-api 2.3.2 → 2.4.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/dist/package.json +6 -3
- package/dist/src/bitgoAPI.d.ts.map +1 -1
- package/dist/src/bitgoAPI.js +3 -2
- package/dist/src/decryptV1.d.ts +60 -0
- package/dist/src/decryptV1.d.ts.map +1 -0
- package/dist/src/decryptV1.js +140 -0
- package/dist/src/encrypt.d.ts +22 -1
- package/dist/src/encrypt.d.ts.map +1 -1
- package/dist/src/encrypt.js +85 -7
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/test/unit/decryptV1.browser.d.ts +2 -0
- package/dist/test/unit/decryptV1.browser.d.ts.map +1 -0
- package/dist/test/unit/decryptV1.browser.js +133 -0
- package/dist/test/unit/decryptV1.d.ts +2 -0
- package/dist/test/unit/decryptV1.d.ts.map +1 -0
- package/dist/test/unit/decryptV1.js +230 -0
- package/dist/test/unit/fixtures/keycard.d.ts +25 -0
- package/dist/test/unit/fixtures/keycard.d.ts.map +1 -0
- package/dist/test/unit/fixtures/keycard.js +28 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const sjcl = __importStar(require("@bitgo/sjcl"));
|
|
40
|
+
const assert_1 = __importDefault(require("assert"));
|
|
41
|
+
const crypto_1 = require("crypto");
|
|
42
|
+
const src_1 = require("../../src");
|
|
43
|
+
const keycard_1 = require("./fixtures/keycard");
|
|
44
|
+
/**
|
|
45
|
+
* sjcl.encrypt's typings require salt/iv, but the runtime picks them from
|
|
46
|
+
* sjcl.random when omitted. Feed real random words so the call type-checks
|
|
47
|
+
* without an `as` cast.
|
|
48
|
+
*/
|
|
49
|
+
function sjclEncrypt(password, plaintext, params) {
|
|
50
|
+
const salt = sjcl.random.randomWords(2); // 8 bytes
|
|
51
|
+
const iv = sjcl.random.randomWords(4); // 16 bytes
|
|
52
|
+
return sjcl.encrypt(password, plaintext, { ...params, salt, iv });
|
|
53
|
+
}
|
|
54
|
+
describe('decryptV1 (native, SJCL-free)', () => {
|
|
55
|
+
const password = 'myPassword';
|
|
56
|
+
const plaintext = 'Hello, World!';
|
|
57
|
+
describe('parity with SJCL', () => {
|
|
58
|
+
it('matches sjcl.decrypt output for the same envelope', async () => {
|
|
59
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
60
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(password, ciphertext), sjcl.decrypt(password, ciphertext));
|
|
61
|
+
});
|
|
62
|
+
it('decrypts with adata (AAD)', async () => {
|
|
63
|
+
const ciphertext = sjclEncrypt(password, plaintext, {
|
|
64
|
+
iter: 10000,
|
|
65
|
+
ks: 256,
|
|
66
|
+
ts: 64,
|
|
67
|
+
mode: 'ccm',
|
|
68
|
+
adata: 'context-A',
|
|
69
|
+
});
|
|
70
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(password, ciphertext), plaintext);
|
|
71
|
+
});
|
|
72
|
+
it('decrypts UTF-8 password + plaintext', async () => {
|
|
73
|
+
const utf8Password = 'pässwörd中文🔐';
|
|
74
|
+
const utf8Plaintext = 'passphrase: 秘密キー ☃🔑';
|
|
75
|
+
const ciphertext = sjclEncrypt(utf8Password, utf8Plaintext, { iter: 10000, ks: 256, ts: 64, mode: 'ccm' });
|
|
76
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(utf8Password, ciphertext), utf8Plaintext);
|
|
77
|
+
});
|
|
78
|
+
it('decrypts large plaintext (>64 KiB, forces L=3 nonce framing)', async () => {
|
|
79
|
+
const large = 'x'.repeat(70000);
|
|
80
|
+
const ciphertext = sjclEncrypt(password, large, { iter: 1000, ks: 256, ts: 64, mode: 'ccm' });
|
|
81
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(password, ciphertext), large);
|
|
82
|
+
});
|
|
83
|
+
it('decrypts aes-128 envelopes', async () => {
|
|
84
|
+
const ciphertext = sjclEncrypt(password, plaintext, { iter: 10000, ks: 128, ts: 64, mode: 'ccm' });
|
|
85
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(password, ciphertext), plaintext);
|
|
86
|
+
});
|
|
87
|
+
it('decrypts envelopes with 128-bit tag size', async () => {
|
|
88
|
+
const ciphertext = sjclEncrypt(password, plaintext, { iter: 10000, ks: 256, ts: 128, mode: 'ccm' });
|
|
89
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(password, ciphertext), plaintext);
|
|
90
|
+
});
|
|
91
|
+
it('parity across 50 randomised inputs', async () => {
|
|
92
|
+
for (let i = 0; i < 50; i++) {
|
|
93
|
+
const pw = (0, crypto_1.randomBytes)(16).toString('hex');
|
|
94
|
+
const pt = (0, crypto_1.randomBytes)(1 + Math.floor(Math.random() * 500)).toString('base64');
|
|
95
|
+
const ciphertext = sjclEncrypt(pw, pt, { iter: 1000, ks: 256, ts: 64, mode: 'ccm' });
|
|
96
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV1)(pw, ciphertext), pt, `iteration ${i}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('failure modes', () => {
|
|
101
|
+
it('throws on wrong password', async () => {
|
|
102
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
103
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1)('wrongPassword', ciphertext));
|
|
104
|
+
});
|
|
105
|
+
it('throws on invalid JSON', async () => {
|
|
106
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1)(password, 'not-json'), /invalid JSON envelope/);
|
|
107
|
+
});
|
|
108
|
+
it('rejects malformed envelope (representative codec check)', async () => {
|
|
109
|
+
const envelope = JSON.parse(await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 }));
|
|
110
|
+
envelope.mode = 'gcm';
|
|
111
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
112
|
+
});
|
|
113
|
+
it('rejects tampered ciphertext (auth-tag mismatch)', async () => {
|
|
114
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
115
|
+
const envelope = JSON.parse(ciphertext);
|
|
116
|
+
const tampered = Buffer.from(envelope.ct, 'base64');
|
|
117
|
+
tampered[0] ^= 0x01;
|
|
118
|
+
envelope.ct = tampered.toString('base64');
|
|
119
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1)(password, JSON.stringify(envelope)));
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('iter cap enforcement', () => {
|
|
123
|
+
it('rejects an envelope with iter above V1_MAX_ITER before running PBKDF2', async () => {
|
|
124
|
+
const envelope = JSON.parse(await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 }));
|
|
125
|
+
envelope.iter = src_1.V1_MAX_ITER + 1;
|
|
126
|
+
const start = Date.now();
|
|
127
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1)(password, JSON.stringify(envelope)), /iter/);
|
|
128
|
+
assert_1.default.ok(Date.now() - start < 100, 'must reject before any KDF work');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe('real BitGo keycard parity', () => {
|
|
132
|
+
it('Box A: native decrypt matches SJCL byte-for-byte', async () => {
|
|
133
|
+
const sjclResult = sjcl.decrypt(keycard_1.KEYCARD_PASSWORD, keycard_1.KEYCARD_BOX_A);
|
|
134
|
+
const nativeResult = await (0, src_1.decryptV1)(keycard_1.KEYCARD_PASSWORD, keycard_1.KEYCARD_BOX_A);
|
|
135
|
+
assert_1.default.strictEqual(nativeResult, sjclResult);
|
|
136
|
+
assert_1.default.strictEqual(nativeResult.length, keycard_1.KEYCARD_BOX_A_LENGTH);
|
|
137
|
+
assert_1.default.ok(nativeResult.startsWith(keycard_1.KEYCARD_PLAINTEXT_PREFIX));
|
|
138
|
+
});
|
|
139
|
+
it('Box B: native decrypt matches SJCL byte-for-byte', async () => {
|
|
140
|
+
const sjclResult = sjcl.decrypt(keycard_1.KEYCARD_PASSWORD, keycard_1.KEYCARD_BOX_B);
|
|
141
|
+
const nativeResult = await (0, src_1.decryptV1)(keycard_1.KEYCARD_PASSWORD, keycard_1.KEYCARD_BOX_B);
|
|
142
|
+
assert_1.default.strictEqual(nativeResult, sjclResult);
|
|
143
|
+
assert_1.default.strictEqual(nativeResult.length, keycard_1.KEYCARD_BOX_B_LENGTH);
|
|
144
|
+
assert_1.default.ok(nativeResult.startsWith(keycard_1.KEYCARD_PLAINTEXT_PREFIX));
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
describe('SJCL fallback behavior', () => {
|
|
148
|
+
// Rollout contract:
|
|
149
|
+
// - Native success -> no warn, no fallback.
|
|
150
|
+
// - Iter cap violation -> rethrown (no fallback), preserves DoS protection.
|
|
151
|
+
// - Both engines fail (e.g. wrong password) -> SJCL error rethrown, NO warn.
|
|
152
|
+
// - Native fails, SJCL succeeds -> return SJCL result + warn (engines disagree).
|
|
153
|
+
// eslint-disable-next-line no-console
|
|
154
|
+
const originalWarn = console.warn;
|
|
155
|
+
let warnings = [];
|
|
156
|
+
beforeEach(() => {
|
|
157
|
+
warnings = [];
|
|
158
|
+
// eslint-disable-next-line no-console
|
|
159
|
+
console.warn = (...args) => {
|
|
160
|
+
warnings.push(args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' '));
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
afterEach(() => {
|
|
164
|
+
// eslint-disable-next-line no-console
|
|
165
|
+
console.warn = originalWarn;
|
|
166
|
+
});
|
|
167
|
+
it('success path emits no console.warn', async () => {
|
|
168
|
+
const ct = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
169
|
+
await (0, src_1.decrypt)(password, ct);
|
|
170
|
+
assert_1.default.deepStrictEqual(warnings, []);
|
|
171
|
+
});
|
|
172
|
+
it('iter cap violation rethrows and does not warn', async () => {
|
|
173
|
+
const envelope = JSON.parse(await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 }));
|
|
174
|
+
envelope.iter = src_1.V1_MAX_ITER + 1;
|
|
175
|
+
await assert_1.default.rejects(() => (0, src_1.decrypt)(password, JSON.stringify(envelope)), /iter/);
|
|
176
|
+
assert_1.default.deepStrictEqual(warnings, []);
|
|
177
|
+
});
|
|
178
|
+
it('wrong password does not warn (both engines fail, SJCL error rethrown)', async () => {
|
|
179
|
+
const ct = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
180
|
+
await assert_1.default.rejects(() => (0, src_1.decrypt)('wrong', ct));
|
|
181
|
+
assert_1.default.deepStrictEqual(warnings, []);
|
|
182
|
+
});
|
|
183
|
+
it('warns and returns SJCL result when native fails but SJCL succeeds', async () => {
|
|
184
|
+
const ct = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
185
|
+
const brokenNative = async () => {
|
|
186
|
+
throw new Error('unsupported algorithm');
|
|
187
|
+
};
|
|
188
|
+
const result = await (0, src_1.decryptV1WithFallback)(password, ct, brokenNative);
|
|
189
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
190
|
+
assert_1.default.strictEqual(warnings.length, 1);
|
|
191
|
+
assert_1.default.ok(warnings[0].includes('SJCL fallback succeeded'));
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe('browser runtime (isBrowser = true)', () => {
|
|
195
|
+
it('skips native and decrypts via SJCL without warning', async () => {
|
|
196
|
+
const ct = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
197
|
+
const neverCalled = async () => {
|
|
198
|
+
throw new Error('native should not be attempted in the browser');
|
|
199
|
+
};
|
|
200
|
+
// eslint-disable-next-line no-console
|
|
201
|
+
const originalWarn = console.warn;
|
|
202
|
+
const warnings = [];
|
|
203
|
+
// eslint-disable-next-line no-console
|
|
204
|
+
console.warn = (...args) => {
|
|
205
|
+
warnings.push(args.join(' '));
|
|
206
|
+
};
|
|
207
|
+
try {
|
|
208
|
+
const result = await (0, src_1.decryptV1WithFallback)(password, ct, neverCalled, true);
|
|
209
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
210
|
+
assert_1.default.deepStrictEqual(warnings, []);
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
// eslint-disable-next-line no-console
|
|
214
|
+
console.warn = originalWarn;
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
it('still enforces the iter cap before running PBKDF2', async () => {
|
|
218
|
+
const envelope = JSON.parse(await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 }));
|
|
219
|
+
envelope.iter = src_1.V1_MAX_ITER + 1;
|
|
220
|
+
const start = Date.now();
|
|
221
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1WithFallback)(password, JSON.stringify(envelope), src_1.decryptV1, true), /iter/);
|
|
222
|
+
assert_1.default.ok(Date.now() - start < 100, 'must reject before any KDF work');
|
|
223
|
+
});
|
|
224
|
+
it('rejects wrong password via SJCL auth failure', async () => {
|
|
225
|
+
const ct = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
226
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV1WithFallback)('wrongPassword', ct, src_1.decryptV1, true));
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjcnlwdFYxLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2RlY3J5cHRWMS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGtEQUFvQztBQUNwQyxvREFBNEI7QUFDNUIsbUNBQXFDO0FBRXJDLG1DQUE0RjtBQUM1RixnREFPNEI7QUFFNUI7Ozs7R0FJRztBQUNILFNBQVMsV0FBVyxDQUFDLFFBQWdCLEVBQUUsU0FBaUIsRUFBRSxNQUE2QjtJQUNyRixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVU7SUFDbkQsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXO0lBQ2xELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLEVBQUUsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDcEUsQ0FBQztBQUVELFFBQVEsQ0FBQywrQkFBK0IsRUFBRSxHQUFHLEVBQUU7SUFDN0MsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDO0lBQzlCLE1BQU0sU0FBUyxHQUFHLGVBQWUsQ0FBQztJQUVsQyxRQUFRLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO1FBQ2hDLEVBQUUsQ0FBQyxtREFBbUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNqRSxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUEsYUFBTyxFQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2hGLGdCQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sSUFBQSxlQUFTLEVBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxFQUFFLElB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QUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLElBQUEsYUFBTyxFQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUYsUUFBUSxDQUFDLElBQUksR0FBRyxpQkFBVyxHQUFHLENBQUMsQ0FBQztZQUNoQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDekIsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFBLDJCQUFxQixFQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFFLGVBQVMsRUFBRSxJQUFJLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMvRyxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsS0FBSyxHQUFHLEdBQUcsRUFBRSxpQ0FBaUMsQ0FBQyxDQUFDO1FBQ3pFLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDhDQUE4QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzVELE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBQSxhQUFPLEVBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxFQUFFLGlCQUFpQixFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEUsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFBLDJCQUFxQixFQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsZUFBUyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDMUYsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgc2pjbCBmcm9tICdAYml0Z28vc2pjbCc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyByYW5kb21CeXRlcyB9IGZyb20gJ2NyeXB0byc7XG5cbmltcG9ydCB7IGRlY3J5cHQsIGRlY3J5cHRWMSwgZGVjcnlwdFYxV2l0aEZhbGxiYWNrLCBlbmNyeXB0LCBWMV9NQVhfSVRFUiB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQge1xuICBLRVlDQVJEX0JPWF9BLFxuICBLRVlDQVJEX0JPWF9BX0xFTkdUSCxcbiAgS0VZQ0FSRF9CT1hfQixcbiAgS0VZQ0FSRF9CT1hfQl9MRU5HVEgsXG4gIEtFWUNBUkRfUEFTU1dPUkQsXG4gIEtFWUNBUkRfUExBSU5URVhUX1BSRUZJWCxcbn0gZnJvbSAnLi9maXh0dXJlcy9rZXljYXJkJztcblxuLyoqXG4gKiBzamNsLmVuY3J5cHQncyB0eXBpbmdzIHJlcXVpcmUgc2FsdC9pdiwgYnV0IHRoZSBydW50aW1lIHBpY2tzIHRoZW0gZnJvbVxuICogc2pjbC5yYW5kb20gd2hlbiBvbWl0dGVkLiBGZWVkIHJlYWwgcmFuZG9tIHdvcmRzIHNvIHRoZSBjYWxsIHR5cGUtY2hlY2tzXG4gKiB3aXRob3V0IGFuIGBhc2AgY2FzdC5cbiAqL1xuZnVuY3Rpb24gc2pjbEVuY3J5cHQocGFzc3dvcmQ6IHN0cmluZywgcGxhaW50ZXh0OiBzdHJpbmcsIHBhcmFtczogc2pjbC5TamNsQ2lwaGVyUGFyYW1zKTogc3RyaW5nIHtcbiAgY29uc3Qgc2FsdCA9IHNqY2wucmFuZG9tLnJhbmRvbVdvcmRzKDIpOyAvLyA4IGJ5dGVzXG4gIGNvbnN0IGl2ID0gc2pjbC5yYW5kb20ucmFuZG9tV29yZHMoNCk7IC8vIDE2IGJ5dGVzXG4gIHJldHVybiBzamNsLmVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyAuLi5wYXJhbXMsIHNhbHQsIGl2IH0pO1xufVxuXG5kZXNjcmliZSgnZGVjcnlwdFYxIChuYXRpdmUsIFNKQ0wtZnJlZSknLCAoKSA9PiB7XG4gIGNvbnN0IHBhc3N3b3JkID0gJ215UGFzc3dvcmQnO1xuICBjb25zdCBwbGFpbnRleHQgPSAnSGVsbG8sIFdvcmxkISc7XG5cbiAgZGVzY3JpYmUoJ3Bhcml0eSB3aXRoIFNKQ0wnLCAoKSA9PiB7XG4gICAgaXQoJ21hdGNoZXMgc2pjbC5kZWNyeXB0IG91dHB1dCBmb3IgdGhlIHNhbWUgZW52ZWxvcGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGVuY3J5cHRpb25WZXJzaW9uOiAxIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHRWMShwYXNzd29yZCwgY2lwaGVydGV4dCksIHNqY2wuZGVjcnlwdChwYXNzd29yZCwgY2lwaGVydGV4dCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlY3J5cHRzIHdpdGggYWRhdGEgKEFBRCknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gc2pjbEVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwge1xuICAgICAgICBpdGVyOiAxMDAwMCxcbiAgICAgICAga3M6IDI1NixcbiAgICAgICAgdHM6IDY0LFxuICAgICAgICBtb2RlOiAnY2NtJyxcbiAgICAgICAgYWRhdGE6ICdjb250ZXh0LUEnLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdFYxKHBhc3N3b3JkLCBjaXBoZXJ0ZXh0KSwgcGxhaW50ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWNyeXB0cyBVVEYtOCBwYXNzd29yZCArIHBsYWludGV4dCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHV0ZjhQYXNzd29yZCA9ICdww6Rzc3fDtnJk5Lit5paH8J+UkCc7XG4gICAgICBjb25zdCB1dGY4UGxhaW50ZXh0ID0gJ3Bhc3NwaHJhc2U6IOenmOWvhuOCreODvCDimIPwn5SRJztcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBzamNsRW5jcnlwdCh1dGY4UGFzc3dvcmQsIHV0ZjhQbGFpbnRleHQsIHsgaXRlcjogMTAwMDAsIGtzOiAyNTYsIHRzOiA2NCwgbW9kZTogJ2NjbScgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdFYxKHV0ZjhQYXNzd29yZCwgY2lwaGVydGV4dCksIHV0ZjhQbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlY3J5cHRzIGxhcmdlIHBsYWludGV4dCAoPjY0IEtpQiwgZm9yY2VzIEw9MyBub25jZSBmcmFtaW5nKScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGxhcmdlID0gJ3gnLnJlcGVhdCg3MF8wMDApO1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IHNqY2xFbmNyeXB0KHBhc3N3b3JkLCBsYXJnZSwgeyBpdGVyOiAxMDAwLCBrczogMjU2LCB0czogNjQsIG1vZGU6ICdjY20nIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHRWMShwYXNzd29yZCwgY2lwaGVydGV4dCksIGxhcmdlKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWNyeXB0cyBhZXMtMTI4IGVudmVsb3BlcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBzamNsRW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGl0ZXI6IDEwMDAwLCBrczogMTI4LCB0czogNjQsIG1vZGU6ICdjY20nIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHRWMShwYXNzd29yZCwgY2lwaGVydGV4dCksIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVjcnlwdHMgZW52ZWxvcGVzIHdpdGggMTI4LWJpdCB0YWcgc2l6ZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBzamNsRW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGl0ZXI6IDEwMDAwLCBrczogMjU2LCB0czogMTI4LCBtb2RlOiAnY2NtJyB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBkZWNyeXB0VjEocGFzc3dvcmQsIGNpcGhlcnRleHQpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Bhcml0eSBhY3Jvc3MgNTAgcmFuZG9taXNlZCBpbnB1dHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDUwOyBpKyspIHtcbiAgICAgICAgY29uc3QgcHcgPSByYW5kb21CeXRlcygxNikudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgICBjb25zdCBwdCA9IHJhbmRvbUJ5dGVzKDEgKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiA1MDApKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBzamNsRW5jcnlwdChwdywgcHQsIHsgaXRlcjogMTAwMCwga3M6IDI1NiwgdHM6IDY0LCBtb2RlOiAnY2NtJyB9KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHRWMShwdywgY2lwaGVydGV4dCksIHB0LCBgaXRlcmF0aW9uICR7aX1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2ZhaWx1cmUgbW9kZXMnLCAoKSA9PiB7XG4gICAgaXQoJ3Rocm93cyBvbiB3cm9uZyBwYXNzd29yZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjEoJ3dyb25nUGFzc3dvcmQnLCBjaXBoZXJ0ZXh0KSk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIG9uIGludmFsaWQgSlNPTicsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHRWMShwYXNzd29yZCwgJ25vdC1qc29uJyksIC9pbnZhbGlkIEpTT04gZW52ZWxvcGUvKTtcbiAgICB9KTtcblxuICAgIGl0KCdyZWplY3RzIG1hbGZvcm1lZCBlbnZlbG9wZSAocmVwcmVzZW50YXRpdmUgY29kZWMgY2hlY2spJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KSk7XG4gICAgICBlbnZlbG9wZS5tb2RlID0gJ2djbSc7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjEocGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9pbnZhbGlkIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyB0YW1wZXJlZCBjaXBoZXJ0ZXh0IChhdXRoLXRhZyBtaXNtYXRjaCknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGVuY3J5cHRpb25WZXJzaW9uOiAxIH0pO1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKGNpcGhlcnRleHQpO1xuICAgICAgY29uc3QgdGFtcGVyZWQgPSBCdWZmZXIuZnJvbShlbnZlbG9wZS5jdCwgJ2Jhc2U2NCcpO1xuICAgICAgdGFtcGVyZWRbMF0gXj0gMHgwMTtcbiAgICAgIGVudmVsb3BlLmN0ID0gdGFtcGVyZWQudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYxKHBhc3N3b3JkLCBKU09OLnN0cmluZ2lmeShlbnZlbG9wZSkpKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2l0ZXIgY2FwIGVuZm9yY2VtZW50JywgKCkgPT4ge1xuICAgIGl0KCdyZWplY3RzIGFuIGVudmVsb3BlIHdpdGggaXRlciBhYm92ZSBWMV9NQVhfSVRFUiBiZWZvcmUgcnVubmluZyBQQktERjInLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IEpTT04ucGFyc2UoYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGVuY3J5cHRpb25WZXJzaW9uOiAxIH0pKTtcbiAgICAgIGVudmVsb3BlLml0ZXIgPSBWMV9NQVhfSVRFUiArIDE7XG4gICAgICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjEocGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9pdGVyLyk7XG4gICAgICBhc3NlcnQub2soRGF0ZS5ub3coKSAtIHN0YXJ0IDwgMTAwLCAnbXVzdCByZWplY3QgYmVmb3JlIGFueSBLREYgd29yaycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncmVhbCBCaXRHbyBrZXljYXJkIHBhcml0eScsICgpID0+IHtcbiAgICBpdCgnQm94IEE6IG5hdGl2ZSBkZWNyeXB0IG1hdGNoZXMgU0pDTCBieXRlLWZvci1ieXRlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2pjbFJlc3VsdCA9IHNqY2wuZGVjcnlwdChLRVlDQVJEX1BBU1NXT1JELCBLRVlDQVJEX0JPWF9BKTtcbiAgICAgIGNvbnN0IG5hdGl2ZVJlc3VsdCA9IGF3YWl0IGRlY3J5cHRWMShLRVlDQVJEX1BBU1NXT1JELCBLRVlDQVJEX0JPWF9BKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChuYXRpdmVSZXN1bHQsIHNqY2xSZXN1bHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG5hdGl2ZVJlc3VsdC5sZW5ndGgsIEtFWUNBUkRfQk9YX0FfTEVOR1RIKTtcbiAgICAgIGFzc2VydC5vayhuYXRpdmVSZXN1bHQuc3RhcnRzV2l0aChLRVlDQVJEX1BMQUlOVEVYVF9QUkVGSVgpKTtcbiAgICB9KTtcblxuICAgIGl0KCdCb3ggQjogbmF0aXZlIGRlY3J5cHQgbWF0Y2hlcyBTSkNMIGJ5dGUtZm9yLWJ5dGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzamNsUmVzdWx0ID0gc2pjbC5kZWNyeXB0KEtFWUNBUkRfUEFTU1dPUkQsIEtFWUNBUkRfQk9YX0IpO1xuICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gYXdhaXQgZGVjcnlwdFYxKEtFWUNBUkRfUEFTU1dPUkQsIEtFWUNBUkRfQk9YX0IpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG5hdGl2ZVJlc3VsdCwgc2pjbFJlc3VsdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwobmF0aXZlUmVzdWx0Lmxlbmd0aCwgS0VZQ0FSRF9CT1hfQl9MRU5HVEgpO1xuICAgICAgYXNzZXJ0Lm9rKG5hdGl2ZVJlc3VsdC5zdGFydHNXaXRoKEtFWUNBUkRfUExBSU5URVhUX1BSRUZJWCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU0pDTCBmYWxsYmFjayBiZWhhdmlvcicsICgpID0+IHtcbiAgICAvLyBSb2xsb3V0IGNvbnRyYWN0OlxuICAgIC8vIC0gTmF0aXZlIHN1Y2Nlc3MgLT4gbm8gd2Fybiwgbm8gZmFsbGJhY2suXG4gICAgLy8gLSBJdGVyIGNhcCB2aW9sYXRpb24gLT4gcmV0aHJvd24gKG5vIGZhbGxiYWNrKSwgcHJlc2VydmVzIERvUyBwcm90ZWN0aW9uLlxuICAgIC8vIC0gQm90aCBlbmdpbmVzIGZhaWwgKGUuZy4gd3JvbmcgcGFzc3dvcmQpIC0+IFNKQ0wgZXJyb3IgcmV0aHJvd24sIE5PIHdhcm4uXG4gICAgLy8gLSBOYXRpdmUgZmFpbHMsIFNKQ0wgc3VjY2VlZHMgLT4gcmV0dXJuIFNKQ0wgcmVzdWx0ICsgd2FybiAoZW5naW5lcyBkaXNhZ3JlZSkuXG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnN0IG9yaWdpbmFsV2FybiA9IGNvbnNvbGUud2FybjtcbiAgICBsZXQgd2FybmluZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIHdhcm5pbmdzID0gW107XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuID0gKC4uLmFyZ3M6IHVua25vd25bXSkgPT4ge1xuICAgICAgICB3YXJuaW5ncy5wdXNoKGFyZ3MubWFwKChhKSA9PiAodHlwZW9mIGEgPT09ICdzdHJpbmcnID8gYSA6IEpTT04uc3RyaW5naWZ5KGEpKSkuam9pbignICcpKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goKCkgPT4ge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybiA9IG9yaWdpbmFsV2FybjtcbiAgICB9KTtcblxuICAgIGl0KCdzdWNjZXNzIHBhdGggZW1pdHMgbm8gY29uc29sZS53YXJuJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBhd2FpdCBkZWNyeXB0KHBhc3N3b3JkLCBjdCk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHdhcm5pbmdzLCBbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnaXRlciBjYXAgdmlvbGF0aW9uIHJldGhyb3dzIGFuZCBkb2VzIG5vdCB3YXJuJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KSk7XG4gICAgICBlbnZlbG9wZS5pdGVyID0gVjFfTUFYX0lURVIgKyAxO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdChwYXNzd29yZCwgSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKSwgL2l0ZXIvKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwod2FybmluZ3MsIFtdKTtcbiAgICB9KTtcblxuICAgIGl0KCd3cm9uZyBwYXNzd29yZCBkb2VzIG5vdCB3YXJuIChib3RoIGVuZ2luZXMgZmFpbCwgU0pDTCBlcnJvciByZXRocm93biknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHQoJ3dyb25nJywgY3QpKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwod2FybmluZ3MsIFtdKTtcbiAgICB9KTtcblxuICAgIGl0KCd3YXJucyBhbmQgcmV0dXJucyBTSkNMIHJlc3VsdCB3aGVuIG5hdGl2ZSBmYWlscyBidXQgU0pDTCBzdWNjZWVkcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGVuY3J5cHRpb25WZXJzaW9uOiAxIH0pO1xuICAgICAgY29uc3QgYnJva2VuTmF0aXZlID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc3VwcG9ydGVkIGFsZ29yaXRobScpO1xuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRlY3J5cHRWMVdpdGhGYWxsYmFjayhwYXNzd29yZCwgY3QsIGJyb2tlbk5hdGl2ZSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCBwbGFpbnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHdhcm5pbmdzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQub2sod2FybmluZ3NbMF0uaW5jbHVkZXMoJ1NKQ0wgZmFsbGJhY2sgc3VjY2VlZGVkJykpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYnJvd3NlciBydW50aW1lIChpc0Jyb3dzZXIgPSB0cnVlKScsICgpID0+IHtcbiAgICBpdCgnc2tpcHMgbmF0aXZlIGFuZCBkZWNyeXB0cyB2aWEgU0pDTCB3aXRob3V0IHdhcm5pbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIGNvbnN0IG5ldmVyQ2FsbGVkID0gYXN5bmMgKCk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbmF0aXZlIHNob3VsZCBub3QgYmUgYXR0ZW1wdGVkIGluIHRoZSBicm93c2VyJyk7XG4gICAgICB9O1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnN0IG9yaWdpbmFsV2FybiA9IGNvbnNvbGUud2FybjtcbiAgICAgIGNvbnN0IHdhcm5pbmdzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybiA9ICguLi5hcmdzOiB1bmtub3duW10pID0+IHtcbiAgICAgICAgd2FybmluZ3MucHVzaChhcmdzLmpvaW4oJyAnKSk7XG4gICAgICB9O1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGVjcnlwdFYxV2l0aEZhbGxiYWNrKHBhc3N3b3JkLCBjdCwgbmV2ZXJDYWxsZWQsIHRydWUpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCBwbGFpbnRleHQpO1xuICAgICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHdhcm5pbmdzLCBbXSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLndhcm4gPSBvcmlnaW5hbFdhcm47XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc3RpbGwgZW5mb3JjZXMgdGhlIGl0ZXIgY2FwIGJlZm9yZSBydW5uaW5nIFBCS0RGMicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0gSlNPTi5wYXJzZShhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSkpO1xuICAgICAgZW52ZWxvcGUuaXRlciA9IFYxX01BWF9JVEVSICsgMTtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHRWMVdpdGhGYWxsYmFjayhwYXNzd29yZCwgSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpLCBkZWNyeXB0VjEsIHRydWUpLCAvaXRlci8pO1xuICAgICAgYXNzZXJ0Lm9rKERhdGUubm93KCkgLSBzdGFydCA8IDEwMCwgJ211c3QgcmVqZWN0IGJlZm9yZSBhbnkgS0RGIHdvcmsnKTtcbiAgICB9KTtcblxuICAgIGl0KCdyZWplY3RzIHdyb25nIHBhc3N3b3JkIHZpYSBTSkNMIGF1dGggZmFpbHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGVuY3J5cHRpb25WZXJzaW9uOiAxIH0pO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYxV2l0aEZhbGxiYWNrKCd3cm9uZ1Bhc3N3b3JkJywgY3QsIGRlY3J5cHRWMSwgdHJ1ZSkpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixtures for real-world v1 decrypt parity tests.
|
|
3
|
+
*
|
|
4
|
+
* These come from a purpose-built BitGo test keycard (wallet name: "sol")
|
|
5
|
+
* created 2026-08-14 solely for this test suite. The wallet is a throwaway
|
|
6
|
+
* testnet Solana wallet with no real funds; the ciphertexts, wallet, and
|
|
7
|
+
* password below are safe to check in.
|
|
8
|
+
*
|
|
9
|
+
* Boxes A + B are the user and backup MPC key shares (uShare), encrypted
|
|
10
|
+
* client-side with the wallet password using the exact envelope shape BitGo
|
|
11
|
+
* produces in production (`iter=10000, ks=256, ts=64, mode=ccm, cipher=aes,
|
|
12
|
+
* adata=""`).
|
|
13
|
+
*
|
|
14
|
+
* Purpose: catch any regression where the native/shim decrypt paths diverge
|
|
15
|
+
* from SJCL on real production-shaped envelopes.
|
|
16
|
+
*/
|
|
17
|
+
export declare const KEYCARD_PASSWORD = "97IoV9Qs3fuhBKYCg6ju0y6LPBHTywBY";
|
|
18
|
+
export declare const KEYCARD_BOX_A = "{\"iv\":\"iury+nZhVfoWjpzbzrN1Yw==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"WiUMqHlpxiQ=\",\"ct\":\"Qx6nr/Q+oEaHmmsIq75cHcR4hR4XzowpJvdgNuzcGD6v113dimT8tg2FAWAGj+syRfH19X5cDBhFX6k3ifWMbyQHneHs0OGh86kjm/v4ddNHaGgGEzhsQCWX2tAOyhxT+oG5PewnSr+xFGZePvo0GFakmPFLzF9gfvG8K3o30i0iU5UyzPdp5iAZGbZTseqp6d3KXcleA712Gnv5eT0mlDYJwoi9Io7TwCjdaa2M5r1PFkN8ZaC1aIzba3A+f7b7PDrfFckGGDIl6o2ytjNEpCKvvbfiTbk9/WOIXtMibW1e3ysmuPl5tiw2lSAtYXHQOl9rqwEvtoIMtM2uZqAE+ELf8UiabdBpdCYFiSVBgD+jjEfgUocd7xCRh2bW/Uqhu8ye7SDdZowMaTI3d/sGW8QubquPaHWQZTkhvDXttT0l1YXsIld3L2mQfDw+FpFD+SihNDiCf4fVYHFI/I9bYMx03QnUV+wXyo0dl1QXnkyVxTVOeaoJ7dM7Tp7h5cY2m5Dlp2YvAY2twRzOSPKjYu8M+rUuY0GsbodZW8mKXCLVfTyNmonSgqmLZ7V8MlZ4oR2gGfPn39XrGG9fRPj3lKb4gaFCSweHWfXAAXLN+MP9BquE57cphKn8RcuwwGPnH0j/tKOdcqKtn1XcAKtf8+s3L7utIXS+dijADqTLrjfG/2gKe4NbpykiW/vOPQ+2BbZO7d0F0YMnd2di/KD2VL5Y3M6Iib1zZAQX1r41X9Zb1/ShEsKtFyObi2zG0atYrQ6g4+f11nBbwJa6BD6n3P+UAaHvIJoXEFnaccvq3OWowlHQppQUOqCkdg5kwf2fXJqkR9hGGSBpXM48gm61hgwR12n2rDQxks6wwtdtm5BMKZrJy25x/ZAqYaQejm+0dT9SVa0qpNNOa1IdDzrPnI0AL1aLNGOVQ9EwEt9OOYoS/DBTp7JmVwhShDC5w8Br3KOKsm5qlWz/uslhfWBR7l6+BFft2jjfeCmfjZORCuhV5tX5nnQXuc13HjQkrdzaJE+LXZYtal+U83i2SfdwZnWuplTQqxKk+C0ikfGGJd7PDNb+8VEoR3rEIXk4YKJyI/HyPAVwNJN48tm/364SOm/iPV+wW5HvwPDmRJBan5vs66pTT2GtkZsZD1L+BxN4s8ycM4BWO1xyjgTI7mKjSatSnBqeJ0Cm0bIHq8hsbM9lH8yc0VsJ\"}";
|
|
19
|
+
export declare const KEYCARD_BOX_B = "{\"iv\":\"QZw8ZmHqaBqQh6X6PSCcMg==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"yM+BoSyVwaY=\",\"ct\":\"oPtcvWYf287IRi9To/UobTLrm5m+YCs6Tp1CuYvPJ5oazTcbmzZkS+gn2hxAGCvojGGV61qieEgrKEKDdKLE4/jSWUhY/VXyFE6BRb2uB5pFny8NwSsVb5Gw5R38bgs0XZ0aL4RCEQgByIkWGKJn3ZbpfmzFcD+x226WZkL0gS1DN5RK8bwAfgrabVp6MupLa/NN7M/YiH9aO9PELdvu/mbyC0zdAwwY8MHpMdf5IPOJi3ieMorUtEsuzfP4SBI2EAHdFi3/VmzIKG69sZS1uIULHB5Xya5ury7+qp6nihlxJOB4S8zpri/rXow+0EQL2bKUSkQz6r6GTL5MclyfkxVcCptVMPrCcsDdVc9P0sR36iP/AsdCTJGuHbzv0AERs776+cUyqivlQj1CQ3GkIHNQKyYjktKLx1PmEMTo29hEEbKVavM8ZoxTbjL/uIaxpz9Di1zh3RB8f1HXmq2JD2XEAPAky+Ukh8FSavROG64GRkPJY4AtUxXvvzUc2M9QCy6wbDIC8prJEio5jWyKZSZ4KVpMSEK98/htMjgB8hH07CdfiJnvMVy7xe9hHOtl3zThMP6r+9g8WpGdT02Y2kWWOVZlhBaPohuiCiJLHOigiN86Tt7i5kgSTB6w8zT4tcZWzSeOBh68eAupDt0qOdfadNESQICJ3fAgfQfeR7pPzjt54npB7c9KpLnJgDhrl4LpwicwZwuYKv0gJ7t9KKKTLFHRp5RD5Nr+8tk10aIxDQxLWCVSwalie5HhTzPsF8OUqNrJJ9mSBGtsTh/Saf5osvE/ETYdU7PTJpVHDYCS5/DaCrV7acZn1ZBzCD9P9FzttzF8RlwPOideEsYDWLORvwdmNHYgTavNnOY4UnISgA07UtFsgzgJ4gC4ubCE32C5MNkX4hGIi/15O4Y0ZaiAeOu2Qnm9r6zfdYZP4TCeQAZEGKy5DsO+VYOLImvhRZD8aOoFvxmQJWM5MEMozEImms8cwJuDRP60WhZqUCgemmmyHHDRPG3+EmUGU2W4QWDQt7G6uADcDCFsYojyshg0+6QRMdc5pLR3wUa4MRug7t49kit0Q/yFMn8kHn6/jhokRdIHt8Yvo1/wnGmw7aGvKX3rtUKOpqZ4AkOakhKuqRJyJvh3nsfz6BXtjx0UnW80Dt8WgAol+x0IFLcbcnwjICotU9uupfn+ONGK0C4NUSiJVg==\"}";
|
|
20
|
+
/** Prefix of the decrypted plaintext for structural sanity checking. Both boxes are MPC uShare JSON. */
|
|
21
|
+
export declare const KEYCARD_PLAINTEXT_PREFIX = "{\"uShare\":{\"i\":";
|
|
22
|
+
/** Expected plaintext lengths, verified against sjcl.decrypt during test authoring. */
|
|
23
|
+
export declare const KEYCARD_BOX_A_LENGTH = 895;
|
|
24
|
+
export declare const KEYCARD_BOX_B_LENGTH = 893;
|
|
25
|
+
//# sourceMappingURL=keycard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keycard.d.ts","sourceRoot":"","sources":["../../../../test/unit/fixtures/keycard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,gBAAgB,qCAAqC,CAAC;AAEnE,eAAO,MAAM,aAAa,m2CACwyC,CAAC;AAEn0C,eAAO,MAAM,aAAa,m2CACwyC,CAAC;AAEn0C,wGAAwG;AACxG,eAAO,MAAM,wBAAwB,wBAAoB,CAAC;AAE1D,uFAAuF;AACvF,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,oBAAoB,MAAM,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fixtures for real-world v1 decrypt parity tests.
|
|
4
|
+
*
|
|
5
|
+
* These come from a purpose-built BitGo test keycard (wallet name: "sol")
|
|
6
|
+
* created 2026-08-14 solely for this test suite. The wallet is a throwaway
|
|
7
|
+
* testnet Solana wallet with no real funds; the ciphertexts, wallet, and
|
|
8
|
+
* password below are safe to check in.
|
|
9
|
+
*
|
|
10
|
+
* Boxes A + B are the user and backup MPC key shares (uShare), encrypted
|
|
11
|
+
* client-side with the wallet password using the exact envelope shape BitGo
|
|
12
|
+
* produces in production (`iter=10000, ks=256, ts=64, mode=ccm, cipher=aes,
|
|
13
|
+
* adata=""`).
|
|
14
|
+
*
|
|
15
|
+
* Purpose: catch any regression where the native/shim decrypt paths diverge
|
|
16
|
+
* from SJCL on real production-shaped envelopes.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.KEYCARD_BOX_B_LENGTH = exports.KEYCARD_BOX_A_LENGTH = exports.KEYCARD_PLAINTEXT_PREFIX = exports.KEYCARD_BOX_B = exports.KEYCARD_BOX_A = exports.KEYCARD_PASSWORD = void 0;
|
|
20
|
+
exports.KEYCARD_PASSWORD = '97IoV9Qs3fuhBKYCg6ju0y6LPBHTywBY';
|
|
21
|
+
exports.KEYCARD_BOX_A = '{"iv":"iury+nZhVfoWjpzbzrN1Yw==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"WiUMqHlpxiQ=","ct":"Qx6nr/Q+oEaHmmsIq75cHcR4hR4XzowpJvdgNuzcGD6v113dimT8tg2FAWAGj+syRfH19X5cDBhFX6k3ifWMbyQHneHs0OGh86kjm/v4ddNHaGgGEzhsQCWX2tAOyhxT+oG5PewnSr+xFGZePvo0GFakmPFLzF9gfvG8K3o30i0iU5UyzPdp5iAZGbZTseqp6d3KXcleA712Gnv5eT0mlDYJwoi9Io7TwCjdaa2M5r1PFkN8ZaC1aIzba3A+f7b7PDrfFckGGDIl6o2ytjNEpCKvvbfiTbk9/WOIXtMibW1e3ysmuPl5tiw2lSAtYXHQOl9rqwEvtoIMtM2uZqAE+ELf8UiabdBpdCYFiSVBgD+jjEfgUocd7xCRh2bW/Uqhu8ye7SDdZowMaTI3d/sGW8QubquPaHWQZTkhvDXttT0l1YXsIld3L2mQfDw+FpFD+SihNDiCf4fVYHFI/I9bYMx03QnUV+wXyo0dl1QXnkyVxTVOeaoJ7dM7Tp7h5cY2m5Dlp2YvAY2twRzOSPKjYu8M+rUuY0GsbodZW8mKXCLVfTyNmonSgqmLZ7V8MlZ4oR2gGfPn39XrGG9fRPj3lKb4gaFCSweHWfXAAXLN+MP9BquE57cphKn8RcuwwGPnH0j/tKOdcqKtn1XcAKtf8+s3L7utIXS+dijADqTLrjfG/2gKe4NbpykiW/vOPQ+2BbZO7d0F0YMnd2di/KD2VL5Y3M6Iib1zZAQX1r41X9Zb1/ShEsKtFyObi2zG0atYrQ6g4+f11nBbwJa6BD6n3P+UAaHvIJoXEFnaccvq3OWowlHQppQUOqCkdg5kwf2fXJqkR9hGGSBpXM48gm61hgwR12n2rDQxks6wwtdtm5BMKZrJy25x/ZAqYaQejm+0dT9SVa0qpNNOa1IdDzrPnI0AL1aLNGOVQ9EwEt9OOYoS/DBTp7JmVwhShDC5w8Br3KOKsm5qlWz/uslhfWBR7l6+BFft2jjfeCmfjZORCuhV5tX5nnQXuc13HjQkrdzaJE+LXZYtal+U83i2SfdwZnWuplTQqxKk+C0ikfGGJd7PDNb+8VEoR3rEIXk4YKJyI/HyPAVwNJN48tm/364SOm/iPV+wW5HvwPDmRJBan5vs66pTT2GtkZsZD1L+BxN4s8ycM4BWO1xyjgTI7mKjSatSnBqeJ0Cm0bIHq8hsbM9lH8yc0VsJ"}';
|
|
22
|
+
exports.KEYCARD_BOX_B = '{"iv":"QZw8ZmHqaBqQh6X6PSCcMg==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"yM+BoSyVwaY=","ct":"oPtcvWYf287IRi9To/UobTLrm5m+YCs6Tp1CuYvPJ5oazTcbmzZkS+gn2hxAGCvojGGV61qieEgrKEKDdKLE4/jSWUhY/VXyFE6BRb2uB5pFny8NwSsVb5Gw5R38bgs0XZ0aL4RCEQgByIkWGKJn3ZbpfmzFcD+x226WZkL0gS1DN5RK8bwAfgrabVp6MupLa/NN7M/YiH9aO9PELdvu/mbyC0zdAwwY8MHpMdf5IPOJi3ieMorUtEsuzfP4SBI2EAHdFi3/VmzIKG69sZS1uIULHB5Xya5ury7+qp6nihlxJOB4S8zpri/rXow+0EQL2bKUSkQz6r6GTL5MclyfkxVcCptVMPrCcsDdVc9P0sR36iP/AsdCTJGuHbzv0AERs776+cUyqivlQj1CQ3GkIHNQKyYjktKLx1PmEMTo29hEEbKVavM8ZoxTbjL/uIaxpz9Di1zh3RB8f1HXmq2JD2XEAPAky+Ukh8FSavROG64GRkPJY4AtUxXvvzUc2M9QCy6wbDIC8prJEio5jWyKZSZ4KVpMSEK98/htMjgB8hH07CdfiJnvMVy7xe9hHOtl3zThMP6r+9g8WpGdT02Y2kWWOVZlhBaPohuiCiJLHOigiN86Tt7i5kgSTB6w8zT4tcZWzSeOBh68eAupDt0qOdfadNESQICJ3fAgfQfeR7pPzjt54npB7c9KpLnJgDhrl4LpwicwZwuYKv0gJ7t9KKKTLFHRp5RD5Nr+8tk10aIxDQxLWCVSwalie5HhTzPsF8OUqNrJJ9mSBGtsTh/Saf5osvE/ETYdU7PTJpVHDYCS5/DaCrV7acZn1ZBzCD9P9FzttzF8RlwPOideEsYDWLORvwdmNHYgTavNnOY4UnISgA07UtFsgzgJ4gC4ubCE32C5MNkX4hGIi/15O4Y0ZaiAeOu2Qnm9r6zfdYZP4TCeQAZEGKy5DsO+VYOLImvhRZD8aOoFvxmQJWM5MEMozEImms8cwJuDRP60WhZqUCgemmmyHHDRPG3+EmUGU2W4QWDQt7G6uADcDCFsYojyshg0+6QRMdc5pLR3wUa4MRug7t49kit0Q/yFMn8kHn6/jhokRdIHt8Yvo1/wnGmw7aGvKX3rtUKOpqZ4AkOakhKuqRJyJvh3nsfz6BXtjx0UnW80Dt8WgAol+x0IFLcbcnwjICotU9uupfn+ONGK0C4NUSiJVg=="}';
|
|
23
|
+
/** Prefix of the decrypted plaintext for structural sanity checking. Both boxes are MPC uShare JSON. */
|
|
24
|
+
exports.KEYCARD_PLAINTEXT_PREFIX = '{"uShare":{"i":';
|
|
25
|
+
/** Expected plaintext lengths, verified against sjcl.decrypt during test authoring. */
|
|
26
|
+
exports.KEYCARD_BOX_A_LENGTH = 895;
|
|
27
|
+
exports.KEYCARD_BOX_B_LENGTH = 893;
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5Y2FyZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9maXh0dXJlcy9rZXljYXJkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7OztBQUVVLFFBQUEsZ0JBQWdCLEdBQUcsa0NBQWtDLENBQUM7QUFFdEQsUUFBQSxhQUFhLEdBQ3hCLGcwQ0FBZzBDLENBQUM7QUFFdHpDLFFBQUEsYUFBYSxHQUN4QixnMENBQWcwQyxDQUFDO0FBRW4wQyx3R0FBd0c7QUFDM0YsUUFBQSx3QkFBd0IsR0FBRyxpQkFBaUIsQ0FBQztBQUUxRCx1RkFBdUY7QUFDMUUsUUFBQSxvQkFBb0IsR0FBRyxHQUFHLENBQUM7QUFDM0IsUUFBQSxvQkFBb0IsR0FBRyxHQUFHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZpeHR1cmVzIGZvciByZWFsLXdvcmxkIHYxIGRlY3J5cHQgcGFyaXR5IHRlc3RzLlxuICpcbiAqIFRoZXNlIGNvbWUgZnJvbSBhIHB1cnBvc2UtYnVpbHQgQml0R28gdGVzdCBrZXljYXJkICh3YWxsZXQgbmFtZTogXCJzb2xcIilcbiAqIGNyZWF0ZWQgMjAyNi0wOC0xNCBzb2xlbHkgZm9yIHRoaXMgdGVzdCBzdWl0ZS4gVGhlIHdhbGxldCBpcyBhIHRocm93YXdheVxuICogdGVzdG5ldCBTb2xhbmEgd2FsbGV0IHdpdGggbm8gcmVhbCBmdW5kczsgdGhlIGNpcGhlcnRleHRzLCB3YWxsZXQsIGFuZFxuICogcGFzc3dvcmQgYmVsb3cgYXJlIHNhZmUgdG8gY2hlY2sgaW4uXG4gKlxuICogQm94ZXMgQSArIEIgYXJlIHRoZSB1c2VyIGFuZCBiYWNrdXAgTVBDIGtleSBzaGFyZXMgKHVTaGFyZSksIGVuY3J5cHRlZFxuICogY2xpZW50LXNpZGUgd2l0aCB0aGUgd2FsbGV0IHBhc3N3b3JkIHVzaW5nIHRoZSBleGFjdCBlbnZlbG9wZSBzaGFwZSBCaXRHb1xuICogcHJvZHVjZXMgaW4gcHJvZHVjdGlvbiAoYGl0ZXI9MTAwMDAsIGtzPTI1NiwgdHM9NjQsIG1vZGU9Y2NtLCBjaXBoZXI9YWVzLFxuICogYWRhdGE9XCJcImApLlxuICpcbiAqIFB1cnBvc2U6IGNhdGNoIGFueSByZWdyZXNzaW9uIHdoZXJlIHRoZSBuYXRpdmUvc2hpbSBkZWNyeXB0IHBhdGhzIGRpdmVyZ2VcbiAqIGZyb20gU0pDTCBvbiByZWFsIHByb2R1Y3Rpb24tc2hhcGVkIGVudmVsb3Blcy5cbiAqL1xuXG5leHBvcnQgY29uc3QgS0VZQ0FSRF9QQVNTV09SRCA9ICc5N0lvVjlRczNmdWhCS1lDZzZqdTB5NkxQQkhUeXdCWSc7XG5cbmV4cG9ydCBjb25zdCBLRVlDQVJEX0JPWF9BID1cbiAgJ3tcIml2XCI6XCJpdXJ5K25aaFZmb1dqcHpienJOMVl3PT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiV2lVTXFIbHB4aVE9XCIsXCJjdFwiOlwiUXg2bnIvUStvRWFIbW1zSXE3NWNIY1I0aFI0WHpvd3BKdmRnTnV6Y0dENnYxMTNkaW1UOHRnMkZBV0FHaitzeVJmSDE5WDVjREJoRlg2azNpZldNYnlRSG5lSHMwT0doODZram0vdjRkZE5IYUdnR0V6aHNRQ1dYMnRBT3loeFQrb0c1UGV3blNyK3hGR1plUHZvMEdGYWttUEZMekY5Z2Z2RzhLM28zMGkwaVU1VXl6UGRwNWlBWkdiWlRzZXFwNmQzS1hjbGVBNzEyR252NWVUMG1sRFlKd29pOUlvN1R3Q2pkYWEyTTVyMVBGa044WmFDMWFJemJhM0ErZjdiN1BEcmZGY2tHR0RJbDZvMnl0ak5FcENLdnZiZmlUYms5L1dPSVh0TWliVzFlM3lzbXVQbDV0aXcybFNBdFlYSFFPbDlycXdFdnRvSU10TTJ1WnFBRStFTGY4VWlhYmRCcGRDWUZpU1ZCZ0QrampFZmdVb2NkN3hDUmgyYlcvVXFodTh5ZTdTRGRab3dNYVRJM2Qvc0dXOFF1YnF1UGFIV1FaVGtodkRYdHRUMGwxWVhzSWxkM0wybVFmRHcrRnBGRCtTaWhORGlDZjRmVllIRkkvSTliWU14MDNRblVWK3dYeW8wZGwxUVhua3lWeFRWT2Vhb0o3ZE03VHA3aDVjWTJtNURscDJZdkFZMnR3UnpPU1BLall1OE0rclV1WTBHc2JvZFpXOG1LWENMVmZUeU5tb25TZ3FtTFo3VjhNbFo0b1IyZ0dmUG4zOVhyR0c5ZlJQajNsS2I0Z2FGQ1N3ZUhXZlhBQVhMTitNUDlCcXVFNTdjcGhLbjhSY3V3d0dQbkgwai90S09kY3FLdG4xWGNBS3RmOCtzM0w3dXRJWFMrZGlqQURxVExyamZHLzJnS2U0TmJweWtpVy92T1BRKzJCYlpPN2QwRjBZTW5kMmRpL0tEMlZMNVkzTTZJaWIxelpBUVgxcjQxWDlaYjEvU2hFc0t0RnlPYmkyekcwYXRZclE2ZzQrZjExbkJid0phNkJENm4zUCtVQWFIdklKb1hFRm5hY2N2cTNPV293bEhRcHBRVU9xQ2tkZzVrd2YyZlhKcWtSOWhHR1NCcFhNNDhnbTYxaGd3UjEybjJyRFF4a3M2d3d0ZHRtNUJNS1pySnkyNXgvWkFxWWFRZWptKzBkVDlTVmEwcXBOTk9hMUlkRHpyUG5JMEFMMWFMTkdPVlE5RXdFdDlPT1lvUy9EQlRwN0ptVndoU2hEQzV3OEJyM0tPS3NtNXFsV3ovdXNsaGZXQlI3bDYrQkZmdDJqamZlQ21malpPUkN1aFY1dFg1bm5RWHVjMTNIalFrcmR6YUpFK0xYWll0YWwrVTgzaTJTZmR3Wm5XdXBsVFFxeEtrK0MwaWtmR0dKZDdQRE5iKzhWRW9SM3JFSVhrNFlLSnlJL0h5UEFWd05KTjQ4dG0vMzY0U09tL2lQVit3VzVIdndQRG1SSkJhbjV2czY2cFRUMkd0a1pzWkQxTCtCeE40czh5Y000QldPMXh5amdUSTdtS2pTYXRTbkJxZUowQ20wYklIcThoc2JNOWxIOHljMFZzSlwifSc7XG5cbmV4cG9ydCBjb25zdCBLRVlDQVJEX0JPWF9CID1cbiAgJ3tcIml2XCI6XCJRWnc4Wm1IcWFCcVFoNlg2UFNDY01nPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwieU0rQm9TeVZ3YVk9XCIsXCJjdFwiOlwib1B0Y3ZXWWYyODdJUmk5VG8vVW9iVExybTVtK1lDczZUcDFDdVl2UEo1b2F6VGNibXpaa1MrZ24yaHhBR0N2b2pHR1Y2MXFpZUVncktFS0RkS0xFNC9qU1dVaFkvVlh5RkU2QlJiMnVCNXBGbnk4TndTc1ZiNUd3NVIzOGJnczBYWjBhTDRSQ0VRZ0J5SWtXR0tKbjNaYnBmbXpGY0QreDIyNldaa0wwZ1MxRE41Uks4YndBZmdyYWJWcDZNdXBMYS9OTjdNL1lpSDlhTzlQRUxkdnUvbWJ5QzB6ZEF3d1k4TUhwTWRmNUlQT0ppM2llTW9yVXRFc3V6ZlA0U0JJMkVBSGRGaTMvVm16SUtHNjlzWlMxdUlVTEhCNVh5YTV1cnk3K3FwNm5paGx4Sk9CNFM4enByaS9yWG93KzBFUUwyYktVU2tRejZyNkdUTDVNY2x5Zmt4VmNDcHRWTVByQ2NzRGRWYzlQMHNSMzZpUC9Bc2RDVEpHdUhienYwQUVSczc3NitjVXlxaXZsUWoxQ1EzR2tJSE5RS3lZamt0S0x4MVBtRU1UbzI5aEVFYktWYXZNOFpveFRiakwvdUlheHB6OURpMXpoM1JCOGYxSFhtcTJKRDJYRUFQQWt5K1VraDhGU2F2Uk9HNjRHUmtQSlk0QXRVeFh2dnpVYzJNOVFDeTZ3YkRJQzhwckpFaW81ald5S1pTWjRLVnBNU0VLOTgvaHRNamdCOGhIMDdDZGZpSm52TVZ5N3hlOWhIT3RsM3pUaE1QNnIrOWc4V3BHZFQwMlkya1dXT1ZabGhCYVBvaHVpQ2lKTEhPaWdpTjg2VHQ3aTVrZ1NUQjZ3OHpUNHRjWld6U2VPQmg2OGVBdXBEdDBxT2RmYWRORVNRSUNKM2ZBZ2ZRZmVSN3BQemp0NTRucEI3YzlLcExuSmdEaHJsNExwd2ljd1p3dVlLdjBnSjd0OUtLS1RMRkhScDVSRDVOcis4dGsxMGFJeERReExXQ1ZTd2FsaWU1SGhUelBzRjhPVXFOckpKOW1TQkd0c1RoL1NhZjVvc3ZFL0VUWWRVN1BUSnBWSERZQ1M1L0RhQ3JWN2FjWm4xWkJ6Q0Q5UDlGenR0ekY4Umx3UE9pZGVFc1lEV0xPUnZ3ZG1OSFlnVGF2Tm5PWTRVbklTZ0EwN1V0RnNnemdKNGdDNHViQ0UzMkM1TU5rWDRoR0lpLzE1TzRZMFphaUFlT3UyUW5tOXI2emZkWVpQNFRDZVFBWkVHS3k1RHNPK1ZZT0xJbXZoUlpEOGFPb0Z2eG1RSldNNU1FTW96RUltbXM4Y3dKdURSUDYwV2hacVVDZ2VtbW15SEhEUlBHMytFbVVHVTJXNFFXRFF0N0c2dUFEY0RDRnNZb2p5c2hnMCs2UVJNZGM1cExSM3dVYTRNUnVnN3Q0OWtpdDBRL3lGTW44a0huNi9qaG9rUmRJSHQ4WXZvMS93bkdtdzdhR3ZLWDNydFVLT3BxWjRBa09ha2hLdXFSSnlKdmgzbnNmejZCWHRqeDBVblc4MER0OFdnQW9sK3gwSUZMY2JjbndqSUNvdFU5dXVwZm4rT05HSzBDNE5VU2lKVmc9PVwifSc7XG5cbi8qKiBQcmVmaXggb2YgdGhlIGRlY3J5cHRlZCBwbGFpbnRleHQgZm9yIHN0cnVjdHVyYWwgc2FuaXR5IGNoZWNraW5nLiBCb3RoIGJveGVzIGFyZSBNUEMgdVNoYXJlIEpTT04uICovXG5leHBvcnQgY29uc3QgS0VZQ0FSRF9QTEFJTlRFWFRfUFJFRklYID0gJ3tcInVTaGFyZVwiOntcImlcIjonO1xuXG4vKiogRXhwZWN0ZWQgcGxhaW50ZXh0IGxlbmd0aHMsIHZlcmlmaWVkIGFnYWluc3Qgc2pjbC5kZWNyeXB0IGR1cmluZyB0ZXN0IGF1dGhvcmluZy4gKi9cbmV4cG9ydCBjb25zdCBLRVlDQVJEX0JPWF9BX0xFTkdUSCA9IDg5NTtcbmV4cG9ydCBjb25zdCBLRVlDQVJEX0JPWF9CX0xFTkdUSCA9IDg5MztcbiJdfQ==
|