@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.
@@ -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==