@bitgo-beta/sdk-core 8.2.1-beta.2088 → 8.2.1-beta.2089
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/src/bitgo/errors.d.ts +2 -1
- package/dist/src/bitgo/errors.d.ts.map +1 -1
- package/dist/src/bitgo/errors.js +3 -2
- package/dist/src/bitgo/safe/index.d.ts +1 -0
- package/dist/src/bitgo/safe/index.d.ts.map +1 -1
- package/dist/src/bitgo/safe/index.js +2 -1
- package/dist/src/bitgo/safe/recovery.d.ts +82 -0
- package/dist/src/bitgo/safe/recovery.d.ts.map +1 -0
- package/dist/src/bitgo/safe/recovery.js +133 -0
- package/dist/test/unit/bitgo/recovery/initiate.js +1 -30
- package/dist/test/unit/bitgo/safe/recovery.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/recovery.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/recovery.js +253 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,253 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
require("should");
|
|
37
|
+
const sinon = __importStar(require("sinon"));
|
|
38
|
+
const utxo_lib_1 = require("@bitgo-beta/utxo-lib");
|
|
39
|
+
const keyShareEnvelope_1 = require("../../../../src/bitgo/utils/tss/keyShareEnvelope");
|
|
40
|
+
const errors_1 = require("../../../../src/bitgo/errors");
|
|
41
|
+
const recovery_1 = require("../../../../src/bitgo/safe/recovery");
|
|
42
|
+
const PASSWORD = 'safe-password';
|
|
43
|
+
function makeMockBitGo(decryptImpl) {
|
|
44
|
+
return {
|
|
45
|
+
decrypt: sinon.stub().callsFake(async (params) => decryptImpl(params)),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** A fake decrypt that only recognizes the user/backup tokens; any other input (e.g. a Box C public) throws. */
|
|
49
|
+
function makeDecryptMap(entries) {
|
|
50
|
+
return ({ password, input }) => {
|
|
51
|
+
password.should.equal(PASSWORD);
|
|
52
|
+
if (!(input in entries)) {
|
|
53
|
+
throw new Error(`unexpected decrypt input: ${input}`);
|
|
54
|
+
}
|
|
55
|
+
return entries[input];
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function box(values) {
|
|
59
|
+
return JSON.stringify(values);
|
|
60
|
+
}
|
|
61
|
+
describe('decryptSafeKeycard', () => {
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
sinon.restore();
|
|
64
|
+
});
|
|
65
|
+
it('decrypts onchain roots to strings and returns Box C verbatim', async () => {
|
|
66
|
+
const userBox = box({
|
|
67
|
+
secp256k1Multisig: 'enc-user-secp',
|
|
68
|
+
ed25519Multisig: 'enc-user-ed25519',
|
|
69
|
+
ecdsaMpc: 'enc-user-ecdsa',
|
|
70
|
+
eddsaMpc: 'enc-user-eddsa',
|
|
71
|
+
});
|
|
72
|
+
const backupBox = box({
|
|
73
|
+
secp256k1Multisig: 'enc-backup-secp',
|
|
74
|
+
ed25519Multisig: 'enc-backup-ed25519',
|
|
75
|
+
ecdsaMpc: 'enc-backup-ecdsa',
|
|
76
|
+
eddsaMpc: 'enc-backup-eddsa',
|
|
77
|
+
});
|
|
78
|
+
const bitgoBox = box({
|
|
79
|
+
secp256k1Multisig: 'xpub-secp-bitgo',
|
|
80
|
+
ed25519Multisig: 'pub-ed25519-bitgo',
|
|
81
|
+
ecdsaMpc: 'common-ecdsa-bitgo',
|
|
82
|
+
eddsaMpc: 'common-eddsa-bitgo',
|
|
83
|
+
});
|
|
84
|
+
const mpcUser = (0, keyShareEnvelope_1.buildSafeMpcKeyEnvelopes)(Buffer.from('user-signing'), Buffer.from('user-reduced'), Buffer.from('user-vrf'));
|
|
85
|
+
const mpcBackup = (0, keyShareEnvelope_1.buildSafeMpcKeyEnvelopes)(Buffer.from('backup-signing'), Buffer.from('backup-reduced'), Buffer.from('backup-vrf'));
|
|
86
|
+
const bitgo = makeMockBitGo(makeDecryptMap({
|
|
87
|
+
'enc-user-secp': 'xprv-user',
|
|
88
|
+
'enc-backup-secp': 'xprv-backup',
|
|
89
|
+
'enc-user-ed25519': 'S-user-seed',
|
|
90
|
+
'enc-backup-ed25519': 'S-backup-seed',
|
|
91
|
+
'enc-user-ecdsa': mpcUser.reducedEnvelope.toString('base64'),
|
|
92
|
+
'enc-backup-ecdsa': mpcBackup.reducedEnvelope.toString('base64'),
|
|
93
|
+
'enc-user-eddsa': mpcUser.reducedEnvelope.toString('base64'),
|
|
94
|
+
'enc-backup-eddsa': mpcBackup.reducedEnvelope.toString('base64'),
|
|
95
|
+
}));
|
|
96
|
+
const result = await (0, recovery_1.decryptSafeKeycard)({
|
|
97
|
+
bitgo,
|
|
98
|
+
userKeyBox: userBox,
|
|
99
|
+
backupKeyBox: backupBox,
|
|
100
|
+
bitgoKeyBox: bitgoBox,
|
|
101
|
+
password: PASSWORD,
|
|
102
|
+
});
|
|
103
|
+
result.secp256k1Multisig.user.should.equal('xprv-user');
|
|
104
|
+
result.secp256k1Multisig.backup.should.equal('xprv-backup');
|
|
105
|
+
result.secp256k1Multisig.bitgo.should.equal('xpub-secp-bitgo');
|
|
106
|
+
result.ed25519Multisig.user.should.equal('S-user-seed');
|
|
107
|
+
result.ed25519Multisig.backup.should.equal('S-backup-seed');
|
|
108
|
+
result.ed25519Multisig.bitgo.should.equal('pub-ed25519-bitgo');
|
|
109
|
+
result.ecdsaMpc.user.signing.toString('hex').should.equal(Buffer.from('user-reduced').toString('hex'));
|
|
110
|
+
result.ecdsaMpc.user.vrf.toString('hex').should.equal(Buffer.from('user-vrf').toString('hex'));
|
|
111
|
+
result.ecdsaMpc.backup.signing.toString('hex').should.equal(Buffer.from('backup-reduced').toString('hex'));
|
|
112
|
+
result.ecdsaMpc.backup.vrf.toString('hex').should.equal(Buffer.from('backup-vrf').toString('hex'));
|
|
113
|
+
result.ecdsaMpc.bitgo.should.equal('common-ecdsa-bitgo');
|
|
114
|
+
result.eddsaMpc.bitgo.should.equal('common-eddsa-bitgo');
|
|
115
|
+
// 4 slots × (user + backup) = 8 decrypts; BitGo (Box C) is never decrypted.
|
|
116
|
+
bitgo.decrypt.callCount.should.equal(8);
|
|
117
|
+
});
|
|
118
|
+
it('throws IncorrectPasswordError when decryption fails (wrong password)', async () => {
|
|
119
|
+
const userBox = box({
|
|
120
|
+
secp256k1Multisig: 'enc-user-secp',
|
|
121
|
+
ed25519Multisig: 'enc-user-ed25519',
|
|
122
|
+
ecdsaMpc: 'enc-user-ecdsa',
|
|
123
|
+
eddsaMpc: 'enc-user-eddsa',
|
|
124
|
+
});
|
|
125
|
+
const bitgo = makeMockBitGo(() => {
|
|
126
|
+
throw new Error('argon2: tag does not match');
|
|
127
|
+
});
|
|
128
|
+
await (0, recovery_1.decryptSafeKeycard)({
|
|
129
|
+
bitgo,
|
|
130
|
+
userKeyBox: userBox,
|
|
131
|
+
backupKeyBox: userBox,
|
|
132
|
+
bitgoKeyBox: userBox,
|
|
133
|
+
password: 'wrong-password',
|
|
134
|
+
}).should.be.rejectedWith(errors_1.IncorrectPasswordError);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
const MPC_ROOT = { signing: Buffer.alloc(0), vrf: Buffer.alloc(0) };
|
|
138
|
+
function makeRoots(secp) {
|
|
139
|
+
return {
|
|
140
|
+
secp256k1Multisig: secp,
|
|
141
|
+
ed25519Multisig: { user: 'u', backup: 'b', bitgo: 'g' },
|
|
142
|
+
ecdsaMpc: { user: MPC_ROOT, backup: MPC_ROOT, bitgo: 'g' },
|
|
143
|
+
eddsaMpc: { user: MPC_ROOT, backup: MPC_ROOT, bitgo: 'g' },
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
describe('deriveSafeWalletKeys', () => {
|
|
147
|
+
const userRoot = utxo_lib_1.bip32.fromSeed(Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex'));
|
|
148
|
+
const backupRoot = utxo_lib_1.bip32.fromSeed(Buffer.from('1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100', 'hex'));
|
|
149
|
+
const bitgoRoot = utxo_lib_1.bip32
|
|
150
|
+
.fromSeed(Buffer.from('2f2e2d2c2b2a292827262524232221201f1e1d1c1b1a19181716151413121110', 'hex'))
|
|
151
|
+
.neutered();
|
|
152
|
+
const roots = makeRoots({
|
|
153
|
+
user: userRoot.toBase58(),
|
|
154
|
+
backup: backupRoot.toBase58(),
|
|
155
|
+
bitgo: bitgoRoot.toBase58(),
|
|
156
|
+
});
|
|
157
|
+
it('derives the BIP44 child triplet for slot 1', async () => {
|
|
158
|
+
const result = await (0, recovery_1.deriveSafeWalletKeys)({ coin: 'btc', slot: 'secp256k1Multisig', account: 0, roots });
|
|
159
|
+
result.path.should.equal("m/44'/0'/1'/0'");
|
|
160
|
+
result.keys.user.prv.should.equal(userRoot.derivePath("m/44'/0'/1'/0'").toBase58());
|
|
161
|
+
result.keys.user.pub.should.equal(userRoot.derivePath("m/44'/0'/1'/0'").neutered().toBase58());
|
|
162
|
+
result.keys.backup.prv.should.equal(backupRoot.derivePath('m/44/0/1/0').toBase58());
|
|
163
|
+
result.keys.bitgo.pub.should.equal(bitgoRoot.derivePath('m/44/0/1/0').toBase58());
|
|
164
|
+
});
|
|
165
|
+
it('varies the path with the account', async () => {
|
|
166
|
+
const result = await (0, recovery_1.deriveSafeWalletKeys)({ coin: 'btc', slot: 'secp256k1Multisig', account: 2, roots });
|
|
167
|
+
result.path.should.equal("m/44'/0'/1'/2'");
|
|
168
|
+
});
|
|
169
|
+
it('rejects unsupported slots', async () => {
|
|
170
|
+
await (0, recovery_1.deriveSafeWalletKeys)({ coin: 'btc', slot: 'eddsaMpc', account: 0, roots }).should.be.rejectedWith(/not supported yet/);
|
|
171
|
+
});
|
|
172
|
+
it('rejects a non-integer account', async () => {
|
|
173
|
+
await (0, recovery_1.deriveSafeWalletKeys)({ coin: 'btc', slot: 'secp256k1Multisig', account: 1.5, roots }).should.be.rejectedWith(/invalid account/);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('buildSafeRecoverKeyParams', () => {
|
|
177
|
+
afterEach(() => {
|
|
178
|
+
sinon.restore();
|
|
179
|
+
});
|
|
180
|
+
const userRoot = utxo_lib_1.bip32.fromSeed(Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex'));
|
|
181
|
+
const backupRoot = utxo_lib_1.bip32.fromSeed(Buffer.from('1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100', 'hex'));
|
|
182
|
+
const bitgoRoot = utxo_lib_1.bip32
|
|
183
|
+
.fromSeed(Buffer.from('2f2e2d2c2b2a292827262524232221201f1e1d1c1b1a19181716151413121110', 'hex'))
|
|
184
|
+
.neutered();
|
|
185
|
+
const keys = {
|
|
186
|
+
user: { prv: userRoot.toBase58(), pub: userRoot.neutered().toBase58() },
|
|
187
|
+
backup: { prv: backupRoot.toBase58(), pub: backupRoot.neutered().toBase58() },
|
|
188
|
+
bitgo: { pub: bitgoRoot.toBase58() },
|
|
189
|
+
};
|
|
190
|
+
it('signed mode re-encrypts child xprvs under a single ephemeral passphrase', async () => {
|
|
191
|
+
const passphrases = [];
|
|
192
|
+
const encrypt = sinon.stub().callsFake(async ({ input, password, encryptionVersion }) => {
|
|
193
|
+
passphrases.push(password);
|
|
194
|
+
encryptionVersion.should.equal(1);
|
|
195
|
+
return `enc(${input})`;
|
|
196
|
+
});
|
|
197
|
+
const bitgo = { encrypt };
|
|
198
|
+
const result = await (0, recovery_1.buildSafeRecoverKeyParams)({
|
|
199
|
+
bitgo,
|
|
200
|
+
coin: 'btc',
|
|
201
|
+
slot: 'secp256k1Multisig',
|
|
202
|
+
keys,
|
|
203
|
+
mode: 'signed',
|
|
204
|
+
});
|
|
205
|
+
result.userKey.should.equal(`enc(${keys.user.prv})`);
|
|
206
|
+
result.backupKey.should.equal(`enc(${keys.backup.prv})`);
|
|
207
|
+
result.bitgoKey.should.equal(keys.bitgo.pub);
|
|
208
|
+
result.walletPassphrase.should.be.a.String();
|
|
209
|
+
passphrases.should.have.length(2);
|
|
210
|
+
passphrases[0].should.equal(passphrases[1]);
|
|
211
|
+
passphrases[0].should.equal(result.walletPassphrase);
|
|
212
|
+
encrypt.callCount.should.equal(2);
|
|
213
|
+
});
|
|
214
|
+
it('rejects non-private child keys in signed mode', async () => {
|
|
215
|
+
const bitgo = { encrypt: sinon.stub() };
|
|
216
|
+
await (0, recovery_1.buildSafeRecoverKeyParams)({
|
|
217
|
+
bitgo,
|
|
218
|
+
coin: 'btc',
|
|
219
|
+
slot: 'secp256k1Multisig',
|
|
220
|
+
keys: { user: { prv: keys.user.pub, pub: keys.user.pub }, backup: keys.backup, bitgo: keys.bitgo },
|
|
221
|
+
mode: 'signed',
|
|
222
|
+
}).should.be.rejectedWith(/must be private xprvs/);
|
|
223
|
+
});
|
|
224
|
+
it('unsigned mode returns pubs and never encrypts', async () => {
|
|
225
|
+
const encrypt = sinon.stub().callsFake(async () => {
|
|
226
|
+
throw new Error('encrypt should not be called');
|
|
227
|
+
});
|
|
228
|
+
const bitgo = { encrypt };
|
|
229
|
+
const result = await (0, recovery_1.buildSafeRecoverKeyParams)({
|
|
230
|
+
bitgo,
|
|
231
|
+
coin: 'btc',
|
|
232
|
+
slot: 'secp256k1Multisig',
|
|
233
|
+
keys,
|
|
234
|
+
mode: 'unsigned',
|
|
235
|
+
});
|
|
236
|
+
result.userKey.should.equal(keys.user.pub);
|
|
237
|
+
result.backupKey.should.equal(keys.backup.pub);
|
|
238
|
+
result.bitgoKey.should.equal(keys.bitgo.pub);
|
|
239
|
+
result.should.not.have.property('walletPassphrase');
|
|
240
|
+
encrypt.callCount.should.equal(0);
|
|
241
|
+
});
|
|
242
|
+
it('rejects unsupported slots', async () => {
|
|
243
|
+
const bitgo = { encrypt: sinon.stub() };
|
|
244
|
+
await (0, recovery_1.buildSafeRecoverKeyParams)({
|
|
245
|
+
bitgo,
|
|
246
|
+
coin: 'btc',
|
|
247
|
+
slot: 'eddsaMpc',
|
|
248
|
+
keys,
|
|
249
|
+
mode: 'signed',
|
|
250
|
+
}).should.be.rejectedWith(/not supported yet/);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3ZlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZXN0L3VuaXQvYml0Z28vc2FmZS9yZWNvdmVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGtCQUFnQjtBQUNoQiw2Q0FBK0I7QUFDL0IsbURBQTZDO0FBQzdDLHVGQUE0RjtBQUM1Rix5REFBc0U7QUFDdEUsa0VBSzZDO0FBRzdDLE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQztBQUVqQyxTQUFTLGFBQWEsQ0FBQyxXQUFvRTtJQUN6RixPQUFPO1FBQ0wsT0FBTyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLE1BQTJDLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztLQUNwRixDQUFDO0FBQzVCLENBQUM7QUFFRCxnSEFBZ0g7QUFDaEgsU0FBUyxjQUFjLENBQUMsT0FBK0I7SUFDckQsT0FBTyxDQUFDLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUU7UUFDN0IsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQ0QsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEIsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsR0FBRyxDQUFDLE1BS1o7SUFDQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDaEMsQ0FBQztBQUVELFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7SUFDbEMsU0FBUyxDQUFDLEdBQUcs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O0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgJ3Nob3VsZCc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgeyBiaXAzMiB9IGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tbGliJztcbmltcG9ydCB7IGJ1aWxkU2FmZU1wY0tleUVudmVsb3BlcyB9IGZyb20gJy4uLy4uLy4uLy4uL3NyYy9iaXRnby91dGlscy90c3Mva2V5U2hhcmVFbnZlbG9wZSc7XG5pbXBvcnQgeyBJbmNvcnJlY3RQYXNzd29yZEVycm9yIH0gZnJvbSAnLi4vLi4vLi4vLi4vc3JjL2JpdGdvL2Vycm9ycyc7XG5pbXBvcnQge1xuICBEZWNyeXB0ZWRTYWZlUm9vdHMsXG4gIGJ1aWxkU2FmZVJlY292ZXJLZXlQYXJhbXMsXG4gIGRlY3J5cHRTYWZlS2V5Y2FyZCxcbiAgZGVyaXZlU2FmZVdhbGxldEtleXMsXG59IGZyb20gJy4uLy4uLy4uLy4uL3NyYy9iaXRnby9zYWZlL3JlY292ZXJ5JztcbmltcG9ydCB7IEJpdEdvQmFzZSB9IGZyb20gJy4uLy4uLy4uLy4uL3NyYy9iaXRnby9iaXRnb0Jhc2UnO1xuXG5jb25zdCBQQVNTV09SRCA9ICdzYWZlLXBhc3N3b3JkJztcblxuZnVuY3Rpb24gbWFrZU1vY2tCaXRHbyhkZWNyeXB0SW1wbDogKHBhcmFtczogeyBwYXNzd29yZDogc3RyaW5nOyBpbnB1dDogc3RyaW5nIH0pID0+IHN0cmluZyk6IEJpdEdvQmFzZSB7XG4gIHJldHVybiB7XG4gICAgZGVjcnlwdDogc2lub24uc3R1YigpLmNhbGxzRmFrZShhc3luYyAocGFyYW1zOiB7IHBhc3N3b3JkOiBzdHJpbmc7IGlucHV0OiBzdHJpbmcgfSkgPT4gZGVjcnlwdEltcGwocGFyYW1zKSksXG4gIH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2U7XG59XG5cbi8qKiBBIGZha2UgZGVjcnlwdCB0aGF0IG9ubHkgcmVjb2duaXplcyB0aGUgdXNlci9iYWNrdXAgdG9rZW5zOyBhbnkgb3RoZXIgaW5wdXQgKGUuZy4gYSBCb3ggQyBwdWJsaWMpIHRocm93cy4gKi9cbmZ1bmN0aW9uIG1ha2VEZWNyeXB0TWFwKGVudHJpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiAocGFyYW1zOiB7IHBhc3N3b3JkOiBzdHJpbmc7IGlucHV0OiBzdHJpbmcgfSkgPT4gc3RyaW5nIHtcbiAgcmV0dXJuICh7IHBhc3N3b3JkLCBpbnB1dCB9KSA9PiB7XG4gICAgcGFzc3dvcmQuc2hvdWxkLmVxdWFsKFBBU1NXT1JEKTtcbiAgICBpZiAoIShpbnB1dCBpbiBlbnRyaWVzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmV4cGVjdGVkIGRlY3J5cHQgaW5wdXQ6ICR7aW5wdXR9YCk7XG4gICAgfVxuICAgIHJldHVybiBlbnRyaWVzW2lucHV0XTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYm94KHZhbHVlczoge1xuICBzZWNwMjU2azFNdWx0aXNpZzogc3RyaW5nO1xuICBlZDI1NTE5TXVsdGlzaWc6IHN0cmluZztcbiAgZWNkc2FNcGM6IHN0cmluZztcbiAgZWRkc2FNcGM6IHN0cmluZztcbn0pOiBzdHJpbmcge1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWVzKTtcbn1cblxuZGVzY3JpYmUoJ2RlY3J5cHRTYWZlS2V5Y2FyZCcsICgpID0+IHtcbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGl0KCdkZWNyeXB0cyBvbmNoYWluIHJvb3RzIHRvIHN0cmluZ3MgYW5kIHJldHVybnMgQm94IEMgdmVyYmF0aW0nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdXNlckJveCA9IGJveCh7XG4gICAgICBzZWNwMjU2azFNdWx0aXNpZzogJ2VuYy11c2VyLXNlY3AnLFxuICAgICAgZWQyNTUxOU11bHRpc2lnOiAnZW5jLXVzZXItZWQyNTUxOScsXG4gICAgICBlY2RzYU1wYzogJ2VuYy11c2VyLWVjZHNhJyxcbiAgICAgIGVkZHNhTXBjOiAnZW5jLXVzZXItZWRkc2EnLFxuICAgIH0pO1xuICAgIGNvbnN0IGJhY2t1cEJveCA9IGJveCh7XG4gICAgICBzZWNwMjU2azFNdWx0aXNpZzogJ2VuYy1iYWNrdXAtc2VjcCcsXG4gICAgICBlZDI1NTE5TXVsdGlzaWc6ICdlbmMtYmFja3VwLWVkMjU1MTknLFxuICAgICAgZWNkc2FNcGM6ICdlbmMtYmFja3VwLWVjZHNhJyxcbiAgICAgIGVkZHNhTXBjOiAnZW5jLWJhY2t1cC1lZGRzYScsXG4gICAgfSk7XG4gICAgY29uc3QgYml0Z29Cb3ggPSBib3goe1xuICAgICAgc2VjcDI1NmsxTXVsdGlzaWc6ICd4cHViLXNlY3AtYml0Z28nLFxuICAgICAgZWQyNTUxOU11bHRpc2lnOiAncHViLWVkMjU1MTktYml0Z28nLFxuICAgICAgZWNkc2FNcGM6ICdjb21tb24tZWNkc2EtYml0Z28nLFxuICAgICAgZWRkc2FNcGM6ICdjb21tb24tZWRkc2EtYml0Z28nLFxuICAgIH0pO1xuXG4gICAgY29uc3QgbXBjVXNlciA9IGJ1aWxkU2FmZU1wY0tleUVudmVsb3BlcyhcbiAgICAgIEJ1ZmZlci5mcm9tKCd1c2VyLXNpZ25pbmcnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKCd1c2VyLXJlZHVjZWQnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKCd1c2VyLXZyZicpXG4gICAgKTtcbiAgICBjb25zdCBtcGNCYWNrdXAgPSBidWlsZFNhZmVNcGNLZXlFbnZlbG9wZXMoXG4gICAgICBCdWZmZXIuZnJvbSgnYmFja3VwLXNpZ25pbmcnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKCdiYWNrdXAtcmVkdWNlZCcpLFxuICAgICAgQnVmZmVyLmZyb20oJ2JhY2t1cC12cmYnKVxuICAgICk7XG5cbiAgICBjb25zdCBiaXRnbyA9IG1ha2VNb2NrQml0R28oXG4gICAgICBtYWtlRGVjcnlwdE1hcCh7XG4gICAgICAgICdlbmMtdXNlci1zZWNwJzogJ3hwcnYtdXNlcicsXG4gICAgICAgICdlbmMtYmFja3VwLXNlY3AnOiAneHBydi1iYWNrdXAnLFxuICAgICAgICAnZW5jLXVzZXItZWQyNTUxOSc6ICdTLXVzZXItc2VlZCcsXG4gICAgICAgICdlbmMtYmFja3VwLWVkMjU1MTknOiAnUy1iYWNrdXAtc2VlZCcsXG4gICAgICAgICdlbmMtdXNlci1lY2RzYSc6IG1wY1VzZXIucmVkdWNlZEVudmVsb3BlLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgJ2VuYy1iYWNrdXAtZWNkc2EnOiBtcGNCYWNrdXAucmVkdWNlZEVudmVsb3BlLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgJ2VuYy11c2VyLWVkZHNhJzogbXBjVXNlci5yZWR1Y2VkRW52ZWxvcGUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgICAnZW5jLWJhY2t1cC1lZGRzYSc6IG1wY0JhY2t1cC5yZWR1Y2VkRW52ZWxvcGUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGVjcnlwdFNhZmVLZXljYXJkKHtcbiAgICAgIGJpdGdvLFxuICAgICAgdXNlcktleUJveDogdXNlckJveCxcbiAgICAgIGJhY2t1cEtleUJveDogYmFja3VwQm94LFxuICAgICAgYml0Z29LZXlCb3g6IGJpdGdvQm94LFxuICAgICAgcGFzc3dvcmQ6IFBBU1NXT1JELFxuICAgIH0pO1xuXG4gICAgcmVzdWx0LnNlY3AyNTZrMU11bHRpc2lnLnVzZXIuc2hvdWxkLmVxdWFsKCd4cHJ2LXVzZXInKTtcbiAgICByZXN1bHQuc2VjcDI1NmsxTXVsdGlzaWcuYmFja3VwLnNob3VsZC5lcXVhbCgneHBydi1iYWNrdXAnKTtcbiAgICByZXN1bHQuc2VjcDI1NmsxTXVsdGlzaWcuYml0Z28uc2hvdWxkLmVxdWFsKCd4cHViLXNlY3AtYml0Z28nKTtcblxuICAgIHJlc3VsdC5lZDI1NTE5TXVsdGlzaWcudXNlci5zaG91bGQuZXF1YWwoJ1MtdXNlci1zZWVkJyk7XG4gICAgcmVzdWx0LmVkMjU1MTlNdWx0aXNpZy5iYWNrdXAuc2hvdWxkLmVxdWFsKCdTLWJhY2t1cC1zZWVkJyk7XG4gICAgcmVzdWx0LmVkMjU1MTlNdWx0aXNpZy5iaXRnby5zaG91bGQuZXF1YWwoJ3B1Yi1lZDI1NTE5LWJpdGdvJyk7XG5cbiAgICByZXN1bHQuZWNkc2FNcGMudXNlci5zaWduaW5nLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZXF1YWwoQnVmZmVyLmZyb20oJ3VzZXItcmVkdWNlZCcpLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgcmVzdWx0LmVjZHNhTXBjLnVzZXIudnJmLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZXF1YWwoQnVmZmVyLmZyb20oJ3VzZXItdnJmJykudG9TdHJpbmcoJ2hleCcpKTtcbiAgICByZXN1bHQuZWNkc2FNcGMuYmFja3VwLnNpZ25pbmcudG9TdHJpbmcoJ2hleCcpLnNob3VsZC5lcXVhbChCdWZmZXIuZnJvbSgnYmFja3VwLXJlZHVjZWQnKS50b1N0cmluZygnaGV4JykpO1xuICAgIHJlc3VsdC5lY2RzYU1wYy5iYWNrdXAudnJmLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZXF1YWwoQnVmZmVyLmZyb20oJ2JhY2t1cC12cmYnKS50b1N0cmluZygnaGV4JykpO1xuICAgIHJlc3VsdC5lY2RzYU1wYy5iaXRnby5zaG91bGQuZXF1YWwoJ2NvbW1vbi1lY2RzYS1iaXRnbycpO1xuXG4gICAgcmVzdWx0LmVkZHNhTXBjLmJpdGdvLnNob3VsZC5lcXVhbCgnY29tbW9uLWVkZHNhLWJpdGdvJyk7XG5cbiAgICAvLyA0IHNsb3RzIMOXICh1c2VyICsgYmFja3VwKSA9IDggZGVjcnlwdHM7IEJpdEdvIChCb3ggQykgaXMgbmV2ZXIgZGVjcnlwdGVkLlxuICAgIChiaXRnby5kZWNyeXB0IGFzIHNpbm9uLlNpbm9uU3R1YikuY2FsbENvdW50LnNob3VsZC5lcXVhbCg4KTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyBJbmNvcnJlY3RQYXNzd29yZEVycm9yIHdoZW4gZGVjcnlwdGlvbiBmYWlscyAod3JvbmcgcGFzc3dvcmQpJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHVzZXJCb3ggPSBib3goe1xuICAgICAgc2VjcDI1NmsxTXVsdGlzaWc6ICdlbmMtdXNlci1zZWNwJyxcbiAgICAgIGVkMjU1MTlNdWx0aXNpZzogJ2VuYy11c2VyLWVkMjU1MTknLFxuICAgICAgZWNkc2FNcGM6ICdlbmMtdXNlci1lY2RzYScsXG4gICAgICBlZGRzYU1wYzogJ2VuYy11c2VyLWVkZHNhJyxcbiAgICB9KTtcbiAgICBjb25zdCBiaXRnbyA9IG1ha2VNb2NrQml0R28oKCkgPT4ge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdhcmdvbjI6IHRhZyBkb2VzIG5vdCBtYXRjaCcpO1xuICAgIH0pO1xuXG4gICAgYXdhaXQgZGVjcnlwdFNhZmVLZXljYXJkKHtcbiAgICAgIGJpdGdvLFxuICAgICAgdXNlcktleUJveDogdXNlckJveCxcbiAgICAgIGJhY2t1cEtleUJveDogdXNlckJveCxcbiAgICAgIGJpdGdvS2V5Qm94OiB1c2VyQm94LFxuICAgICAgcGFzc3dvcmQ6ICd3cm9uZy1wYXNzd29yZCcsXG4gICAgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChJbmNvcnJlY3RQYXNzd29yZEVycm9yKTtcbiAgfSk7XG59KTtcblxuY29uc3QgTVBDX1JPT1QgPSB7IHNpZ25pbmc6IEJ1ZmZlci5hbGxvYygwKSwgdnJmOiBCdWZmZXIuYWxsb2MoMCkgfTtcblxuZnVuY3Rpb24gbWFrZVJvb3RzKHNlY3A6IHsgdXNlcjogc3RyaW5nOyBiYWNrdXA6IHN0cmluZzsgYml0Z286IHN0cmluZyB9KTogRGVjcnlwdGVkU2FmZVJvb3RzIHtcbiAgcmV0dXJuIHtcbiAgICBzZWNwMjU2azFNdWx0aXNpZzogc2VjcCxcbiAgICBlZDI1NTE5TXVsdGlzaWc6IHsgdXNlcjogJ3UnLCBiYWNrdXA6ICdiJywgYml0Z286ICdnJyB9LFxuICAgIGVjZHNhTXBjOiB7IHVzZXI6IE1QQ19ST09ULCBiYWNrdXA6IE1QQ19ST09ULCBiaXRnbzogJ2cnIH0sXG4gICAgZWRkc2FNcGM6IHsgdXNlcjogTVBDX1JPT1QsIGJhY2t1cDogTVBDX1JPT1QsIGJpdGdvOiAnZycgfSxcbiAgfTtcbn1cblxuZGVzY3JpYmUoJ2Rlcml2ZVNhZmVXYWxsZXRLZXlzJywgKCkgPT4ge1xuICBjb25zdCB1c2VyUm9vdCA9IGJpcDMyLmZyb21TZWVkKEJ1ZmZlci5mcm9tKCcwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZicsICdoZXgnKSk7XG4gIGNvbnN0IGJhY2t1cFJvb3QgPSBiaXAzMi5mcm9tU2VlZChcbiAgICBCdWZmZXIuZnJvbSgnMWYxZTFkMWMxYjFhMTkxODE3MTYxNTE0MTMxMjExMTAwZjBlMGQwYzBiMGEwOTA4MDcwNjA1MDQwMzAyMDEwMCcsICdoZXgnKVxuICApO1xuICBjb25zdCBiaXRnb1Jvb3QgPSBiaXAzMlxuICAgIC5mcm9tU2VlZChCdWZmZXIuZnJvbSgnMmYyZTJkMmMyYjJhMjkyODI3MjYyNTI0MjMyMjIxMjAxZjFlMWQxYzFiMWExOTE4MTcxNjE1MTQxMzEyMTExMCcsICdoZXgnKSlcbiAgICAubmV1dGVyZWQoKTtcblxuICBjb25zdCByb290cyA9IG1ha2VSb290cyh7XG4gICAgdXNlcjogdXNlclJvb3QudG9CYXNlNTgoKSxcbiAgICBiYWNrdXA6IGJhY2t1cFJvb3QudG9CYXNlNTgoKSxcbiAgICBiaXRnbzogYml0Z29Sb290LnRvQmFzZTU4KCksXG4gIH0pO1xuXG4gIGl0KCdkZXJpdmVzIHRoZSBCSVA0NCBjaGlsZCB0cmlwbGV0IGZvciBzbG90IDEnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGVyaXZlU2FmZVdhbGxldEtleXMoeyBjb2luOiAnYnRjJywgc2xvdDogJ3NlY3AyNTZrMU11bHRpc2lnJywgYWNjb3VudDogMCwgcm9vdHMgfSk7XG5cbiAgICByZXN1bHQucGF0aC5zaG91bGQuZXF1YWwoXCJtLzQ0Jy8wJy8xJy8wJ1wiKTtcbiAgICByZXN1bHQua2V5cy51c2VyLnBydi5zaG91bGQuZXF1YWwodXNlclJvb3QuZGVyaXZlUGF0aChcIm0vNDQnLzAnLzEnLzAnXCIpLnRvQmFzZTU4KCkpO1xuICAgIHJlc3VsdC5rZXlzLnVzZXIucHViLnNob3VsZC5lcXVhbCh1c2VyUm9vdC5kZXJpdmVQYXRoKFwibS80NCcvMCcvMScvMCdcIikubmV1dGVyZWQoKS50b0Jhc2U1OCgpKTtcbiAgICByZXN1bHQua2V5cy5iYWNrdXAucHJ2LnNob3VsZC5lcXVhbChiYWNrdXBSb290LmRlcml2ZVBhdGgoJ20vNDQvMC8xLzAnKS50b0Jhc2U1OCgpKTtcbiAgICByZXN1bHQua2V5cy5iaXRnby5wdWIuc2hvdWxkLmVxdWFsKGJpdGdvUm9vdC5kZXJpdmVQYXRoKCdtLzQ0LzAvMS8wJykudG9CYXNlNTgoKSk7XG4gIH0pO1xuXG4gIGl0KCd2YXJpZXMgdGhlIHBhdGggd2l0aCB0aGUgYWNjb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkZXJpdmVTYWZlV2FsbGV0S2V5cyh7IGNvaW46ICdidGMnLCBzbG90OiAnc2VjcDI1NmsxTXVsdGlzaWcnLCBhY2NvdW50OiAyLCByb290cyB9KTtcbiAgICByZXN1bHQucGF0aC5zaG91bGQuZXF1YWwoXCJtLzQ0Jy8wJy8xJy8yJ1wiKTtcbiAgfSk7XG5cbiAgaXQoJ3JlamVjdHMgdW5zdXBwb3J0ZWQgc2xvdHMnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgZGVyaXZlU2FmZVdhbGxldEtleXMoeyBjb2luOiAnYnRjJywgc2xvdDogJ2VkZHNhTXBjJywgYWNjb3VudDogMCwgcm9vdHMgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgIC9ub3Qgc3VwcG9ydGVkIHlldC9cbiAgICApO1xuICB9KTtcblxuICBpdCgncmVqZWN0cyBhIG5vbi1pbnRlZ2VyIGFjY291bnQnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgZGVyaXZlU2FmZVdhbGxldEtleXMoeyBjb2luOiAnYnRjJywgc2xvdDogJ3NlY3AyNTZrMU11bHRpc2lnJywgYWNjb3VudDogMS41LCByb290cyB9KS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgL2ludmFsaWQgYWNjb3VudC9cbiAgICApO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnYnVpbGRTYWZlUmVjb3ZlcktleVBhcmFtcycsICgpID0+IHtcbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGNvbnN0IHVzZXJSb290ID0gYmlwMzIuZnJvbVNlZWQoQnVmZmVyLmZyb20oJzAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmJywgJ2hleCcpKTtcbiAgY29uc3QgYmFja3VwUm9vdCA9IGJpcDMyLmZyb21TZWVkKFxuICAgIEJ1ZmZlci5mcm9tKCcxZjFlMWQxYzFiMWExOTE4MTcxNjE1MTQxMzEyMTExMDBmMGUwZDBjMGIwYTA5MDgwNzA2MDUwNDAzMDIwMTAwJywgJ2hleCcpXG4gICk7XG4gIGNvbnN0IGJpdGdvUm9vdCA9IGJpcDMyXG4gICAgLmZyb21TZWVkKEJ1ZmZlci5mcm9tKCcyZjJlMmQyYzJiMmEyOTI4MjcyNjI1MjQyMzIyMjEyMDFmMWUxZDFjMWIxYTE5MTgxNzE2MTUxNDEzMTIxMTEwJywgJ2hleCcpKVxuICAgIC5uZXV0ZXJlZCgpO1xuXG4gIGNvbnN0IGtleXMgPSB7XG4gICAgdXNlcjogeyBwcnY6IHVzZXJSb290LnRvQmFzZTU4KCksIHB1YjogdXNlclJvb3QubmV1dGVyZWQoKS50b0Jhc2U1OCgpIH0sXG4gICAgYmFja3VwOiB7IHBydjogYmFja3VwUm9vdC50b0Jhc2U1OCgpLCBwdWI6IGJhY2t1cFJvb3QubmV1dGVyZWQoKS50b0Jhc2U1OCgpIH0sXG4gICAgYml0Z286IHsgcHViOiBiaXRnb1Jvb3QudG9CYXNlNTgoKSB9LFxuICB9O1xuXG4gIGl0KCdzaWduZWQgbW9kZSByZS1lbmNyeXB0cyBjaGlsZCB4cHJ2cyB1bmRlciBhIHNpbmdsZSBlcGhlbWVyYWwgcGFzc3BocmFzZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwYXNzcGhyYXNlczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBlbmNyeXB0ID0gc2lub24uc3R1YigpLmNhbGxzRmFrZShhc3luYyAoeyBpbnB1dCwgcGFzc3dvcmQsIGVuY3J5cHRpb25WZXJzaW9uIH0pID0+IHtcbiAgICAgIHBhc3NwaHJhc2VzLnB1c2gocGFzc3dvcmQpO1xuICAgICAgZW5jcnlwdGlvblZlcnNpb24uc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgcmV0dXJuIGBlbmMoJHtpbnB1dH0pYDtcbiAgICB9KTtcbiAgICBjb25zdCBiaXRnbyA9IHsgZW5jcnlwdCB9IGFzIHVua25vd24gYXMgQml0R29CYXNlO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYnVpbGRTYWZlUmVjb3ZlcktleVBhcmFtcyh7XG4gICAgICBiaXRnbyxcbiAgICAgIGNvaW46ICdidGMnLFxuICAgICAgc2xvdDogJ3NlY3AyNTZrMU11bHRpc2lnJyxcbiAgICAgIGtleXMsXG4gICAgICBtb2RlOiAnc2lnbmVkJyxcbiAgICB9KTtcblxuICAgIHJlc3VsdC51c2VyS2V5LnNob3VsZC5lcXVhbChgZW5jKCR7a2V5cy51c2VyLnBydn0pYCk7XG4gICAgcmVzdWx0LmJhY2t1cEtleS5zaG91bGQuZXF1YWwoYGVuYygke2tleXMuYmFja3VwLnBydn0pYCk7XG4gICAgcmVzdWx0LmJpdGdvS2V5LnNob3VsZC5lcXVhbChrZXlzLmJpdGdvLnB1Yik7XG4gICAgKHJlc3VsdC53YWxsZXRQYXNzcGhyYXNlIGFzIHN0cmluZykuc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgcGFzc3BocmFzZXMuc2hvdWxkLmhhdmUubGVuZ3RoKDIpO1xuICAgIHBhc3NwaHJhc2VzWzBdLnNob3VsZC5lcXVhbChwYXNzcGhyYXNlc1sxXSk7XG4gICAgcGFzc3BocmFzZXNbMF0uc2hvdWxkLmVxdWFsKHJlc3VsdC53YWxsZXRQYXNzcGhyYXNlKTtcbiAgICBlbmNyeXB0LmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMik7XG4gIH0pO1xuXG4gIGl0KCdyZWplY3RzIG5vbi1wcml2YXRlIGNoaWxkIGtleXMgaW4gc2lnbmVkIG1vZGUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYml0Z28gPSB7IGVuY3J5cHQ6IHNpbm9uLnN0dWIoKSB9IGFzIHVua25vd24gYXMgQml0R29CYXNlO1xuICAgIGF3YWl0IGJ1aWxkU2FmZVJlY292ZXJLZXlQYXJhbXMoe1xuICAgICAgYml0Z28sXG4gICAgICBjb2luOiAnYnRjJyxcbiAgICAgIHNsb3Q6ICdzZWNwMjU2azFNdWx0aXNpZycsXG4gICAgICBrZXlzOiB7IHVzZXI6IHsgcHJ2OiBrZXlzLnVzZXIucHViLCBwdWI6IGtleXMudXNlci5wdWIgfSwgYmFja3VwOiBrZXlzLmJhY2t1cCwgYml0Z286IGtleXMuYml0Z28gfSxcbiAgICAgIG1vZGU6ICdzaWduZWQnLFxuICAgIH0pLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL211c3QgYmUgcHJpdmF0ZSB4cHJ2cy8pO1xuICB9KTtcblxuICBpdCgndW5zaWduZWQgbW9kZSByZXR1cm5zIHB1YnMgYW5kIG5ldmVyIGVuY3J5cHRzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHQgPSBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKGFzeW5jICgpID0+IHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZW5jcnlwdCBzaG91bGQgbm90IGJlIGNhbGxlZCcpO1xuICAgIH0pO1xuICAgIGNvbnN0IGJpdGdvID0geyBlbmNyeXB0IH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2U7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBidWlsZFNhZmVSZWNvdmVyS2V5UGFyYW1zKHtcbiAgICAgIGJpdGdvLFxuICAgICAgY29pbjogJ2J0YycsXG4gICAgICBzbG90OiAnc2VjcDI1NmsxTXVsdGlzaWcnLFxuICAgICAga2V5cyxcbiAgICAgIG1vZGU6ICd1bnNpZ25lZCcsXG4gICAgfSk7XG5cbiAgICByZXN1bHQudXNlcktleS5zaG91bGQuZXF1YWwoa2V5cy51c2VyLnB1Yik7XG4gICAgcmVzdWx0LmJhY2t1cEtleS5zaG91bGQuZXF1YWwoa2V5cy5iYWNrdXAucHViKTtcbiAgICByZXN1bHQuYml0Z29LZXkuc2hvdWxkLmVxdWFsKGtleXMuYml0Z28ucHViKTtcbiAgICByZXN1bHQuc2hvdWxkLm5vdC5oYXZlLnByb3BlcnR5KCd3YWxsZXRQYXNzcGhyYXNlJyk7XG4gICAgZW5jcnlwdC5jYWxsQ291bnQuc2hvdWxkLmVxdWFsKDApO1xuICB9KTtcblxuICBpdCgncmVqZWN0cyB1bnN1cHBvcnRlZCBzbG90cycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBiaXRnbyA9IHsgZW5jcnlwdDogc2lub24uc3R1YigpIH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2U7XG4gICAgYXdhaXQgYnVpbGRTYWZlUmVjb3ZlcktleVBhcmFtcyh7XG4gICAgICBiaXRnbyxcbiAgICAgIGNvaW46ICdidGMnLFxuICAgICAgc2xvdDogJ2VkZHNhTXBjJyxcbiAgICAgIGtleXMsXG4gICAgICBtb2RlOiAnc2lnbmVkJyxcbiAgICB9KS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9ub3Qgc3VwcG9ydGVkIHlldC8pO1xuICB9KTtcbn0pO1xuIl19
|