bitgo
Version:
BitGo JavaScript SDK
1,500 lines • 271 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const _ = require("lodash");
const nock = require("nock");
const openpgp = require("openpgp");
const should = require("should");
const sinon = require("sinon");
const sdk_test_1 = require("@bitgo/sdk-test");
const src_1 = require("../../../../../src");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const ecdsaFixtures_1 = require("../../../fixtures/tss/ecdsaFixtures");
const common_1 = require("./common");
const helpers_1 = require("../../tss/helpers");
const utxo_lib_1 = require("@bitgo/utxo-lib");
const ecdsaNtilde_1 = require("./mocks/ecdsaNtilde");
const sdk_opensslbytes_1 = require("@bitgo/sdk-opensslbytes");
const openSSLBytes = (0, sdk_opensslbytes_1.loadWebAssembly)().buffer;
const createKeccakHash = require('keccak');
const encryptNShare = sdk_core_1.ECDSAMethods.encryptNShare;
openpgp.config.rejectCurves = new Set();
describe('TSS Ecdsa Utils:', async function () {
const coinName = 'hteth';
const reqId = new sdk_core_1.RequestTracer();
const walletId = '5b34252f1bf349930e34020a00000000';
const enterpriseId = '6449153a6f6bc20006d66771cdbe15d3';
const enterpriseData = { id: enterpriseId, name: 'Test Enterprise' };
let sandbox;
let MPC;
let bgUrl;
let tssUtils;
let wallet;
let bitgo;
let baseCoin;
let bitgoKeyShare;
let userKeyShare;
let backupKeyShare;
let bitgoPublicKey;
let userGpgKey;
let userLocalBackupGpgKey;
let bitGoGPGKeyPair;
let nockedBitGoKeychain;
let nockedUserKeychain;
beforeEach(async function () {
sandbox = sinon.createSandbox();
});
afterEach(function () {
sandbox.restore();
});
before(async function () {
nock.cleanAll();
MPC = new sdk_core_1.Ecdsa();
userKeyShare = ecdsaFixtures_1.keyShares.userKeyShare;
backupKeyShare = ecdsaFixtures_1.keyShares.backupKeyShare;
bitgoKeyShare = ecdsaFixtures_1.keyShares.bitgoKeyShare;
const gpgKeyPromises = [
openpgp.generateKey({
userIDs: [
{
name: 'test',
email: 'test@test.com',
},
],
curve: 'secp256k1',
}),
openpgp.generateKey({
userIDs: [
{
name: 'backup',
email: 'backup@test.com',
},
],
curve: 'secp256k1',
}),
openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: 'bitgo@test.com',
},
],
curve: 'secp256k1',
}),
];
[userGpgKey, userLocalBackupGpgKey, bitGoGPGKeyPair] = await Promise.all(gpgKeyPromises);
bitgoPublicKey = await openpgp.readKey({ armoredKey: bitGoGPGKeyPair.publicKey });
const constants = {
mpc: {
bitgoPublicKey: bitGoGPGKeyPair.publicKey,
},
};
bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
bitgo.initializeTestVars();
baseCoin = bitgo.coin(coinName);
bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
// TODO(WP-346): sdk-test mocks conflict so we can't use persist
nock(bgUrl).get('/api/v1/client/constants').times(16).reply(200, { ttl: 3600, constants });
const nockPromises = [
nockBitgoKeychain({
coin: coinName,
userKeyShare,
backupKeyShare,
bitgoKeyShare,
userGpgKey,
userLocalBackupGpgKey,
bitgoGpgKey: bitGoGPGKeyPair,
}),
nockKeychain({ coin: coinName, keyChain: { id: '1', pub: '', type: 'tss' }, source: 'user' }),
nockKeychain({ coin: coinName, keyChain: { id: '2', pub: '', type: 'tss' }, source: 'backup' }),
];
[nockedBitGoKeychain, nockedUserKeychain] = await Promise.all(nockPromises);
const walletData = {
id: walletId,
enterprise: enterpriseId,
coin: coinName,
coinSpecific: {},
multisigType: 'tss',
};
wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData);
tssUtils = new sdk_core_1.ECDSAUtils.EcdsaUtils(bitgo, baseCoin, wallet);
});
after(function () {
nock.cleanAll();
});
describe('TSS key chains', async function () {
it('should create backup key share held by BitGo', async function () {
const enterpriseId = 'enterprise id';
const expectedKeyShare = await nockCreateBitgoHeldBackupKeyShare(coinName, enterpriseId, userGpgKey, backupKeyShare, bitGoGPGKeyPair);
const result = await tssUtils.createBitgoHeldBackupKeyShare(userGpgKey, enterpriseId);
result.should.eql(expectedKeyShare);
});
it('should finalize backup key share held by BitGo', async function () {
const commonKeychain = '4428';
const originalKeyShare = await createIncompleteBitgoHeldBackupKeyShare(userGpgKey, backupKeyShare, bitGoGPGKeyPair);
const expectedFinalKeyShare = await nockFinalizeBitgoHeldBackupKeyShare(coinName, originalKeyShare, commonKeychain, userKeyShare, bitGoGPGKeyPair, nockedBitGoKeychain);
const result = await tssUtils.finalizeBitgoHeldBackupKeyShare(originalKeyShare.id, commonKeychain, userKeyShare, nockedBitGoKeychain, userGpgKey, bitgoPublicKey);
result.should.eql(expectedFinalKeyShare);
});
it('should get the respective backup key shares based on provider', async function () {
const enterpriseId = 'enterprise id';
await nockCreateBitgoHeldBackupKeyShare(coinName, enterpriseId, userGpgKey, backupKeyShare, bitGoGPGKeyPair);
const backupKeyShares = await tssUtils.createBackupKeyShares();
should.exist(backupKeyShares.userHeldKeyShare);
should.not.exist(backupKeyShares.bitGoHeldKeyShares);
});
it('should get the correct bitgo gpg key based on coin and feature flags', async function () {
const nitroGPGKeypair = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo nitro',
email: 'bitgo@test.com',
},
],
});
const nockGPGKey = await nockGetBitgoPublicKeyBasedOnFeatureFlags(coinName, 'enterprise_id', nitroGPGKeypair);
const { mpcv2PublicKey: bitgoGpgPublicKey } = await tssUtils.getBitgoGpgPubkeyBasedOnFeatureFlags('enterprise_id');
should.equal(nockGPGKey.publicKey, bitgoGpgPublicKey.armor());
});
it('getBackupEncryptedNShare should get valid encrypted n shares based on provider', async function () {
const bitgoGpgKeyPubKey = await tssUtils.getBitgoPublicGpgKey();
// Backup key held by user
const backupShareHolderNew = {
userHeldKeyShare: backupKeyShare,
};
const backupToBitgoEncryptedNShare = await tssUtils.getBackupEncryptedNShare(backupShareHolderNew, 3, bitgoGpgKeyPubKey.armor(), userGpgKey);
const encryptedNShare = await encryptNShare(backupKeyShare, 3, bitgoGpgKeyPubKey.armor(), userGpgKey);
// cant verify the encrypted shares, since they will be encrypted with diff. values
should.equal(backupToBitgoEncryptedNShare.publicShare, encryptedNShare.publicShare);
});
it('should generate TSS key chains', async function () {
const backupShareHolder = {
userHeldKeyShare: backupKeyShare,
};
const backupGpgKey = userLocalBackupGpgKey;
const bitgoKeychain = await tssUtils.createBitgoKeychain({
userGpgKey,
backupGpgKey,
userKeyShare,
backupKeyShare: backupShareHolder,
bitgoPublicGpgKey: bitgoPublicKey,
});
const usersKeyChainPromises = [
tssUtils.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 1, userKeyShare, backupKeyShare, bitgoKeychain, 'passphrase'),
tssUtils.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 2, userKeyShare, backupKeyShare, bitgoKeychain, 'passphrase'),
];
const [userKeychain, backupKeychain] = await Promise.all(usersKeyChainPromises);
bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
userKeychain.should.deepEqual(nockedUserKeychain);
// unencrypted `prv` property should exist on backup keychain
const keyChainPrv = JSON.parse(backupKeychain.prv ?? '');
_.isEqual(keyChainPrv.pShare, backupKeyShare.pShare).should.be.true();
_.isEqual(keyChainPrv.bitgoNShare, bitgoKeyShare.nShares[2]).should.be.true();
_.isEqual(keyChainPrv.userNShare, userKeyShare.nShares[2]).should.be.true();
should.exist(backupKeychain.encryptedPrv);
});
it('should send webauthnInfo (with enterpriseId) on the user keychain when webauthnInfo is provided', async function () {
// Keep the real crypto deps (constants w/ bitgo gpg key for verifyWalletSignatures) and
// capture the user keychain add() params by stubbing baseCoin.keychains().
nock.cleanAll();
nock(bgUrl)
.get('/api/v1/client/constants')
.times(16)
.reply(200, { ttl: 3600, constants: { mpc: { bitgoPublicKey: bitGoGPGKeyPair.publicKey } } });
const addStub = sandbox.stub().resolves({ id: '1', pub: '', type: 'tss' });
sandbox.stub(baseCoin, 'keychains').returns({ add: addStub });
const enterpriseId = 'enterprise_id';
const webauthnInfo = { otpDeviceId: 'device-123', prfSalt: 'salt-abc', passphrase: 'prf-derived-passphrase' };
await tssUtils.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 1, userKeyShare, backupKeyShare, nockedBitGoKeychain, 'passphrase', undefined, webauthnInfo, undefined, enterpriseId);
// User keychain must carry webauthnInfo (the field the backend POST /key consumes), including
// enterpriseId, and must NOT use the deprecated webauthnDevices array.
assert.ok(addStub.calledOnce, 'keychains().add should have been called for the user keychain');
const body = addStub.firstCall.args[0];
assert.ok(body.webauthnInfo, 'user keychain body should include webauthnInfo');
assert.equal(body.webauthnInfo.otpDeviceId, webauthnInfo.otpDeviceId);
assert.equal(body.webauthnInfo.prfSalt, webauthnInfo.prfSalt);
assert.equal(body.webauthnInfo.enterpriseId, enterpriseId);
assert.ok(body.webauthnInfo.encryptedPrv, 'encryptedPrv should be set');
assert.ok(await bitgo.decrypt({ input: body.webauthnInfo.encryptedPrv, password: webauthnInfo.passphrase }));
assert.strictEqual(body.webauthnDevices, undefined, 'deprecated webauthnDevices should not be sent');
});
it('should generate TSS key chains with optional params', async function () {
const enterprise = 'enterprise_id';
const backupShareHolder = {
userHeldKeyShare: backupKeyShare,
};
const backupGpgKey = userLocalBackupGpgKey;
const bitgoKeychain = await tssUtils.createBitgoKeychain({
userGpgKey,
backupGpgKey,
userKeyShare,
backupKeyShare: backupShareHolder,
enterprise,
bitgoPublicGpgKey: bitgoPublicKey,
});
const usersKeyChainPromises = [
tssUtils.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 1, userKeyShare, backupKeyShare, bitgoKeychain, 'passphrase', 'originalPasscodeEncryptionCode'),
tssUtils.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 2, userKeyShare, backupKeyShare, bitgoKeychain, 'passphrase'),
];
const [userKeychain, backupKeychain] = await Promise.all(usersKeyChainPromises);
bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
userKeychain.should.deepEqual(nockedUserKeychain);
// unencrypted `prv` property should exist on backup keychain
const keyChainPrv = JSON.parse(backupKeychain.prv ?? '');
_.isEqual(keyChainPrv.pShare, backupKeyShare.pShare).should.be.true();
_.isEqual(keyChainPrv.bitgoNShare, bitgoKeyShare.nShares[2]).should.be.true();
_.isEqual(keyChainPrv.userNShare, userKeyShare.nShares[2]).should.be.true();
should.exist(backupKeychain.encryptedPrv);
});
it('should fail to generate TSS key chains', async function () {
const backupShareHolder = {
userHeldKeyShare: backupKeyShare,
};
const backupGpgKey = userLocalBackupGpgKey;
const bitgoKeychain = await tssUtils.createBitgoKeychain({
userGpgKey,
backupGpgKey,
userKeyShare,
backupKeyShare: backupShareHolder,
bitgoPublicGpgKey: bitgoPublicKey,
});
bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
const testKeyShares = ecdsaFixtures_1.otherKeyShares;
const testCasesPromises = [
tssUtils
.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 1, userKeyShare, testKeyShares[0], bitgoKeychain, 'passphrase')
.should.be.rejectedWith('Common keychains do not match'),
tssUtils
.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 1, testKeyShares[1], backupKeyShare, bitgoKeychain, 'passphrase')
.should.be.rejectedWith('Common keychains do not match'),
tssUtils
.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 2, testKeyShares[2], backupKeyShare, bitgoKeychain, 'passphrase')
.should.be.rejectedWith('Common keychains do not match'),
tssUtils
.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 2, userKeyShare, testKeyShares[3], bitgoKeychain, 'passphrase')
.should.be.rejectedWith('Common keychains do not match'),
];
await Promise.all(testCasesPromises);
});
it('createParticipantKeychain should produce a v2-encrypted encryptedPrv when encryptionVersion: 2', async function () {
const passphrase = 'test-passphrase';
// Stub keychains.add to capture the params sent to the API so we can inspect encryptedPrv
const addStub = sinon.stub(baseCoin.keychains(), 'add').resolves({ id: '1', pub: '', type: 'tss' });
try {
await tssUtils.createParticipantKeychain(userGpgKey, userLocalBackupGpgKey, bitgoPublicKey, 1, userKeyShare, backupKeyShare, nockedBitGoKeychain, passphrase, undefined, undefined, 2 // encryptionVersion
);
sinon.assert.calledOnce(addStub);
const addParams = addStub.firstCall.args[0];
assert.ok(addParams.encryptedPrv, 'encryptedPrv must be passed to keychains.add');
const envelope = JSON.parse(addParams.encryptedPrv);
assert.strictEqual(envelope.v, 2, 'encryptedPrv must use v2 (Argon2id) envelope');
}
finally {
addStub.restore();
}
});
it('should fail to generate TSS keychains when received invalid number of wallet signatures', async function () {
const bitgoKeychain = await generateBitgoKeychain({
coin: coinName,
userKeyShare,
backupKeyShare,
bitgoKeyShare,
userGpgKey,
userLocalBackupGpgKey,
bitgoGpgKey: bitGoGPGKeyPair,
});
const certsString = await (0, src_1.createSharedDataProof)(bitGoGPGKeyPair.privateKey, userGpgKey.publicKey, []);
const certsKey = await openpgp.readKey({ armoredKey: certsString });
const finalKey = new openpgp.PacketList();
certsKey.toPacketList().forEach((packet) => finalKey.push(packet));
// Once the following PR has been merged and released we no longer need the ts-ignore:
// https://github.com/openpgpjs/openpgpjs/pull/1576
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
bitgoKeychain.walletHSMGPGPublicKeySigs = openpgp.armor(openpgp.enums.armor.publicKey, finalKey.write());
await tssUtils
.verifyWalletSignatures(userLocalBackupGpgKey.publicKey, userLocalBackupGpgKey.publicKey, bitgoKeychain, '', 1)
.should.be.rejectedWith(`Invalid wallet signatures`);
});
it('should fail to generate TSS keychains when wallet signature fingerprints do not match passed user/backup fingerprints', async function () {
const customUserKeyShare = await MPC.keyShare(1, 2, 3);
const customBackupKeyShare = await MPC.keyShare(2, 2, 3);
const backupShareHolder = {
userHeldKeyShare: customBackupKeyShare,
};
const backupGpgKey = userLocalBackupGpgKey;
const bitgoKeychain = await tssUtils.createBitgoKeychain({
userGpgKey,
backupGpgKey,
userKeyShare: customUserKeyShare,
backupKeyShare: backupShareHolder,
bitgoPublicGpgKey: bitgoPublicKey,
});
// using the backup gpg here instead of the user gpg key to simulate that the first signature has a different
// fingerprint from the passed in first gpg key
await tssUtils
.verifyWalletSignatures(userLocalBackupGpgKey.publicKey, userLocalBackupGpgKey.publicKey, bitgoKeychain, '', 1)
.should.be.rejectedWith(`first wallet signature's fingerprint does not match passed user gpg key's fingerprint`);
// using the user gpg here instead of the backup gpg key to simulate that the second signature has a different
// fingerprint from the passed in second gpg key
await tssUtils
.verifyWalletSignatures(userGpgKey.publicKey, userGpgKey.publicKey, bitgoKeychain, '', 1)
.should.be.rejectedWith(`second wallet signature's fingerprint does not match passed backup gpg key's fingerprint`);
});
});
describe('signTxRequest:', () => {
const txRequestId = 'randomidEcdsa';
const txRequest = {
txRequestId,
transactions: [
{
unsignedTx: {
// hteth txid: 0xc5a7bfe6b13ceae563da0f9feaa9c4ad1c101a15366a2a488828a5dd27cb9da3
serializedTxHex: '02f38242688084448b9b8084448b9b908301637894a1cfb9d51c0af191ff21c5f0f01723e056f7dc12865af3107a400080c0808080',
signableHex: '02f08242688084448b9b8084448b9b908301637894a1cfb9d51c0af191ff21c5f0f01723e056f7dc12865af3107a400080c0',
derivationPath: '', // Needs this when key derivation is supported
},
state: 'pendingSignature',
signatureShares: [],
},
],
unsignedTxs: [
{
// hteth txid: 0xc5a7bfe6b13ceae563da0f9feaa9c4ad1c101a15366a2a488828a5dd27cb9da3
serializedTxHex: '02f38242688084448b9b8084448b9b908301637894a1cfb9d51c0af191ff21c5f0f01723e056f7dc12865af3107a400080c0808080',
signableHex: '02f38242688084448b9b8084448b9b908301637894a1cfb9d51c0af191ff21c5f0f01723e056f7dc12865af3107a400080c0808080',
derivationPath: '', // Needs this when key derivation is supported
},
],
date: new Date().toISOString(),
intent: {
intentType: 'payment',
},
latest: true,
state: 'pendingUserSignature',
walletType: 'hot',
walletId: 'walletId',
policiesChecked: true,
version: 1,
userId: 'userId',
};
let aShare, dShare, wShare, oShare, userSignShare, bitgoChallenges, enterpriseChallenges;
beforeEach(async () => {
// Initializing user and bitgo for creating shares for nocks
const userSigningKey = MPC.keyCombine(userKeyShare.pShare, [bitgoKeyShare.nShares[1], backupKeyShare.nShares[1]]);
const bitgoSigningKey = MPC.keyCombine(bitgoKeyShare.pShare, [
userKeyShare.nShares[3],
backupKeyShare.nShares[3],
]);
const serializedEntChallenge = ecdsaNtilde_1.mockChallengeA;
const serializedBitgoChallenge = ecdsaNtilde_1.mockChallengeB;
const deserializedEntChallenge = sdk_lib_mpc_1.EcdsaTypes.deserializeNtildeWithProofs(serializedEntChallenge);
sinon.stub(sdk_lib_mpc_1.EcdsaRangeProof, 'generateNtilde').resolves(deserializedEntChallenge);
const [userToBitgoPaillierChallenge, bitgoToUserPaillierChallenge] = await Promise.all([
sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(userSigningKey.yShares[3].n)),
sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(bitgoSigningKey.yShares[1].n)),
]);
bitgoChallenges = {
...serializedBitgoChallenge,
p: sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: bitgoToUserPaillierChallenge }).p,
n: bitgoSigningKey.xShare.n,
};
enterpriseChallenges = {
...serializedEntChallenge,
p: sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: userToBitgoPaillierChallenge }).p,
n: bitgoSigningKey.xShare.n,
};
sinon.stub(sdk_core_1.ECDSAUtils.EcdsaUtils.prototype, 'getEcdsaSigningChallenges').resolves({
enterpriseChallenge: enterpriseChallenges,
bitgoChallenge: bitgoChallenges,
});
const [userXShare, bitgoXShare] = [
MPC.appendChallenge(userSigningKey.xShare, serializedEntChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: userToBitgoPaillierChallenge })),
MPC.appendChallenge(bitgoSigningKey.xShare, serializedBitgoChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: bitgoToUserPaillierChallenge })),
];
const bitgoYShare = MPC.appendChallenge(userSigningKey.yShares[3], serializedBitgoChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: bitgoToUserPaillierChallenge }));
/**
* START STEP ONE
* 1) User creates signShare, saves wShare and sends kShare to bitgo
* 2) Bitgo performs signConvert operation using its private xShare , yShare
* and KShare from user and responds back with aShare and saves bShare for later use
*/
userSignShare = await sdk_core_1.ECDSAMethods.createUserSignShare(userXShare, bitgoYShare);
wShare = userSignShare.wShare;
const signatureShareOneFromUser = {
from: sdk_core_1.SignatureShareType.USER,
to: sdk_core_1.SignatureShareType.BITGO,
share: sdk_core_1.ECDSAMethods.convertKShare(userSignShare.kShare).share.replace(sdk_core_1.ECDSAMethods.delimeter, ''),
};
const getBitgoAandBShare = await MPC.signConvertStep1({
xShare: bitgoXShare,
yShare: bitgoSigningKey.yShares[1], // corresponds to the user
kShare: userSignShare.kShare,
});
const bitgoAshare = getBitgoAandBShare.aShare;
aShare = bitgoAshare;
const aShareBitgoResponse = sdk_core_1.ECDSAMethods.convertAShare(bitgoAshare).share.replace(sdk_core_1.ECDSAMethods.delimeter, '');
const signatureShareOneFromBitgo = {
from: sdk_core_1.SignatureShareType.BITGO,
to: sdk_core_1.SignatureShareType.USER,
share: aShareBitgoResponse,
};
await (0, common_1.nockSendSignatureShareWithResponse)({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare: signatureShareOneFromUser,
response: signatureShareOneFromBitgo,
tssType: 'ecdsa',
});
/** END STEP ONE */
/**
* START STEP TWO
* 1) Using the aShare got from bitgo and wShare from previous step,
* user creates gShare and muShare and sends muShare to bitgo
* 2) Bitgo using the signConvert step using bShare from previous step
* and muShare from user generates its gShare.
* 3) Using the signCombine operation using gShare, Bitgo generates oShare
* which it saves and dShare which is send back to the user.
*/
const userGammaAndMuShares = await sdk_core_1.ECDSAMethods.createUserGammaAndMuShare(userSignShare.wShare, bitgoAshare);
const signatureShareTwoFromUser = {
from: sdk_core_1.SignatureShareType.USER,
to: sdk_core_1.SignatureShareType.BITGO,
share: sdk_core_1.ECDSAMethods.convertMuShare(userGammaAndMuShares.muShare).share.replace(sdk_core_1.ECDSAMethods.delimeter, ''),
};
const getBitGoGShareAndSignerIndexes = await MPC.signConvertStep3({
bShare: getBitgoAandBShare.bShare,
muShare: userGammaAndMuShares.muShare,
});
const getBitgoOShareAndDShares = MPC.signCombine({
gShare: getBitGoGShareAndSignerIndexes.gShare,
signIndex: {
i: 1,
j: 3,
},
});
const bitgoDshare = getBitgoOShareAndDShares.dShare;
dShare = bitgoDshare;
const dShareBitgoResponse = bitgoDshare.delta + bitgoDshare.Gamma;
const signatureShareTwoFromBitgo = {
from: sdk_core_1.SignatureShareType.BITGO,
to: sdk_core_1.SignatureShareType.USER,
share: dShareBitgoResponse,
};
await (0, common_1.nockSendSignatureShareWithResponse)({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare: signatureShareTwoFromUser,
response: signatureShareTwoFromBitgo,
tssType: 'ecdsa',
});
/** END STEP TWO */
/**
* START STEP THREE
* 1) User creates its oShare and dShare using the private gShare
* from step two
* 2) User uses the private oShare and dShare from bitgo from step
* two to generate its signature share which it sends back along with dShare that
* user generated from the above step
* 3) Bitgo using its private oShare from step two and dShare from bitgo creates
* its signature share. Using the Signature Share received from user from the above
* step, bitgo constructs the final signature and is returned to the user
*/
const userOmicronAndDeltaShare = await sdk_core_1.ECDSAMethods.createUserOmicronAndDeltaShare(userGammaAndMuShares.gShare);
oShare = userOmicronAndDeltaShare.oShare;
const signablePayload = Buffer.from(txRequest.unsignedTxs[0].signableHex, 'hex');
const userSShare = await sdk_core_1.ECDSAMethods.createUserSignatureShare(userOmicronAndDeltaShare.oShare, bitgoDshare, signablePayload);
const signatureShareThreeFromUser = {
from: sdk_core_1.SignatureShareType.USER,
to: sdk_core_1.SignatureShareType.BITGO,
share: userSShare.R +
userSShare.s +
userSShare.y +
userOmicronAndDeltaShare.dShare.delta +
userOmicronAndDeltaShare.dShare.Gamma,
};
const getBitGoSShare = MPC.sign(signablePayload, getBitgoOShareAndDShares.oShare, userOmicronAndDeltaShare.dShare, createKeccakHash('keccak256'));
const getBitGoFinalSignature = MPC.constructSignature([getBitGoSShare, userSShare]);
const finalSigantureBitgoResponse = getBitGoFinalSignature.r + getBitGoFinalSignature.s + getBitGoFinalSignature.y;
const signatureShareThreeFromBitgo = {
from: sdk_core_1.SignatureShareType.BITGO,
to: sdk_core_1.SignatureShareType.USER,
share: finalSigantureBitgoResponse,
};
await (0, common_1.nockSendSignatureShareWithResponse)({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare: signatureShareThreeFromUser,
response: signatureShareThreeFromBitgo,
tssType: 'ecdsa',
});
/* END STEP THREE */
const signature = MPC.constructSignature([userSShare, getBitGoSShare]);
MPC.verify(signablePayload, signature, createKeccakHash('keccak256')).should.be.true;
});
afterEach(async () => {
sinon.restore();
});
it('signTxRequest should fail if wallet is in pendingEcdsaTssInitialization', async function () {
sandbox.stub(wallet, 'coinSpecific').returns({
customChangeWalletId: '',
pendingEcdsaTssInitialization: true,
});
await tssUtils
.signTxRequest({
txRequest,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
})
.should.be.rejectedWith('Wallet is not ready for TSS ECDSA signing. Please contact your enterprise admin to finish the enterprise TSS initialization.');
});
it('signTxRequest should succeed with txRequest object as input', async function () {
const sendShareSpy = sinon.spy(sdk_core_1.ECDSAMethods, 'sendShareToBitgo');
await setupSignTxRequestNocks(false, userSignShare, aShare, dShare, enterpriseData);
const signedTxRequest = await tssUtils.signTxRequest({
txRequest,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
});
signedTxRequest.unsignedTxs.should.deepEqual(txRequest.unsignedTxs);
const userGpgActual = sendShareSpy.getCalls()[0].args[10];
userGpgActual.should.startWith('-----BEGIN PGP PUBLIC KEY BLOCK-----');
});
it('signTxRequest should succeed with txRequest id as input', async function () {
const sendShareSpy = sinon.spy(sdk_core_1.ECDSAMethods, 'sendShareToBitgo');
await setupSignTxRequestNocks(true, userSignShare, aShare, dShare, enterpriseData);
const signedTxRequest = await tssUtils.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
});
signedTxRequest.unsignedTxs.should.deepEqual(txRequest.unsignedTxs);
const userGpgActual = sendShareSpy.getCalls()[0].args[10];
userGpgActual.should.startWith('-----BEGIN PGP PUBLIC KEY BLOCK-----');
});
it('signTxRequest should fail with wrong recipient', async function () {
// To generate these Hex values, we used the bitgo-ui to create a transaction and then
// used the `signableHex` and `serializedTxHex` values from the prebuild.
const signableHex = '02f283088bb0038406f18758847f3443c683016378949726ea58be57b153791a8ff5b282d776aaf28e3c87038d7ea4c6800080c0';
const serializedTxHex = '02f583088bb0038406f18758847f3443c683016378949726ea58be57b153791a8ff5b282d776aaf28e3c87038d7ea4c6800080c0808080';
await setupSignTxRequestNocks(true, userSignShare, aShare, dShare, enterpriseData, {
signableHex,
serializedTxHex,
apiVersion: 'full',
});
await tssUtils
.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
txParams: { recipients: [{ address: '0x1234', amount: '1000000000000000' }], type: 'transfer' },
})
.should.be.rejectedWith('destination address does not match with the recipient address');
});
it('signTxRequest should fail with incorrect value', async function () {
nock.cleanAll();
// To generate these Hex values, we used the bitgo-ui to create a transaction and then
// used the `signableHex` and `serializedTxHex` values from the prebuild.
const signableHex = '02f283088bb0038406f18758847f3443c683016378949726ea58be57b153791a8ff5b282d776aaf28e3c87038d7ea4c6800080c0';
const serializedTxHex = '02f583088bb0038406f18758847f3443c683016378949726ea58be57b153791a8ff5b282d776aaf28e3c87038d7ea4c6800080c0808080';
await setupSignTxRequestNocks(true, userSignShare, aShare, dShare, enterpriseData, {
signableHex,
serializedTxHex,
apiVersion: 'full',
});
await tssUtils
.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
txParams: {
recipients: [{ address: '0xa1cfb9d51c0af191ff21c5f0f01723e056f7dc12', amount: '1' }],
type: 'transfer',
},
})
.should.be.rejectedWith('the transaction amount in txPrebuild does not match the value given by client');
});
it('signTxRequest should fail with incorrect value for token txn', async function () {
nock.cleanAll();
// To generate these Hex values, we used the bitgo-ui to create a transaction and then
// used the `signableHex` and `serializedTxHex` values from the prebuild.
const signableHex = '02f86f83088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0';
const serializedTxHex = '02f87283088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0808080';
await setupSignTxRequestNocks(true, userSignShare, aShare, dShare, enterpriseData, {
signableHex,
serializedTxHex,
apiVersion: 'full',
});
await tssUtils
.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
txParams: {
recipients: [{ address: '0x2b0d6cb2f8c388757f4d7ad857fccab18290dbc9', amount: '707' }],
type: 'transfer',
},
})
.should.be.rejectedWith('the transaction amount in txPrebuild does not match the value given by client');
});
it('signTxRequest should succeed for WalletConnect ERC20 transfer with data field', async function () {
nock.cleanAll();
// WalletConnect ERC20 transfer: recipients[0].address is token contract, recipients[0].amount is 0 (no native coins)
// recipients[0].data contains the actual recipient and token amount
const signableHex = '02f86f83088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0';
const serializedTxHex = '02f87283088bb00283e1d7dd84768ea6898301e04b94d9327fd36c3312466efed23ff0493453ee32f55180b844a9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000c0808080';
await setupSignTxRequestNocks(true, userSignShare, aShare, dShare, enterpriseData, {
signableHex,
serializedTxHex,
apiVersion: 'full',
});
await tssUtils.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
txParams: {
recipients: [
{
address: '0xd9327fd36c3312466efed23ff0493453ee32f551', // Token contract address
amount: '0', // No native coins sent
data: '0xa9059cbb0000000000000000000000007d7e63af583ba73ba5c927dbd028153963566bef00000000000000000000000000000000000000000000000000470de4df820000', // ERC20 transfer calldata with actual recipient and token amount
},
],
type: 'transfer',
},
});
});
it('getOfflineSignerPaillierModulus should succeed', async function () {
const paillierModulus = tssUtils.getOfflineSignerPaillierModulus({
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
});
paillierModulus.userPaillierModulus.should.equal(userKeyShare.pShare.n);
});
it('createOfflineKShare should succeed', async function () {
const mockPassword = 'password';
const step1SigningMaterial = await tssUtils.createOfflineKShare({
tssParams: {
txRequest,
reqId: reqId,
},
challenges: {
enterpriseChallenge: enterpriseChallenges,
bitgoChallenge: bitgoChallenges,
},
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
requestType: src_1.RequestType.tx,
walletPassphrase: mockPassword,
});
step1SigningMaterial.privateShareProof.should.startWith('-----BEGIN PGP PUBLIC KEY BLOCK-----');
step1SigningMaterial.vssProof?.length.should.equal(userKeyShare.nShares[3].v?.length);
step1SigningMaterial.publicShare.length.should.equal(userKeyShare.nShares[3].y.length + userKeyShare.nShares[3].chaincode.length);
step1SigningMaterial.encryptedSignerOffsetShare.should.startWith('-----BEGIN PGP MESSAGE-----');
step1SigningMaterial.userPublicGpgKey.should.startWith('-----BEGIN PGP PUBLIC KEY BLOCK-----');
step1SigningMaterial.kShare.n.should.equal(userKeyShare.pShare.n);
step1SigningMaterial.wShare.should.startWith('{"iv":');
});
it('createOfflineKShare should fail with txId passed', async function () {
const mockPassword = 'password';
await tssUtils
.createOfflineKShare({
tssParams: {
txRequest: txRequest.txRequestId,
reqId: reqId,
},
challenges: {
enterpriseChallenge: enterpriseChallenges,
bitgoChallenge: bitgoChallenges,
},
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
requestType: src_1.RequestType.tx,
walletPassphrase: mockPassword,
})
.should.be.rejectedWith('Invalid txRequest type');
});
// Seems to be flaky on CI, failed here: https://github.com/BitGo/BitGoJS/actions/runs/5902489990/job/16010623888?pr=3822
xit('createOfflineMuDeltaShare should succeed', async function () {
const mockPassword = 'password';
const alphaLength = 1536;
const deltaLength = 64;
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const step2SigningMaterial = await tssUtils.createOfflineMuDeltaShare({
aShareFromBitgo: aShare,
bitgoChallenge: bitgoChallenges,
encryptedWShare: await bitgo.encrypt({ input: JSON.stringify(wShare), password: mockPassword }),
walletPassphrase: mockPassword,
});
step2SigningMaterial.muDShare.muShare.alpha.length.should.equal(alphaLength);
step2SigningMaterial.muDShare.dShare.delta.length.should.equal(deltaLength);
step2SigningMaterial.oShare.should.startWith('{"iv":');
});
it('createOfflineMuDeltaShare should fail with incorrect password', async function () {
const mockPassword = 'password';
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
await tssUtils
.createOfflineMuDeltaShare({
aShareFromBitgo: aShare,
bitgoChallenge: bitgoChallenges,
encryptedWShare: await bitgo.encrypt({ input: JSON.stringify(wShare), password: mockPassword }),
walletPassphrase: 'password1',
})
.should.be.rejectedWith('incorrect password');
});
it('createOfflineMuDeltaShare should succeed with v2-encrypted wShare', async function () {
const mockPassword = 'password';
const alphaLength = 1536;
const deltaLength = 64;
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const encryptedWShare = await bitgo.encrypt({
input: JSON.stringify(wShare),
password: mockPassword,
encryptionVersion: 2,
});
assert.strictEqual(JSON.parse(encryptedWShare).v, 2, 'pre-condition: wShare must be v2-encrypted');
const step2SigningMaterial = await tssUtils.createOfflineMuDeltaShare({
aShareFromBitgo: aShare,
bitgoChallenge: bitgoChallenges,
encryptedWShare,
walletPassphrase: mockPassword,
});
step2SigningMaterial.muDShare.muShare.alpha.length.should.equal(alphaLength);
step2SigningMaterial.muDShare.dShare.delta.length.should.equal(deltaLength);
});
it('createOfflineSShare should succeed', async function () {
const mockPassword = 'password';
const pubKeyLength = 66;
const privKeyLength = 64;
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const step3SigningMaterial = await tssUtils.createOfflineSShare({
tssParams: {
txRequest: txRequest,
reqId: reqId,
},
dShareFromBitgo: dShare,
encryptedOShare: await bitgo.encrypt({ input: JSON.stringify(oShare), password: mockPassword }),
walletPassphrase: mockPassword,
requestType: src_1.RequestType.tx,
});
step3SigningMaterial.R.length.should.equal(pubKeyLength);
step3SigningMaterial.y.length.should.equal(pubKeyLength);
step3SigningMaterial.s.length.should.equal(privKeyLength);
});
it('createOfflineSShare should succeed with v2-encrypted oShare', async function () {
const mockPassword = 'password';
const pubKeyLength = 66;
const privKeyLength = 64;
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const encryptedOShare = await bitgo.encrypt({
input: JSON.stringify(oShare),
password: mockPassword,
encryptionVersion: 2,
});
assert.strictEqual(JSON.parse(encryptedOShare).v, 2, 'pre-condition: oShare must be v2-encrypted');
const step3SigningMaterial = await tssUtils.createOfflineSShare({
tssParams: {
txRequest: txRequest,
reqId: reqId,
},
dShareFromBitgo: dShare,
encryptedOShare,
walletPassphrase: mockPassword,
requestType: src_1.RequestType.tx,
});
step3SigningMaterial.R.length.should.equal(pubKeyLength);
step3SigningMaterial.y.length.should.equal(pubKeyLength);
step3SigningMaterial.s.length.should.equal(privKeyLength);
});
it('createOfflineSShare should fail with txId passed', async function () {
const mockPassword = 'password';
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
await tssUtils
.createOfflineSShare({
tssParams: {
txRequest: txRequest.txRequestId,
reqId: reqId,
},
dShareFromBitgo: dShare,
encryptedOShare: await bitgo.encrypt({ input: JSON.stringify(oShare), password: mockPassword }),
walletPassphrase: mockPassword,
requestType: src_1.RequestType.tx,
})
.should.be.rejectedWith('Invalid txRequest type');
});
it('signTxRequest should fail with invalid user prv', async function () {
const invalidUserKey = { ...userKeyShare, pShare: { ...userKeyShare.pShare, i: 2 } };
await tssUtils
.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: invalidUserKey.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
backupNShare: backupKeyShare.nShares[1],
}),
reqId,
})
.should.be.rejectedWith('Invalid user key');
});
it('signTxRequest should fail with no backupNShares', async function () {
const getTxRequest = sandbox.stub(tssUtils, 'getTxRequest');
getTxRequest.resolves(txRequest);
getTxRequest.calledWith(txRequestId);
setupSignTxRequestNocks(false, userSignShare, aShare, dShare, enterpriseData);
await tssUtils
.signTxRequest({
txRequest: txRequestId,
prv: JSON.stringify({
pShare: userKeyShare.pShare,
bitgoNShare: bitgoKeyShare.nShares[1],
}),
reqId,
})
.should.be.rejectedWith('Invalid user key - missing backupNShare');
});
async function setupSignTxRequestNocks(isTxRequest = true, userSignShare, aShare, dShare, enterpriseData, { signableHex, serializedTxHex, apiVersion, } = {}) {
if (enterpriseData) {
await (0, helpers_1.nockGetEnterprise)({ enterpriseId: enterpriseData.id, response: enterpriseData, times: 1 });
}
const derivationPath = '';
sinon.stub(sdk_core_1.ECDSAMethods, 'createUserSignShare').resolves(userSignShare);
let response = {
txRequests: [
{
...txRequest,
transactions: [
{
...txRequest,
unsignedTx: {
signableHex: signableHex ?? txRequest.unsignedTxs[0].signableHex,
serializedTxHex: serializedTxHex ?? txRequest.unsignedTxs[0].serializedTxHex,
derivationPath,
},
},
],
apiVersion: apiVersion,
},
],
};
if (isTxRequest) {
await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response: response });
}
const aRecord = sdk_core_1.ECDSAMethods.convertAShare(aShare);
const signatureShares = [aRecord];
txRequest.signatureShares = signatureShares;
response = {
txRequests: [
{
...txRequest,
transactions: [
{
...txRequest,
unsignedTx: {
signableHex: txRequest.unsignedTxs[0].signableHex,
serializedTxHex: txRequest.unsignedTxs[0].serializedTxHex,
derivationPath,
},
},
],
apiVersion: apiVersion,
},
],
};
await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response: response });
const dRecord = sdk_core_1.ECDSAMethods.convertDShare(dShare);
signatureShares.push(dRecord);
response = {
txRequests: [
{
...txRequest,
transactions: [
{
...txRequest,
unsignedTx: {
signableHex: txRequest.unsignedTxs[0].signableHex,
serializedTxHex: txRequest.unsignedTxs[0].serializedTxHex,
derivationPath,
},
},
],
apiVersion: apiVersion,
},
],
};
await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response: response });
await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response: response });
}
});
describe('getEcdsaSigningChallenges', function () {
const mockWalletPaillierKey = {
n: 'f47be4c2d8bc1e28f88c6c4da634da97d92a1c279a7b0fe7b87c337c36a27b32ce0ff0c45f16e4e15bbd20e4e640de12047eff9b1a2b98144f9a268d406bd000d192a35b6847a17e40fb85f55b314d001ff87393481cafe391807d0eb83eff9e38614b38e5f25fc4449cb01caed805584d026b5d866c723f3d4d4f1e462662f2113b1561eb2bf755b4b91d0308d8eacc439167da8b7d6e108524f226960360af00215d9614457414ebdbe8834999689e2e903208c8713ff5d9901f9eaba3aa81d705323cbbba61ba7fa9f3228f30853fb55da1b3d3ed7db1dfc6545bc96aa8d2eb848931c1b807fdfe8f65af72f68638a82fe9e22ac1f0f032e621066806a1f144b5719a5f091986867b384be6c34146c8241cbfbd781966ebbcd19e6caa27fab040e62e5a162888aa8624d046c8fe3b72244f04a7264c4a36b6366dbe7da98afb201d34be2c0d6dd11982af35bf7535582b263914725aaec280d52290527382d3ab297d746c41aacd8de98c09fcfb85a95e02de1b34d4933e51045e2f1ce8af',
lambda: 'f47be4c2d8bc1e28f88c6c4da634da97d92a1c279a7b0fe7b87c337c36a27b32ce0ff0c45f16e4e15bbd20e4e640de12047eff9b1a2b98144f9a268d406bd000d192a35b6847a17e40fb85f55b314d001ff87393481cafe391807d0eb83eff9e38614b38e5f25fc4449cb01caed805584d026b5d866c723f3d4d4f1e462662f2113b1561eb2bf755b4b91d0308d8eacc439167da8b7d6e108524f226960360af00215d9614457414ebdbe8834999689e2e903208c8713ff5d9901f9eaba3aa7fc3d0c0bcc5bff644156ab887146d51bcee1eef70f45c486147d687ee37def1f8a16bc945eff22dd4dca3614a99158823acd9492e347f7ec79a7771024205d07f27b30cd20340e330411da8fa2da209e5cc688da94d1dbef54bfd9c69b4e99cf06d67309a3420b82c78a0fe0dd0b9c31382eae38746cfdd27fa90022a50532246c8ae1339c93e183c03bf6fd7014be3658abc73baae1fa5b86dab94b9f125395a818e54dde6235c45d3dbc032b3078e9df1cad69d8ac19a7cb6405a558b7bfba8',
};
const mockBitgoPaillierKey = {
n: 'f010d294effceb8c4f96af1978ab367c4fbb272c2169317e41ae87220652cae2ce929696ee55ec6831aa6b4b3b931babc2bac9c1a20fddbca925cc99680791f7c3157b3d31256ee72c47d47db567e0f070dce121c3a4d9e003c1f1389073acb252c65d2b0723e86e3265f67a137cb1e23f4551544405644d0ae63d35f25f40becd2b693879f3bdbec3f7250791a3f3c975a5ac78a0e81dcd1a87eb2ca67010dff880b2338556275de23d9e88d21b77da0d524ddc2b394f8de00b1af0ce85f6eee2e05a184e05494d66d2c636045bf70ed15ebd0f41a8eea2920af85e6d68a0ce11fc2abbcb3cebcc3c23ec2e148c318683a5426e15b5207efd3b9b05cb919ec4340f74dff336986d0c923df10a789007b1da9daddf8edf3014e93989f30243f27f9a307d55d630cbfcd16cd6a95a41dee10c31acc293df6834ce0e3ea5b68f170bd7938ea0c2eeb788e16f30af57b3f0888fb44d3610e7eeba60e7fd8cc4a8f044718dfc6174bf4a380690dc1dc77472a48892eb3e81775540ea0acc9e89b639',
lambda: 'f010d294effceb8c4f96af1978ab367c4fbb272c2169317e41ae87220652cae2ce929696ee55ec6831aa6b4b3b931babc2bac9c1a20fddbca925cc99680791f7c3157b3d31256ee72c47d47db567e0f070dce121c3a4d9e003c1f1389073acb252c65d2b0723e86e3265f67a137cb1e23f4551544405644d0ae63d35f25f40becd2b693879f3bdbec3f7250791a3f3c975a5ac78a0e81dcd1a87eb2ca67010dff880b2338556275de23d9e88d21b77da0d524ddc2b394f8de00b1af0ce85f6ecdef8a4bc955a28ecef7d97cded079d390e77c80998d78ad9510cbabfeb8f0a157dbfc590b4d59ee8c0b088f9d89473b557320078a117478624f5d1df36e30f320b6722a4217dcb46b978cc6c8f1a21c8a6c74bce84d82c481402c99a69b798e3c05f23350b4aade4f79784b1c09692b6a33cfba7f145597d82b799cccef620c36f1fbbe2cb4ac0ea395c476e381bc475d41722320f541ae9bf56aa4a12dff3ea7ab11174fb5b8df7429c9f57d36f8fc51e1a8c647d5b8fa0189fb8acdbd0a780',
};
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const txRequestId = 'fakeTxRequestId';
const rawEntChallengeWithProofs = sdk_test_1.mockSerializedChallengeWithProofs;
let rawBitgoChallenge;
const adminEcdhKey = bitgo.keychains().create();
const fakeAdminEcdhKey = bitgo.keychains().create();
const derivationPath = 'm/0/0';
const mockedSigningKey = {
userId: 'id',
userEmail: 'user@bitgo.com',
derivedPubkey: utxo_lib_1.bip32.fromBase58(adminEcdhKey.xpub).derivePath(derivationPath).publicKey.toString('hex'),
derivationPath: derivationPath,
ecdhKeychain: 'my keychain',
};
before(async function () {
const p = await sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(mockWalletPaillierKey.n));
rawBitgoChallenge = {
...sdk_lib_mpc_1.EcdsaTypes.serializeNtilde(sdk_lib_mpc_1.EcdsaTypes.deserializeNtilde(sdk_test_1.mockSerializedChallengeWithProofs2)),
p: sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p }).p,
n: mockBitgoPaillierKey.n,
};
});
afterEach(function () {
sinon.restore();
nock.cleanAll();
});
it('should fetch static ent and bitgo challenges with the ent feature flag and verify them', async function () {
await (0, helpers_1.nockGetChallenge)({ walletId, txRequestId, addendum: '/transactions/0', response: rawBitgoChallenge });
await (0, helpers_1.nockGetSigningKey)({ enterpriseId, userId: mockedSigningKey.userId, response: mockedSigningKey, times: 1 });
const adminSignatureEntChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(rawEntChallengeWithProofs, adminEcdhKey.xprv, derivationPath);
const adminSignatureBitGoChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(rawBitgoChallenge, adminEcdhKey.xprv, derivationPath);
const mockChallengesResponse = {
enterpriseChallenge: {
...rawEntChallengeWithProofs,
verifiers: {
adminSignature: adminSignatureEntChallenge.toString('hex'),
},
},
bitgoChallenge: {
...rawBitgoChallenge,
verifiers: {
adminSignature: adminSignatureBitGoChallenge.toString('hex'),
},
},
createdBy: 'id',
};
await (0, helpers_1.nockGetChallenges)({ walletId: walletId, response: mockChallengesResponse });
const challenges = await tssUtils.getEcdsaSigningChallenges(txRequestId, 0, mockWalletPaillierKey.n, 0);
should.exist(challenges);
const expectedRangeProofChallenges = {
enterpriseChallenge: {
ntilde: challenges.enterpriseChallenge.ntilde,
h1: challenges.enterpriseChallenge.h1,
h2: challenges.enterpriseChallenge.h2,
},
bitgoChallenge: rawBitgoChallenge,
};
expectedRangeProofChallenges.should.deepEqual({
enterpriseChallenge: {
ntilde: rawEntChallengeWithProofs.ntilde,
h1: rawEntChallengeWithProofs.h1,
h2: rawEntChallengeWithProofs.h2,
},
bitgoChallenge: rawBitgoChallenge,
});
});
it('Fails if the enterprise challenge signature is different from the admin ecdh key', async function () {
await (0, helpers_1.nockGetChallenge)({ walletId, txRequestId, addendum: '/transactions/0', response: rawBitgoChallenge });
await (0, helpers_1.nockGetEnterprise)({
enterpriseId: enterpriseData.id,
response: {
...enterpriseData,
featureFlags: ['useEnterpriseEcdsaTssChallenge'],
},
times: 1,
});
await (0, helpers_1.nockGetSigningKey)({ enterpriseId, userId: mockedSigningKey.userId, response: mockedSigningKey, times: 1 });
// Bad sign
const adminSignedEntChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(rawEntChallengeWithProofs, fakeAdminEcdhKey.xprv, derivationPath);
const adminSignedBitGoChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(rawBitgoChallenge, adminEcdhKey.xprv, derivationPath);
const mockChallengesResponse = {
enterpriseChallenge: {
...rawEntChallengeWithProofs,
verifiers: {
adminSignature: adminSignedEntChallenge.toString('hex'),
},
},
bitgoChallenge: {
...rawBitgoChallenge,
verifiers: {
adminSignature: adminSignedBitGoChallenge.toString('hex'),
},
},
createdBy: 'id',
};
await (0, helpers_1.nockGetChallenges)({ walletId: walletId, response: mockChallengesResponse });
await tssUtils
.getEcdsaSigningChallenges(txRequestId, 0, mockWalletPaillierKey.n)
.should.be.rejectedWith('Admin signature for enterprise challenge is not valid. Please contact your enterprise admin.');
});
it('Fails if the bitgo challenge signature is different from the admin ecdh key', async function () {
await (0, helpers_1.nockGetChallenge)({ walletId, txRequestId, addendum: '/transactions/0', response: rawBitgoChallenge });
await (0, helpers_1.nockGetEnterprise)({
enterpriseId: enterpriseData.id,
response: {
...enterpriseData,
featureFlags: ['useEnterpriseEcdsaTssChallenge'],
},
times: 1,
});
await (0, helpers_1.nockGetSigningKey)({ enterpriseId, userId: mockedSigningKey.userId, response: mockedSigningKey, times: 1 });
const adminSignedEntChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(rawEntChallengeWithProofs, adminEcdhKey.xprv, derivationPath);
// Bad sign
const adminSignedBitGoChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(rawBitgoChallenge, fakeAdminEcdhKey.xprv, derivationPath);
const mockChallengesResponse = {
enterpriseChallenge: {
...rawEntChallengeWithProofs,
verifiers: {
adminSignature: adminSignedEntChallenge.toString('hex'),
},
},
bitgoChallenge: {
...rawBitgoChallenge,
verifiers: {
adminSignature: adminSignedBitGoChallenge.toString('hex'),
},
},
createdBy: 'id',
};
await (0, helpers_1.nockGetChallenges)({ walletId: walletId, response: mockChallengesResponse });
await tssUtils
.getEcdsaSigningChallenges(txRequestId, 0, mockWalletPaillierKey.n)
.should.be.rejectedWith("Admin signature for BitGo's challenge is not valid. Please contact your enterprise admin.");
});
});
describe('getVerifyAndSignBitGoChallenges', function () {
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const adminEcdhKey = bitgo.keychains().create();
const derivationPath = 'm/0/0';
const bitgoInstChallenge = ecdsaNtilde_1.mockChallengeA;
const bitgoNitroChallenge = ecdsaNtilde_1.mockChallengeB;
const userPassword = 'password123';
let encryptedXprv;
before(async function () {
encryptedXprv = await bitgo.encrypt({
password: userPassword,
input: adminEcdhKey.xprv,
});
});
beforeEach(async function () {
sinon.stub(bitgo, 'getSigningKeyForUser').resolves({
userId: 'id',
userEmail: 'user@bitgo.com',
derivedPubkey: utxo_lib_1.bip32.fromBase58(adminEcdhKey.xpub).derivePath(derivationPath).publicKey.toString('hex'),
derivationPath: derivationPath,
ecdhKeychain: 'my keychain',
});
sinon.stub(bitgo, 'getECDHKeychain').resolves({
encryptedXprv: encryptedXprv,
});
});
afterEach(async function () {
sinon.restore();
nock.cleanAll();
});
function nockGetBitgoChallenges(response) {
return nock(bgUrl)
.get(`/api/v2/tss/ecdsa/challenges`)
.times(1)
.reply(() => [200, response]);
}
it('succeeds for valid bitgo proofs', async function () {
const nockGetBitgoChallengesApi = nockGetBitgoChallenges({
bitgoNitroHsm: bitgoNitroChallenge,
bitgoInstitutionalHsm: bitgoInstChallenge,
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', userPassword).should.not.be.rejected();
nockGetBitgoChallengesApi.isDone().should.be.true();
});
it('Fails if bitgo challenge proofs are not present', async function () {
const nockGetBitgoChallengesApi = nockGetBitgoChallenges({
bitgoNitroHsm: {
...bitgoNitroChallenge,
ntildeProof: undefined,
},
bitgoInstitutionalHsm: bitgoInstChallenge,
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', userPassword).should.be.rejectedWith('Expected BitGo challenge proof to be present. Contact support@bitgo.com.');
nockGetBitgoChallengesApi.isDone().should.be.true();
});
it('Fails if the user password to decrypt the ecdhkeychain is wrong', async function () {
const nockGetBitgoChallengesApi = nockGetBitgoChallenges({
bitgoNitroHsm: bitgoNitroChallenge,
bitgoInstitutionalHsm: bitgoInstChallenge,
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', 'bro').should.be.rejectedWith('Incorrect password. Please try again.');
nockGetBitgoChallengesApi.isDone().should.be.true();
});
it('Fails bitgo challenge proofs for faulty nitro h2WrtH1 proof', async function () {
const nockGetBitgoChallengesApi = nockGetBitgoChallenges({
bitgoNitroHsm: {
...bitgoNitroChallenge,
ntildeProof: {
...bitgoNitroChallenge.ntildeProof,
h2WrtH1: bitgoNitroChallenge.ntildeProof.h1WrtH2,
},
},
bitgoInstitutionalHsm: bitgoInstChallenge,
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', userPassword).should.be.rejectedWith("Failed to verify BitGo's challenge needed to enable ECDSA signing. Please contact support@bitgo.com");
nockGetBitgoChallengesApi.isDone().should.be.true();
});
it('Fails bitgo challenge proofs for faulty nitro h1WrtH2 proof', async function () {
const nockGetBitgoChallengesApi = nockGetBitgoChallenges({
bitgoNitroHsm: {
...bitgoNitroChallenge,
ntildeProof: {
...bitgoNitroChallenge.ntildeProof,
h1WrtH2: bitgoNitroChallenge.ntildeProof.h2WrtH1,
},
},
bitgoInstitutionalHsm: bitgoInstChallenge,
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', userPassword).should.be.rejectedWith("Failed to verify BitGo's challenge needed to enable ECDSA signing. Please contact support@bitgo.com");
nockGetBitgoChallengesApi.isDone().should.be.true();
});
it('Fails bitgo challenge proofs for faulty inst h2WrtH1 proof', async function () {
const nockGetBitgoChallengesApi = nock(bgUrl)
.get(`/api/v2/tss/ecdsa/challenges`)
.times(1)
.reply(200, {
bitgoNitroHsm: bitgoNitroChallenge,
bitgoInstitutionalHsm: {
...bitgoInstChallenge,
ntildeProof: {
...bitgoInstChallenge.ntildeProof,
h2WrtH1: bitgoInstChallenge.ntildeProof.h1WrtH2,
},
},
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', userPassword).should.be.rejectedWith("Failed to verify BitGo's challenge needed to enable ECDSA signing. Please contact support@bitgo.com");
nockGetBitgoChallengesApi.isDone().should.be.true();
});
it('Fails bitgo challenge proofs for faulty inst h1WrtH2 proof', async function () {
const nockGetBitgoChallengesApi = nock(bgUrl)
.get(`/api/v2/tss/ecdsa/challenges`)
.times(1)
.reply(200, {
bitgoNitroHsm: bitgoNitroChallenge,
bitgoInstitutionalHsm: {
...bitgoInstChallenge,
ntildeProof: {
...bitgoInstChallenge.ntildeProof,
h1WrtH2: bitgoInstChallenge.ntildeProof.h2WrtH1,
},
},
});
await sdk_core_1.ECDSAUtils.EcdsaUtils.getVerifyAndSignBitGoChallenges(bitgo, 'ent_id', userPassword).should.be.rejectedWith("Failed to verify BitGo's challenge needed to enable ECDSA signing. Please contact support@bitgo.com");
nockGetBitgoChallengesApi.isDone().should.be.true();
});
});
describe('supportedTxRequestVersions', function () {
it('returns only full for hot wallets', function () {
const hotWallet = new sdk_core_1.Wallet(bitgo, baseCoin, { type: 'hot', multisigType: 'tss' });
const hotWalletTssUtils = new sdk_core_1.ECDSAUtils.EcdsaUtils(bitgo, baseCoin, hotWallet);
hotWalletTssUtils.supportedTxRequestVersions().should.deepEqual(['full']);
});
it('returns only full for cold wallets', function () {
const coldWallet = new sdk_core_1.Wallet(bitgo, baseCoin, {
type: 'cold',
multisigType: 'tss',
});
const coldWalletTssUtils = new sdk_core_1.ECDSAUtils.EcdsaUtils(bitgo, baseCoin, coldWallet);
coldWalletTssUtils.supportedTxRequestVersions().should.deepEqual(['full']);
});
it('returns only full for custodial wallets', function () {
const custodialWallet = new sdk_core_1.Wallet(bitgo, baseCoin, { type: 'custodial', multisigType: 'tss' });
const custodialWalletTssUtils = new sdk_core_1.ECDSAUtils.EcdsaUtils(bitgo, baseCoin, custodialWallet);
custodialWalletTssUtils.supportedTxRequestVersions().should.deepEqual(['full']);
});
it('returns empty for trading wallets', function () {
const tradingWallet = new sdk_core_1.Wallet(bitgo, baseCoin, { type: 'trading', multisigType: 'tss' });
const tradingWalletTssUtils = new sdk_core_1.ECDSAUtils.EcdsaUtils(bitgo, baseCoin, tradingWallet);
tradingWalletTssUtils.supportedTxRequestVersions().should.deepEqual([]);
});
it('returns empty for non-tss wallets', function () {
const nonTssWalletData = { coin: 'tbtc', multisigType: 'onchain' };
const btcCoin = bitgo.coin('tbtc');
const nonTssWallet = new sdk_core_1.Wallet(bitgo, btcCoin, nonTssWalletData);
const nonTssWalletTssUtils = new src_1.TssUtils(bitgo, btcCoin, nonTssWallet);
nonTssWalletTssUtils.supportedTxRequestVersions().should.deepEqual([]);
});
});
describe('initiateChallengesForEnterprise', function () {
const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const adminEcdhKey = bitgo.keychains().create();
const derivationPath = 'm/0/0';
const bitgoInstChallenge = ecdsaNtilde_1.mockChallengeA;
const bitgoNitroChallenge = ecdsaNtilde_1.mockChallengeB;
const serializedEntChallenge = ecdsaNtilde_1.mockChallengeC;
const userPassword = 'password123';
let encryptedXprv;
before(async function () {
encryptedXprv = await bitgo.encrypt({
password: userPassword,
input: adminEcdhKey.xprv,
});
});
beforeEach(async function () {
sinon.stub(bitgo, 'getSigningKeyForUser').resolves({
userId: 'id',
userEmail: 'user@bitgo.com',
derivedPubkey: utxo_lib_1.bip32.fromBase58(adminEcdhKey.xpub).derivePath(derivationPath).publicKey.toString('hex'),
derivationPath: derivationPath,
ecdhKeychain: 'my keychain',
});
sinon.stub(bitgo, 'getECDHKeychain').resolves({
encryptedXprv: encryptedXprv,
});
});
afterEach(async function () {
sinon.restore();
});
it('should upload challenge without generating if passed in', async function () {
const stubUploadChallenge = sinon.stub(sdk_core_1.ECDSAUtils.EcdsaUtils, 'uploadChallengesToEnterprise');
const deserializedEntChallenge = sdk_lib_mpc_1.EcdsaTypes.deserializeNtildeWithProofs(serializedEntChallenge);
const signedEntChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(serializedEntChallenge, adminEcdhKey.xprv, derivationPath);
const signedInstChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(bitgoInstChallenge, adminEcdhKey.xprv, derivationPath);
const signedNitroChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(bitgoNitroChallenge, adminEcdhKey.xprv, derivationPath);
await sdk_core_1.ECDSAUtils.EcdsaUtils.initiateChallengesForEnterprise(bitgo, 'ent_id', userPassword, signedInstChallenge, signedNitroChallenge, openSSLBytes, deserializedEntChallenge).should.not.be.rejected();
stubUploadChallenge.calledWith(bitgo, 'ent_id', serializedEntChallenge, signedEntChallenge.toString('hex'), signedInstChallenge.toString('hex'), signedNitroChallenge.toString('hex'));
});
it('should generate a challenge and if one is not provided', async function () {
const stubUploadChallenge = sinon.stub(sdk_core_1.ECDSAUtils.EcdsaUtils, 'uploadChallengesToEnterprise');
const deserializedEntChallenge = sdk_lib_mpc_1.EcdsaTypes.deserializeNtildeWithProofs(serializedEntChallenge);
sinon.stub(sdk_lib_mpc_1.EcdsaRangeProof, 'generateNtilde').resolves(deserializedEntChallenge);
const signedEntChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(serializedEntChallenge, adminEcdhKey.xprv, derivationPath);
const signedInstChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(bitgoInstChallenge, adminEcdhKey.xprv, derivationPath);
const signedNitroChallenge = sdk_core_1.ECDSAUtils.EcdsaUtils.signChallenge(bitgoNitroChallenge, adminEcdhKey.xprv, derivationPath);
await sdk_core_1.ECDSAUtils.EcdsaUtils.initiateChallengesForEnterprise(bitgo, 'ent_id', userPassword, signedInstChallenge, signedNitroChallenge, openSSLBytes).should.not.be.rejected();
stubUploadChallenge.calledWith(bitgo, 'ent_id', serializedEntChallenge, signedEntChallenge.toString('hex'), signedInstChallenge.toString('hex'), signedNitroChallenge.toString('hex'));
});
});
it('getMessageToSignFromChallenge concatenates the challenge values only', function () {
const challenge = ecdsaNtilde_1.mockChallengeA;
const expectedMessageToSign = challenge.ntilde.concat(challenge.h1).concat(challenge.h2);
const message = sdk_core_1.ECDSAUtils.EcdsaUtils.getMessageToSignFromChallenge(challenge);
message.should.equal(expectedMessageToSign);
});
describe('validateCommonKeychainPublicKey', function () {
it('validateCommonKeychainPublicKey returns correct public key', function () {
const commonKeychain = '03f40c70545b519bb7bbc7195fd4b7d5bbfc873bfd38b18596e4b47a05b6a88d552e2e8319cb31e279b99dbe54115a983d35e86679af96d81b7478d1df368f76a8';
const expectedPubKeyResult = `f40c70545b519bb7bbc7195fd4b7d5bbfc873bfd38b18596e4b47a05b6a88d556a10d6ab8055dc0b3a9af9dc4e42f4f9773c590afcc298d017c1b1ce29a88041`;
const actualPubKey = sdk_core_1.ECDSAUtils.EcdsaUtils.validateCommonKeychainPublicKey(commonKeychain);
actualPubKey.should.equal(expectedPubKeyResult);
});
it('validateCommonKeychainPublicKey throws correctly with invalid length', function () {
const commonKeychain = '03f40c70548';
should(() => sdk_core_1.ECDSAUtils.EcdsaUtils.validateCommonKeychainPublicKey(commonKeychain)).throwError('Invalid commonKeychain length, expected 130, got 11');
});
it('validateCommonKeychainPublicKey throws correctly with invalid commonKeychain', function () {
const commonKeychainWithInvalidCharacters = '!@#$^0c70545b519bb7bbc7195fd4b7d5bfc873bfd38b18596e4b47a05b6a88d552e2e8319cb31e279b99dbe54115a983d35e86679af96d81b7478d1df368f76a8'; // 129 chars
should(() => sdk_core_1.ECDSAUtils.EcdsaUtils.validateCommonKeychainPublicKey(commonKeychainWithInvalidCharacters)).throwError(/^Invalid commonKeychain, error:/);
});
});
// #region Nock helpers
async function createIncompleteBitgoHeldBackupKeyShare(userGpgKey, backupKeyShare, bitgoGpgKey) {
const nSharePromises = [
encryptNShare(backupKeyShare, 1, userGpgKey.publicKey, userGpgKey, false),
encryptNShare(backupKeyShare, 3, bitgoGpgKey.publicKey, userGpgKey, false),
];
const backupToUserPublicShare = Buffer.concat([
Buffer.from(backupKeyShare.nShares[1].y, 'hex'),
Buffer.from(backupKeyShare.nShares[1].chaincode, 'hex'),
]).toString('hex');
const backupToBitgoPublicShare = Buffer.concat([
Buffer.from(backupKeyShare.nShares[3].y, 'hex'),
Buffer.from(backupKeyShare.nShares[3].chaincode, 'hex'),
]).toString('hex');
return {
id: '4711',
keyShares: [
{
from: 'backup',
to: 'user',
publicShare: backupToUserPublicShare,
privateShare: (await nSharePromises[0]).encryptedPrivateShare,
},
{
from: 'backup',
to: 'bitgo',
publicShare: backupToBitgoPublicShare,
privateShare: (await nSharePromises[1]).encryptedPrivateShare,
},
],
};
}
async function nockGetBitgoPublicKeyBasedOnFeatureFlags(coin, enterpriseId, bitgoGpgKeyPair) {
const bitgoGPGPublicKeyResponse = {
name: 'irrelevant',
publicKey: bitgoGpgKeyPair.publicKey,
mpcv2PublicKey: bitgoGpgKeyPair.publicKey,
enterpriseId,
};
nock(bgUrl).get(`/api/v2/${coin}/tss/pubkey`).query({ enterpriseId }).reply(200, bitgoGPGPublicKeyResponse);
return bitgoGPGPublicKeyResponse;
}
async function nockCreateBitgoHeldBackupKeyShare(coin, enterpriseId, userGpgKey, backupKeyShare, bitgoGpgKey) {
const keyShare = await createIncompleteBitgoHeldBackupKeyShare(userGpgKey, backupKeyShare, bitgoGpgKey);
nock(bgUrl)
.post(`/api/v2/${coin}/krs/backupkeys`, _.matches({ enterprise: enterpriseId, userGPGPublicKey: userGpgKey.publicKey }))
.reply(201, keyShare);
return keyShare;
}
async function nockFinalizeBitgoHeldBackupKeyShare(coin, originalKeyShare, commonKeychain, userKeyShare, userLocalBackupGpgKey, bitgoKeychain) {
const encryptedUserToBackupKeyShare = await encryptNShare(userKeyShare, 2, userLocalBackupGpgKey.publicKey, userGpgKey, false);
assert.ok(bitgoKeychain.keyShares);
const bitgoToBackupKeyShare = bitgoKeychain.keyShares.find((keyShare) => keyShare.from === 'bitgo' && keyShare.to === 'backup');
assert.ok(bitgoToBackupKeyShare);
const userPublicShare = Buffer.concat([
Buffer.from(userKeyShare.nShares[2].y, 'hex'),
Buffer.from(userKeyShare.nShares[2].chaincode, 'hex'),
]).toString('hex');
const expectedKeyShares = [
{
from: 'user',
to: 'backup',
publicShare: userPublicShare,
// Omitting the private share, the actual encryption happens inside the function where we make the matching call
// to this nock. We cannot recreate the same encrypted value here because gpg encryption is not deterministic
},
bitgoToBackupKeyShare,
];
const updatedKeyShare = {
id: originalKeyShare.id,
commonKeychain,
keyShares: [
...originalKeyShare.keyShares,
{
from: 'user',
to: 'backup',
publicShare: userPublicShare,
privateShare: encryptedUserToBackupKeyShare.encryptedPrivateShare,
},
bitgoToBackupKeyShare,
],
};
nock(bgUrl)
.put(`/api/v2/${coin}/krs/backupkeys/${originalKeyShare.id}`, _.matches({ commonKeychain, keyShares: expectedKeyShares }))
.reply(200, updatedKeyShare);
return updatedKeyShare;
}
/**
* Helper function to generate a bitgo keychain given the full set of keyshares and GPG keys.
* Also mocks the wallet signatures added by the HSM.
* @param params
*/
async function generateBitgoKeychain(params) {
const bitgoCombined = MPC.keyCombine(params.bitgoKeyShare.pShare, [
params.userKeyShare.nShares[3],
params.backupKeyShare.nShares[3],
]);
const userGpgKeyActual = await openpgp.readKey({ armoredKey: params.userGpgKey.publicKey });
const backupGpgKeyActual = await openpgp.readKey({ armoredKey: params.userLocalBackupGpgKey.publicKey });
const nSharePromises = [
encryptNShare(params.bitgoKeyShare, 1, params.userGpgKey.publicKey, params.userGpgKey, false),
encryptNShare(params.bitgoKeyShare, 2, params.userLocalBackupGpgKey.publicKey, params.userLocalBackupGpgKey, false),
];
const [userToBitgoShare, backupToBitgoShare] = await Promise.all(nSharePromises);
const bitgoKeychain = {
id: '3',
pub: '',
commonKeychain: bitgoCombined.xShare.y + bitgoCombined.xShare.chaincode,
keyShares: [
{
from: 'bitgo',
to: 'user',
publicShare: userToBitgoShare.publicShare,
privateShare: userToBitgoShare.encryptedPrivateShare,
n: userToBitgoShare.n,
vssProof: userToBitgoShare.vssProof,
privateShareProof: userToBitgoShare.privateShareProof,
},
{
from: 'bitgo',
to: 'backup',
publicShare: backupToBitgoShare.publicShare,
privateShare: backupToBitgoShare.encryptedPrivateShare,
n: backupToBitgoShare.n,
vssProof: backupToBitgoShare.vssProof,
privateShareProof: backupToBitgoShare.privateShareProof,
},
],
type: 'tss',
};
const userKeyId = userGpgKeyActual.keyPacket.getFingerprint();
const backupKeyId = backupGpgKeyActual.keyPacket.getFingerprint();
const bitgoToUserPublicU = Buffer.from(utxo_lib_1.ecc.pointFromScalar(Buffer.from(params.bitgoKeyShare.nShares[1].u, 'hex'), true)).toString('hex') + params.bitgoKeyShare.nShares[1].chaincode;
const bitgoToBackupPublicU = Buffer.from(utxo_lib_1.ecc.pointFromScalar(Buffer.from(params.bitgoKeyShare.nShares[2].u, 'hex'), true)).toString('hex') + params.bitgoKeyShare.nShares[2].chaincode;
bitgoKeychain.walletHSMGPGPublicKeySigs = await (0, helpers_1.createWalletSignatures)(params.bitgoGpgKey.privateKey, params.userGpgKey.publicKey, params.userLocalBackupGpgKey.publicKey, [
{ name: 'commonKeychain', value: bitgoCombined.xShare.y + bitgoCombined.xShare.chaincode },
{ name: 'userKeyId', value: userKeyId },
{ name: 'backupKeyId', value: backupKeyId },
{ name: 'bitgoToUserPublicShare', value: bitgoToUserPublicU },
{ name: 'bitgoToBackupPublicShare', value: bitgoToBackupPublicU },
]);
return bitgoKeychain;
}
async function nockBitgoKeychain(params) {
const bitgoKeychain = await generateBitgoKeychain(params);
nock(bgUrl)
.persist()
.post(`/api/v2/${params.coin}/key`, _.matches({ keyType: 'tss', source: 'bitgo' }))
.reply(200, bitgoKeychain);
return bitgoKeychain;
}
async function nockKeychain(params) {
nock('https://bitgo.fakeurl')
.persist()
.post(`/api/v2/${params.coin}/key`, _.matches({ keyType: 'tss', source: params.source }))
.reply(200, params.keyChain);
return params.keyChain;
}
// #endregion Nock helpers
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZXN0L3YyL3VuaXQvaW50ZXJuYWwvdHNzVXRpbHMvZWNkc2EudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxpQ0FBaUM7QUFDakMsNEJBQTRCO0FBQzVCLDZCQUE4QjtBQUM5QixtQ0FBbUM7QUFDbkMsaUNBQWtDO0FBQ2xDLCtCQUErQjtBQUUvQiw4Q0FLeUI7QUFDekIsNENBQXlGO0FBQ3pGLDhDQW1CeUI7QUFDekIsb0RBQWtHO0FBQ2xHLHVFQUFnRjtBQUNoRixxQ0FBOEQ7QUFDOUQsK0NBTzJCO0FBQzNCLDhDQUE2QztBQUU3QyxxREFBcUY7QUFFckYsOERBQTBEO0FBRTFELE1BQU0sWUFBWSxHQUFHLElBQUEsa0NBQWUsR0FBRSxDQUFDLE1BQU0sQ0FBQztBQUU5QyxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUUzQyxNQUFNLGFBQWEsR0FBRyx1QkFBWSxDQUFDLGFBQWEsQ0FBQztBQUdqRCxPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0FBRXhDLFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxLQUFLO0lBQ2hDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQztJQUN6QixNQUFNLEtBQUssR0FBRyxJQUFJLHdCQUFhLEVBQUUsQ0FBQztJQUNsQyxNQUFNLFFBQVEsR0FBRyxrQ0FBa0MsQ0FBQztJQUNwRCxNQUFNLFlBQVksR0FBRyxrQ0FBa0MsQ0FBQztJQUN4RCxNQUFNLGNBQWMsR0FBRyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLENBQUM7SUFFckUsSUFBSSxPQUEyQixDQUFDO0lBQ2hDLElBQUksR0FBVSxDQUFDO0lBQ2YsSUFBSSxLQUFhLENBQUM7SUFDbEIsSUFBSSxRQUErQixDQUFDO0lBQ3BDLElBQUksTUFBYyxDQUFD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LEVBQUUsa0JBQWtCLEVBQUU7WUFDN0QsRUFBRSxJQUFJLEVBQUUsMEJBQTBCLEVBQUUsS0FBSyxFQUFFLG9CQUFvQixFQUFFO1NBQ2xFLENBQ0YsQ0FBQztRQUVGLE9BQU8sYUFBYSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxLQUFLLFVBQVUsaUJBQWlCLENBQUMsTUFRaEM7UUFDQyxNQUFNLGFBQWEsR0FBRyxNQUFNLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTFELElBQUksQ0FBQyxLQUFLLENBQUM7YUFDUixPQUFPLEVBQUU7YUFDVCxJQUFJLENBQUMsV0FBVyxNQUFNLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7YUFDbEYsS0FBSyxDQUFDLEdBQUcsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUU3QixPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO0lBRUQsS0FBSyxVQUFVLFlBQVksQ0FBQyxNQUkzQjtRQUNDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQzthQUMxQixPQUFPLEVBQUU7YUFDVCxJQUFJLENBQUMsV0FBVyxNQUFNLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2FBQ3hGLEtBQUssQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRS9CLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDO0lBQ0QsMEJBQTBCO0FBQzVCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgbm9jayA9IHJlcXVpcmUoJ25vY2snKTtcbmltcG9ydCAqIGFzIG9wZW5wZ3AgZnJvbSAnb3BlbnBncCc7XG5pbXBvcnQgc2hvdWxkID0gcmVxdWlyZSgnc2hvdWxkJyk7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5cbmltcG9ydCB7XG4gIG1vY2tTZXJpYWxpemVkQ2hhbGxlbmdlV2l0aFByb29mcyxcbiAgbW9ja1NlcmlhbGl6ZWRDaGFsbGVuZ2VXaXRoUHJvb2ZzMixcbiAgVGVzdGFibGVCRyxcbiAgVGVzdEJpdEdvLFxufSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R28sIGNyZWF0ZVNoYXJlZERhdGFQcm9vZiwgVHNzVXRpbHMsIFJlcXVlc3RUeXBlIH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vc3JjJztcbmltcG9ydCB7XG4gIEJhY2t1cEdwZ0tleSxcbiAgQWRkS2V5Y2hhaW5PcHRpb25zLFxuICBCYWNrdXBLZXlTaGFyZSxcbiAgQmFzZUNvaW4sXG4gIEJpdGdvR1BHUHVibGljS2V5LFxuICBCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZSxcbiAgY29tbW9uLFxuICBFY2RzYSxcbiAgRUNEU0EsXG4gIEVDRFNBTWV0aG9kcyxcbiAgRUNEU0FVdGlscyxcbiAgRW50ZXJwcmlzZURhdGEsXG4gIEtleWNoYWluLFxuICBSZXF1ZXN0VHJhY2VyLFxuICBTaWduYXR1cmVTaGFyZVJlY29yZCxcbiAgU2lnbmF0dXJlU2hhcmVUeXBlLFxuICBUeFJlcXVlc3QsXG4gIFdhbGxldCxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IEVjZHNhUGFpbGxpZXJQcm9vZiwgRWNkc2FSYW5nZVByb29mLCBFY2RzYVR5cGVzLCBoZXhUb0JpZ0ludCB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5pbXBvcnQgeyBrZXlTaGFyZXMsIG90aGVyS2V5U2hhcmVzIH0gZnJvbSAnLi4vLi4vLi4vZml4dHVyZXMvdHNzL2VjZHNhRml4dHVyZXMnO1xuaW1wb3J0IHsgbm9ja1NlbmRTaWduYXR1cmVTaGFyZVdpdGhSZXNwb25zZSB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7XG4gIGNyZWF0ZVdhbGxldFNpZ25hdHVyZXMsXG4gIG5vY2tHZXRDaGFsbGVuZ2UsXG4gIG5vY2tHZXRDaGFsbGVuZ2VzLFxuICBub2NrR2V0RW50ZXJwcmlzZSxcbiAgbm9ja0dldFNpZ25pbmdLZXksXG4gIG5vY2tHZXRUeFJlcXVlc3QsXG59IGZyb20gJy4uLy4uL3Rzcy9oZWxwZXJzJztcbmltcG9ydCB7IGJpcDMyLCBlY2MgfSBmcm9tICdAYml0Z28vdXR4by1saWInO1xuaW1wb3J0IHsgSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBtb2NrQ2hhbGxlbmdlQSwgbW9ja0NoYWxsZW5nZUIsIG1vY2tDaGFsbGVuZ2VDIH0gZnJvbSAnLi9tb2Nrcy9lY2RzYU50aWxkZSc7XG5cbmltcG9ydCB7IGxvYWRXZWJBc3NlbWJseSB9IGZyb20gJ0BiaXRnby9zZGstb3BlbnNzbGJ5dGVzJztcblxuY29uc3Qgb3BlblNTTEJ5dGVzID0gbG9hZFdlYkFzc2VtYmx5KCkuYnVmZmVyO1xuXG5jb25zdCBjcmVhdGVLZWNjYWtIYXNoID0gcmVxdWlyZSgna2VjY2FrJyk7XG5cbmNvbnN0IGVuY3J5cHROU2hhcmUgPSBFQ0RTQU1ldGhvZHMuZW5jcnlwdE5TaGFyZTtcbnR5cGUgS2V5U2hhcmUgPSBFQ0RTQS5LZXlTaGFyZTtcblxub3BlbnBncC5jb25maWcucmVqZWN0Q3VydmVzID0gbmV3IFNldCgpO1xuXG5kZXNjcmliZSgnVFNTIEVjZHNhIFV0aWxzOicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgY29pbk5hbWUgPSAnaHRldGgnO1xuICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gIGNvbnN0IHdhbGxldElkID0gJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJztcbiAgY29uc3QgZW50ZXJwcmlzZUlkID0gJzY0NDkxNTNhNmY2YmMyMDAwNmQ2Njc3MWNkYmUxNWQzJztcbiAgY29uc3QgZW50ZXJwcmlzZURhdGEgPSB7IGlkOiBlbnRlcnByaXNlSWQsIG5hbWU6ICdUZXN0IEVudGVycHJpc2UnIH07XG5cbiAgbGV0IHNhbmRib3g6IHNpbm9uLlNpbm9uU2FuZGJveDtcbiAgbGV0IE1QQzogRWNkc2E7XG4gIGxldCBiZ1VybDogc3RyaW5nO1xuICBsZXQgdHNzVXRpbHM6IEVDRFNBVXRpbHMuRWNkc2FVdGlscztcbiAgbGV0IHdhbGxldDogV2FsbGV0O1xuICBsZXQgYml0Z286IFRlc3RhYmxlQkcgJiBCaXRHbztcbiAgbGV0IGJhc2VDb2luOiBCYXNlQ29pbjtcbiAgbGV0IGJpdGdvS2V5U2hhcmU7XG4gIGxldCB1c2VyS2V5U2hhcmU6IEtleVNoYXJlO1xuICBsZXQgYmFja3VwS2V5U2hhcmU6IEtleVNoYXJlO1xuICBsZXQgYml0Z29QdWJsaWNLZXk6IG9wZW5wZ3AuS2V5O1xuXG4gIGxldCB1c2VyR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz4gJiB7XG4gICAgcmV2b2NhdGlvbkNlcnRpZmljYXRlOiBzdHJpbmc7XG4gIH07XG4gIGxldCB1c2VyTG9jYWxCYWNrdXBHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPiAmIHtcbiAgICByZXZvY2F0aW9uQ2VydGlmaWNhdGU6IHN0cmluZztcbiAgfTtcbiAgbGV0IGJpdEdvR1BHS2V5UGFpcjogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+ICYge1xuICAgIHJldm9jYXRpb25DZXJ0aWZpY2F0ZTogc3RyaW5nO1xuICB9O1xuICBsZXQgbm9ja2VkQml0R29LZXljaGFpbjogS2V5Y2hhaW47XG4gIGxldCBub2NrZWRVc2VyS2V5Y2hhaW46IEtleWNoYWluO1xuXG4gIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIE1QQyA9IG5ldyBFY2RzYSgpO1xuICAgIHVzZXJLZXlTaGFyZSA9IGtleVNoYXJlcy51c2VyS2V5U2hhcmU7XG4gICAgYmFja3VwS2V5U2hhcmUgPSBrZXlTaGFyZXMuYmFja3VwS2V5U2hhcmU7XG4gICAgYml0Z29LZXlTaGFyZSA9IGtleVNoYXJlcy5iaXRnb0tleVNoYXJlO1xuXG4gICAgY29uc3QgZ3BnS2V5UHJvbWlzZXMgPSBbXG4gICAgICBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgICAgdXNlcklEczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICd0ZXN0JyxcbiAgICAgICAgICAgIGVtYWlsOiAndGVzdEB0ZXN0LmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgY3VydmU6ICdzZWNwMjU2azEnLFxuICAgICAgfSksXG4gICAgICBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgICAgdXNlcklEczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdiYWNrdXAnLFxuICAgICAgICAgICAgZW1haWw6ICdiYWNrdXBAdGVzdC5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGN1cnZlOiAnc2VjcDI1NmsxJyxcbiAgICAgIH0pLFxuICAgICAgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICAgIHVzZXJJRHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnYml0Z28nLFxuICAgICAgICAgICAgZW1haWw6ICdiaXRnb0B0ZXN0LmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgY3VydmU6ICdzZWNwMjU2azEnLFxuICAgICAgfSksXG4gICAgXTtcbiAgICBbdXNlckdwZ0tleSwgdXNlckxvY2FsQmFja3VwR3BnS2V5LCBiaXRHb0dQR0tleVBhaXJdID0gYXdhaXQgUHJvbWlzZS5hbGwoZ3BnS2V5UHJvbWlzZXMpO1xuICAgIGJpdGdvUHVibGljS2V5ID0gYXdhaXQgb3BlbnBncC5yZWFkS2V5KHsgYXJtb3JlZEtleTogYml0R29HUEdLZXlQYWlyLnB1YmxpY0tleSB9KTtcbiAgICBjb25zdCBjb25zdGFudHMgPSB7XG4gICAgICBtcGM6IHtcbiAgICAgICAgYml0Z29QdWJsaWNLZXk6IGJpdEdvR1BHS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICB9LFxuICAgIH07XG5cbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcblxuICAgIGJhc2VDb2luID0gYml0Z28uY29pbihjb2luTmFtZSk7XG5cbiAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaTtcblxuICAgIC8vIFRPRE8oV1AtMzQ2KTogc2RrLXRlc3QgbW9ja3MgY29uZmxpY3Qgc28gd2UgY2FuJ3QgdXNlIHBlcnNpc3RcbiAgICBub2NrKGJnVXJsKS5nZXQoJy9hcGkvdjEvY2xpZW50L2NvbnN0YW50cycpLnRpbWVzKDE2KS5yZXBseSgyMDAsIHsgdHRsOiAzNjAwLCBjb25zdGFudHMgfSk7XG5cbiAgICBjb25zdCBub2NrUHJvbWlzZXMgPSBbXG4gICAgICBub2NrQml0Z29LZXljaGFpbih7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleVNoYXJlLFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXksXG4gICAgICAgIGJpdGdvR3BnS2V5OiBiaXRHb0dQR0tleVBhaXIsXG4gICAgICB9KSxcbiAgICAgIG5vY2tLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lLCBrZXlDaGFpbjogeyBpZDogJzEnLCBwdWI6ICcnLCB0eXBlOiAndHNzJyB9LCBzb3VyY2U6ICd1c2VyJyB9KSxcbiAgICAgIG5vY2tLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lLCBrZXlDaGFpbjogeyBpZDogJzInLCBwdWI6ICcnLCB0eXBlOiAndHNzJyB9LCBzb3VyY2U6ICdiYWNrdXAnIH0pLFxuICAgIF07XG4gICAgW25vY2tlZEJpdEdvS2V5Y2hhaW4sIG5vY2tlZFVzZXJLZXljaGFpbl0gPSBhd2FpdCBQcm9taXNlLmFsbChub2NrUHJvbWlzZXMpO1xuXG4gICAgY29uc3Qgd2FsbGV0RGF0YSA9IHtcbiAgICAgIGlkOiB3YWxsZXRJZCxcbiAgICAgIGVudGVycHJpc2U6IGVudGVycHJpc2VJZCxcbiAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgY29pblNwZWNpZmljOiB7fSxcbiAgICAgIG11bHRpc2lnVHlwZTogJ3RzcycsXG4gICAgfTtcbiAgICB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgd2FsbGV0RGF0YSk7XG4gICAgdHNzVXRpbHMgPSBuZXcgRUNEU0FVdGlscy5FY2RzYVV0aWxzKGJpdGdvLCBiYXNlQ29pbiwgd2FsbGV0KTtcbiAgfSk7XG5cbiAgYWZ0ZXIoZnVuY3Rpb24gKCkge1xuICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RTUyBrZXkgY2hhaW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY3JlYXRlIGJhY2t1cCBrZXkgc2hhcmUgaGVsZCBieSBCaXRHbycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGVudGVycHJpc2VJZCA9ICdlbnRlcnByaXNlIGlkJztcbiAgICAgIGNvbnN0IGV4cGVjdGVkS2V5U2hhcmUgPSBhd2FpdCBub2NrQ3JlYXRlQml0Z29IZWxkQmFja3VwS2V5U2hhcmUoXG4gICAgICAgIGNvaW5OYW1lLFxuICAgICAgICBlbnRlcnByaXNlSWQsXG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRHb0dQR0tleVBhaXJcbiAgICAgICk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZSh1c2VyR3BnS2V5LCBlbnRlcnByaXNlSWQpO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcWwoZXhwZWN0ZWRLZXlTaGFyZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZpbmFsaXplIGJhY2t1cCBrZXkgc2hhcmUgaGVsZCBieSBCaXRHbycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbW1vbktleWNoYWluID0gJzQ0MjgnO1xuICAgICAgY29uc3Qgb3JpZ2luYWxLZXlTaGFyZSA9IGF3YWl0IGNyZWF0ZUluY29tcGxldGVCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZShcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdEdvR1BHS2V5UGFpclxuICAgICAgKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkRmluYWxLZXlTaGFyZSA9IGF3YWl0IG5vY2tGaW5hbGl6ZUJpdGdvSGVsZEJhY2t1cEtleVNoYXJlKFxuICAgICAgICBjb2luTmFtZSxcbiAgICAgICAgb3JpZ2luYWxLZXlTaGFyZSxcbiAgICAgICAgY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYml0R29HUEdLZXlQYWlyLFxuICAgICAgICBub2NrZWRCaXRHb0tleWNoYWluXG4gICAgICApO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0c3NVdGlscy5maW5hbGl6ZUJpdGdvSGVsZEJhY2t1cEtleVNoYXJlKFxuICAgICAgICBvcmlnaW5hbEtleVNoYXJlLmlkLFxuICAgICAgICBjb21tb25LZXljaGFpbixcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBub2NrZWRCaXRHb0tleWNoYWluLFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiaXRnb1B1YmxpY0tleVxuICAgICAgKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZXFsKGV4cGVjdGVkRmluYWxLZXlTaGFyZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdldCB0aGUgcmVzcGVjdGl2ZSBiYWNrdXAga2V5IHNoYXJlcyBiYXNlZCBvbiBwcm92aWRlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGVudGVycHJpc2VJZCA9ICdlbnRlcnByaXNlIGlkJztcbiAgICAgIGF3YWl0IG5vY2tDcmVhdGVCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZShjb2luTmFtZSwgZW50ZXJwcmlzZUlkLCB1c2VyR3BnS2V5LCBiYWNrdXBLZXlTaGFyZSwgYml0R29HUEdLZXlQYWlyKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlcyA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJhY2t1cEtleVNoYXJlcygpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJhY2t1cEtleVNoYXJlcy51c2VySGVsZEtleVNoYXJlKTtcbiAgICAgIHNob3VsZC5ub3QuZXhpc3QoYmFja3VwS2V5U2hhcmVzLmJpdEdvSGVsZEtleVNoYXJlcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdldCB0aGUgY29ycmVjdCBiaXRnbyBncGcga2V5IGJhc2VkIG9uIGNvaW4gYW5kIGZlYXR1cmUgZmxhZ3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBuaXRyb0dQR0tleXBhaXIgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgICAgdXNlcklEczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdiaXRnbyBuaXRybycsXG4gICAgICAgICAgICBlbWFpbDogJ2JpdGdvQHRlc3QuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBub2NrR1BHS2V5ID0gYXdhaXQgbm9ja0dldEJpdGdvUHVibGljS2V5QmFzZWRPbkZlYXR1cmVGbGFncyhjb2luTmFtZSwgJ2VudGVycHJpc2VfaWQnLCBuaXRyb0dQR0tleXBhaXIpO1xuICAgICAgY29uc3QgeyBtcGN2MlB1YmxpY0tleTogYml0Z29HcGdQdWJsaWNLZXkgfSA9IGF3YWl0IHRzc1V0aWxzLmdldEJpdGdvR3BnUHVia2V5QmFzZWRPbkZlYXR1cmVGbGFncyhcbiAgICAgICAgJ2VudGVycHJpc2VfaWQnXG4gICAgICApO1xuICAgICAgc2hvdWxkLmVxdWFsKG5vY2tHUEdLZXkucHVibGljS2V5LCBiaXRnb0dwZ1B1YmxpY0tleS5hcm1vcigpKTtcbiAgICB9KTtcblxuICAgIGl0KCdnZXRCYWNrdXBFbmNyeXB0ZWROU2hhcmUgc2hvdWxkIGdldCB2YWxpZCBlbmNyeXB0ZWQgbiBzaGFyZXMgYmFzZWQgb24gcHJvdmlkZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiaXRnb0dwZ0tleVB1YktleSA9IGF3YWl0IHRzc1V0aWxzLmdldEJpdGdvUHVibGljR3BnS2V5KCk7XG4gICAgICAvLyBCYWNrdXAga2V5IGhlbGQgYnkgdXNlclxuICAgICAgY29uc3QgYmFja3VwU2hhcmVIb2xkZXJOZXc6IEJhY2t1cEtleVNoYXJlID0ge1xuICAgICAgICB1c2VySGVsZEtleVNoYXJlOiBiYWNrdXBLZXlTaGFyZSxcbiAgICAgIH07XG4gICAgICBjb25zdCBiYWNrdXBUb0JpdGdvRW5jcnlwdGVkTlNoYXJlID0gYXdhaXQgdHNzVXRpbHMuZ2V0QmFja3VwRW5jcnlwdGVkTlNoYXJlKFxuICAgICAgICBiYWNrdXBTaGFyZUhvbGRlck5ldyxcbiAgICAgICAgMyxcbiAgICAgICAgYml0Z29HcGdLZXlQdWJLZXkuYXJtb3IoKSxcbiAgICAgICAgdXNlckdwZ0tleVxuICAgICAgKTtcbiAgICAgIGNvbnN0IGVuY3J5cHRlZE5TaGFyZSA9IGF3YWl0IGVuY3J5cHROU2hhcmUoYmFja3VwS2V5U2hhcmUsIDMsIGJpdGdvR3BnS2V5UHViS2V5LmFybW9yKCksIHVzZXJHcGdLZXkpO1xuICAgICAgLy8gY2FudCB2ZXJpZnkgdGhlIGVuY3J5cHRlZCBzaGFyZXMsIHNpbmNlIHRoZXkgd2lsbCBiZSBlbmNyeXB0ZWQgd2l0aCBkaWZmLiB2YWx1ZXNcbiAgICAgIHNob3VsZC5lcXVhbChiYWNrdXBUb0JpdGdvRW5jcnlwdGVkTlNoYXJlLnB1YmxpY1NoYXJlLCBlbmNyeXB0ZWROU2hhcmUucHVibGljU2hhcmUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1Mga2V5IGNoYWlucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJhY2t1cFNoYXJlSG9sZGVyOiBCYWNrdXBLZXlTaGFyZSA9IHtcbiAgICAgICAgdXNlckhlbGRLZXlTaGFyZTogYmFja3VwS2V5U2hhcmUsXG4gICAgICB9O1xuICAgICAgY29uc3QgYmFja3VwR3BnS2V5OiBCYWNrdXBHcGdLZXkgPSB1c2VyTG9jYWxCYWNrdXBHcGdLZXk7XG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlQml0Z29LZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZTogYmFja3VwU2hhcmVIb2xkZXIsXG4gICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb1B1YmxpY0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdXNlcnNLZXlDaGFpblByb21pc2VzID0gW1xuICAgICAgICB0c3NVdGlscy5jcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluKFxuICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgdXNlckxvY2FsQmFja3VwR3BnS2V5LFxuICAgICAgICAgIGJpdGdvUHVibGljS2V5LFxuICAgICAgICAgIDEsXG4gICAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgICAgJ3Bhc3NwaHJhc2UnXG4gICAgICAgICksXG4gICAgICAgIHRzc1V0aWxzLmNyZWF0ZVBhcnRpY2lwYW50S2V5Y2hhaW4oXG4gICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXksXG4gICAgICAgICAgYml0Z29QdWJsaWNLZXksXG4gICAgICAgICAgMixcbiAgICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgICAncGFzc3BocmFzZSdcbiAgICAgICAgKSxcbiAgICAgIF07XG4gICAgICBjb25zdCBbdXNlcktleWNoYWluLCBiYWNrdXBLZXljaGFpbl0gPSBhd2FpdCBQcm9taXNlLmFsbCh1c2Vyc0tleUNoYWluUHJvbWlzZXMpO1xuXG4gICAgICBiaXRnb0tleWNoYWluLnNob3VsZC5kZWVwRXF1YWwobm9ja2VkQml0R29LZXljaGFpbik7XG4gICAgICB1c2VyS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRVc2VyS2V5Y2hhaW4pO1xuXG4gICAgICAvLyB1bmVuY3J5cHRlZCBgcHJ2YCBwcm9wZXJ0eSBzaG91bGQgZXhpc3Qgb24gYmFja3VwIGtleWNoYWluXG4gICAgICBjb25zdCBrZXlDaGFpblBydiA9IEpTT04ucGFyc2UoYmFja3VwS2V5Y2hhaW4ucHJ2ID8/ICcnKTtcbiAgICAgIF8uaXNFcXVhbChrZXlDaGFpblBydi5wU2hhcmUsIGJhY2t1cEtleVNoYXJlLnBTaGFyZSkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIF8uaXNFcXVhbChrZXlDaGFpblBydi5iaXRnb05TaGFyZSwgYml0Z29LZXlTaGFyZS5uU2hhcmVzWzJdKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgXy5pc0VxdWFsKGtleUNoYWluUHJ2LnVzZXJOU2hhcmUsIHVzZXJLZXlTaGFyZS5uU2hhcmVzWzJdKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJhY2t1cEtleWNoYWluLmVuY3J5cHRlZFBydik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNlbmQgd2ViYXV0aG5JbmZvICh3aXRoIGVudGVycHJpc2VJZCkgb24gdGhlIHVzZXIga2V5Y2hhaW4gd2hlbiB3ZWJhdXRobkluZm8gaXMgcHJvdmlkZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBLZWVwIHRoZSByZWFsIGNyeXB0byBkZXBzIChjb25zdGFudHMgdy8gYml0Z28gZ3BnIGtleSBmb3IgdmVyaWZ5V2FsbGV0U2lnbmF0dXJlcykgYW5kXG4gICAgICAvLyBjYXB0dXJlIHRoZSB1c2VyIGtleWNoYWluIGFkZCgpIHBhcmFtcyBieSBzdHViYmluZyBiYXNlQ29pbi5rZXljaGFpbnMoKS5cbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoJy9hcGkvdjEvY2xpZW50L2NvbnN0YW50cycpXG4gICAgICAgIC50aW1lcygxNilcbiAgICAgICAgLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50czogeyBtcGM6IHsgYml0Z29QdWJsaWNLZXk6IGJpdEdvR1BHS2V5UGFpci5wdWJsaWNLZXkgfSB9IH0pO1xuXG4gICAgICBjb25zdCBhZGRTdHViID0gc2FuZGJveC5zdHViKCkucmVzb2x2ZXMoeyBpZDogJzEnLCBwdWI6ICcnLCB0eXBlOiAndHNzJyB9KTtcbiAgICAgIHNhbmRib3guc3R1YihiYXNlQ29pbiwgJ2tleWNoYWlucycpLnJldHVybnMoeyBhZGQ6IGFkZFN0dWIgfSBhcyB1bmtub3duIGFzIFJldHVyblR5cGU8QmFzZUNvaW5bJ2tleWNoYWlucyddPik7XG5cbiAgICAgIGNvbnN0IGVudGVycHJpc2VJZCA9ICdlbnRlcnByaXNlX2lkJztcbiAgICAgIGNvbnN0IHdlYmF1dGhuSW5mbyA9IHsgb3RwRGV2aWNlSWQ6ICdkZXZpY2UtMTIzJywgcHJmU2FsdDogJ3NhbHQtYWJjJywgcGFzc3BocmFzZTogJ3ByZi1kZXJpdmVkLXBhc3NwaHJhc2UnIH07XG4gICAgICBhd2FpdCB0c3NVdGlscy5jcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluKFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXksXG4gICAgICAgIGJpdGdvUHVibGljS2V5LFxuICAgICAgICAxLFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBub2NrZWRCaXRHb0tleWNoYWluLFxuICAgICAgICAncGFzc3BocmFzZScsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgd2ViYXV0aG5JbmZvLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIGVudGVycHJpc2VJZFxuICAgICAgKTtcblxuICAgICAgLy8gVXNlciBrZXljaGFpbiBtdXN0IGNhcnJ5IHdlYmF1dGhuSW5mbyAodGhlIGZpZWxkIHRoZSBiYWNrZW5kIFBPU1QgL2tleSBjb25zdW1lcyksIGluY2x1ZGluZ1xuICAgICAgLy8gZW50ZXJwcmlzZUlkLCBhbmQgbXVzdCBOT1QgdXNlIHRoZSBkZXByZWNhdGVkIHdlYmF1dGhuRGV2aWNlcyBhcnJheS5cbiAgICAgIGFzc2VydC5vayhhZGRTdHViLmNhbGxlZE9uY2UsICdrZXljaGFpbnMoKS5hZGQgc2hvdWxkIGhhdmUgYmVlbiBjYWxsZWQgZm9yIHRoZSB1c2VyIGtleWNoYWluJyk7XG4gICAgICBjb25zdCBib2R5ID0gYWRkU3R1Yi5maXJzdENhbGwuYXJnc1swXSBhcyBBZGRLZXljaGFpbk9wdGlvbnM7XG4gICAgICBhc3NlcnQub2soYm9keS53ZWJhdXRobkluZm8sICd1c2VyIGtleWNoYWluIGJvZHkgc2hvdWxkIGluY2x1ZGUgd2ViYXV0aG5JbmZvJyk7XG4gICAgICBhc3NlcnQuZXF1YWwoYm9keS53ZWJhdXRobkluZm8ub3RwRGV2aWNlSWQsIHdlYmF1dGhuSW5mby5vdHBEZXZpY2VJZCk7XG4gICAgICBhc3NlcnQuZXF1YWwoYm9keS53ZWJhdXRobkluZm8ucHJmU2FsdCwgd2ViYXV0aG5JbmZvLnByZlNhbHQpO1xuICAgICAgYXNzZXJ0LmVxdWFsKGJvZHkud2ViYXV0aG5JbmZvLmVudGVycHJpc2VJZCwgZW50ZXJwcmlzZUlkKTtcbiAgICAgIGFzc2VydC5vayhib2R5LndlYmF1dGhuSW5mby5lbmNyeXB0ZWRQcnYsICdlbmNyeXB0ZWRQcnYgc2hvdWxkIGJlIHNldCcpO1xuICAgICAgYXNzZXJ0Lm9rKGF3YWl0IGJpdGdvLmRlY3J5cHQoeyBpbnB1dDogYm9keS53ZWJhdXRobkluZm8uZW5jcnlwdGVkUHJ2LCBwYXNzd29yZDogd2ViYXV0aG5JbmZvLnBhc3NwaHJhc2UgfSkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJvZHkud2ViYXV0aG5EZXZpY2VzLCB1bmRlZmluZWQsICdkZXByZWNhdGVkIHdlYmF1dGhuRGV2aWNlcyBzaG91bGQgbm90IGJlIHNlbnQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgVFNTIGtleSBjaGFpbnMgd2l0aCBvcHRpb25hbCBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBlbnRlcnByaXNlID0gJ2VudGVycHJpc2VfaWQnO1xuICAgICAgY29uc3QgYmFja3VwU2hhcmVIb2xkZXI6IEJhY2t1cEtleVNoYXJlID0ge1xuICAgICAgICB1c2VySGVsZEtleVNoYXJlOiBiYWNrdXBLZXlTaGFyZSxcbiAgICAgIH07XG4gICAgICBjb25zdCBiYWNrdXBHcGdLZXk6IEJhY2t1cEdwZ0tleSA9IHVzZXJMb2NhbEJhY2t1cEdwZ0tleTtcbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlOiBiYWNrdXBTaGFyZUhvbGRlcixcbiAgICAgICAgZW50ZXJwcmlzZSxcbiAgICAgICAgYml0Z29QdWJsaWNHcGdLZXk6IGJpdGdvUHVibGljS2V5LFxuICAgICAgfSk7XG4gICAgICBjb25zdCB1c2Vyc0tleUNoYWluUHJvbWlzZXMgPSBbXG4gICAgICAgIHRzc1V0aWxzLmNyZWF0ZVBhcnRpY2lwYW50S2V5Y2hhaW4oXG4gICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXksXG4gICAgICAgICAgYml0Z29QdWJsaWNLZXksXG4gICAgICAgICAgMSxcbiAgICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgICAncGFzc3BocmFzZScsXG4gICAgICAgICAgJ29yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZSdcbiAgICAgICAgKSxcbiAgICAgICAgdHNzVXRpbHMuY3JlYXRlUGFydGljaXBhbnRLZXljaGFpbihcbiAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgIHVzZXJMb2NhbEJhY2t1cEdwZ0tleSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0tleSxcbiAgICAgICAgICAyLFxuICAgICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICAgICdwYXNzcGhyYXNlJ1xuICAgICAgICApLFxuICAgICAgXTtcblxuICAgICAgY29uc3QgW3VzZXJLZXljaGFpbiwgYmFja3VwS2V5Y2hhaW5dID0gYXdhaXQgUHJvbWlzZS5hbGwodXNlcnNLZXlDaGFpblByb21pc2VzKTtcbiAgICAgIGJpdGdvS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcbiAgICAgIHVzZXJLZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZFVzZXJLZXljaGFpbik7XG5cbiAgICAgIC8vIHVuZW5jcnlwdGVkIGBwcnZgIHByb3BlcnR5IHNob3VsZCBleGlzdCBvbiBiYWNrdXAga2V5Y2hhaW5cbiAgICAgIGNvbnN0IGtleUNoYWluUHJ2ID0gSlNPTi5wYXJzZShiYWNrdXBLZXljaGFpbi5wcnYgPz8gJycpO1xuICAgICAgXy5pc0VxdWFsKGtleUNoYWluUHJ2LnBTaGFyZSwgYmFja3VwS2V5U2hhcmUucFNoYXJlKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgXy5pc0VxdWFsKGtleUNoYWluUHJ2LmJpdGdvTlNoYXJlLCBiaXRnb0tleVNoYXJlLm5TaGFyZXNbMl0pLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBfLmlzRXF1YWwoa2V5Q2hhaW5QcnYudXNlck5TaGFyZSwgdXNlcktleVNoYXJlLm5TaGFyZXNbMl0pLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBzaG91bGQuZXhpc3QoYmFja3VwS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBnZW5lcmF0ZSBUU1Mga2V5IGNoYWlucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJhY2t1cFNoYXJlSG9sZGVyOiBCYWNrdXBLZXlTaGFyZSA9IHtcbiAgICAgICAgdXNlckhlbGRLZXlTaGFyZTogYmFja3VwS2V5U2hhcmUsXG4gICAgICB9O1xuICAgICAgY29uc3QgYmFja3VwR3BnS2V5OiBCYWNrdXBHcGdLZXkgPSB1c2VyTG9jYWxCYWNrdXBHcGdLZXk7XG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlQml0Z29LZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZTogYmFja3VwU2hhcmVIb2xkZXIsXG4gICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb1B1YmxpY0tleSxcbiAgICAgIH0pO1xuICAgICAgYml0Z29LZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZEJpdEdvS2V5Y2hhaW4pO1xuICAgICAgY29uc3QgdGVzdEtleVNoYXJlcyA9IG90aGVyS2V5U2hhcmVzO1xuICAgICAgY29uc3QgdGVzdENhc2VzUHJvbWlzZXMgPSBbXG4gICAgICAgIHRzc1V0aWxzXG4gICAgICAgICAgLmNyZWF0ZVBhcnRpY2lwYW50S2V5Y2hhaW4oXG4gICAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgICAgdXNlckxvY2FsQmFja3VwR3BnS2V5LFxuICAgICAgICAgICAgYml0Z29QdWJsaWNLZXksXG4gICAgICAgICAgICAxLFxuICAgICAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICAgICAgdGVzdEtleVNoYXJlc1swXSxcbiAgICAgICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgICAgICAncGFzc3BocmFzZSdcbiAgICAgICAgICApXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0NvbW1vbiBrZXljaGFpbnMgZG8gbm90IG1hdGNoJyksXG4gICAgICAgIHRzc1V0aWxzXG4gICAgICAgICAgLmNyZWF0ZVBhcnRpY2lwYW50S2V5Y2hhaW4oXG4gICAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgICAgdXNlckxvY2FsQmFja3VwR3BnS2V5LFxuICAgICAgICAgICAgYml0Z29QdWJsaWNLZXksXG4gICAgICAgICAgICAxLFxuICAgICAgICAgICAgdGVzdEtleVNoYXJlc1sxXSxcbiAgICAgICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgICAgICdwYXNzcGhyYXNlJ1xuICAgICAgICAgIClcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnQ29tbW9uIGtleWNoYWlucyBkbyBub3QgbWF0Y2gnKSxcbiAgICAgICAgdHNzVXRpbHNcbiAgICAgICAgICAuY3JlYXRlUGFydGljaXBhbnRLZXljaGFpbihcbiAgICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXksXG4gICAgICAgICAgICBiaXRnb1B1YmxpY0tleSxcbiAgICAgICAgICAgIDIsXG4gICAgICAgICAgICB0ZXN0S2V5U2hhcmVzWzJdLFxuICAgICAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICAgICAgJ3Bhc3NwaHJhc2UnXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdDb21tb24ga2V5Y2hhaW5zIGRvIG5vdCBtYXRjaCcpLFxuICAgICAgICB0c3NVdGlsc1xuICAgICAgICAgIC5jcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluKFxuICAgICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICAgIHVzZXJMb2NhbEJhY2t1cEdwZ0tleSxcbiAgICAgICAgICAgIGJpdGdvUHVibGljS2V5LFxuICAgICAgICAgICAgMixcbiAgICAgICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgICAgIHRlc3RLZXlTaGFyZXNbM10sXG4gICAgICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICAgICAgJ3Bhc3NwaHJhc2UnXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdDb21tb24ga2V5Y2hhaW5zIGRvIG5vdCBtYXRjaCcpLFxuICAgICAgXTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHRlc3RDYXNlc1Byb21pc2VzKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluIHNob3VsZCBwcm9kdWNlIGEgdjItZW5jcnlwdGVkIGVuY3J5cHRlZFBydiB3aGVuIGVuY3J5cHRpb25WZXJzaW9uOiAyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFzc3BocmFzZSA9ICd0ZXN0LXBhc3NwaHJhc2UnO1xuICAgICAgLy8gU3R1YiBrZXljaGFpbnMuYWRkIHRvIGNhcHR1cmUgdGhlIHBhcmFtcyBzZW50IHRvIHRoZSBBUEkgc28gd2UgY2FuIGluc3BlY3QgZW5jcnlwdGVkUHJ2XG4gICAgICBjb25zdCBhZGRTdHViID0gc2lub24uc3R1YihiYXNlQ29pbi5rZXljaGFpbnMoKSwgJ2FkZCcpLnJlc29sdmVzKHsgaWQ6ICcxJywgcHViOiAnJywgdHlwZTogJ3RzcycgfSBhcyBLZXljaGFpbik7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0c3NVdGlscy5jcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluKFxuICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgdXNlckxvY2FsQmFja3VwR3BnS2V5LFxuICAgICAgICAgIGJpdGdvUHVibGljS2V5LFxuICAgICAgICAgIDEsXG4gICAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICAgIG5vY2tlZEJpdEdvS2V5Y2hhaW4sXG4gICAgICAgICAgcGFzc3BocmFzZSxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIDIgLy8gZW5jcnlwdGlvblZlcnNpb25cbiAgICAgICAgKTtcbiAgICAgICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UoYWRkU3R1Yik7XG4gICAgICAgIGNvbnN0IGFkZFBhcmFtcyA9IGFkZFN0dWIuZmlyc3RDYWxsLmFyZ3NbMF0gYXMgeyBlbmNyeXB0ZWRQcnY/OiBzdHJpbmcgfTtcbiAgICAgICAgYXNzZXJ0Lm9rKGFkZFBhcmFtcy5lbmNyeXB0ZWRQcnYsICdlbmNyeXB0ZWRQcnYgbXVzdCBiZSBwYXNzZWQgdG8ga2V5Y2hhaW5zLmFkZCcpO1xuICAgICAgICBjb25zdCBlbnZlbG9wZSA9IEpTT04ucGFyc2UoYWRkUGFyYW1zLmVuY3J5cHRlZFBydiEpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUudiwgMiwgJ2VuY3J5cHRlZFBydiBtdXN0IHVzZSB2MiAoQXJnb24yaWQpIGVudmVsb3BlJyk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhZGRTdHViLnJlc3RvcmUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBnZW5lcmF0ZSBUU1Mga2V5Y2hhaW5zIHdoZW4gcmVjZWl2ZWQgaW52YWxpZCBudW1iZXIgb2Ygd2FsbGV0IHNpZ25hdHVyZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5U2hhcmUsXG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIHVzZXJMb2NhbEJhY2t1cEdwZ0tleSxcbiAgICAgICAgYml0Z29HcGdLZXk6IGJpdEdvR1BHS2V5UGFpcixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBjZXJ0c1N0cmluZyA9IGF3YWl0IGNyZWF0ZVNoYXJlZERhdGFQcm9vZihiaXRHb0dQR0tleVBhaXIucHJpdmF0ZUtleSwgdXNlckdwZ0tleS5wdWJsaWNLZXksIFtdKTtcbiAgICAgIGNvbnN0IGNlcnRzS2V5ID0gYXdhaXQgb3BlbnBncC5yZWFkS2V5KHsgYXJtb3JlZEtleTogY2VydHNTdHJpbmcgfSk7XG4gICAgICBjb25zdCBmaW5hbEtleSA9IG5ldyBvcGVucGdwLlBhY2tldExpc3QoKTtcbiAgICAgIGNlcnRzS2V5LnRvUGFja2V0TGlzdCgpLmZvckVhY2goKHBhY2tldCkgPT4gZmluYWxLZXkucHVzaChwYWNrZXQpKTtcbiAgICAgIC8vIE9uY2UgdGhlIGZvbGxvd2luZyBQUiBoYXMgYmVlbiBtZXJnZWQgYW5kIHJlbGVhc2VkIHdlIG5vIGxvbmdlciBuZWVkIHRoZSB0cy1pZ25vcmU6XG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vb3BlbnBncGpzL29wZW5wZ3Bqcy9wdWxsLzE1NzZcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGJpdGdvS2V5Y2hhaW4ud2FsbGV0SFNNR1BHUHVibGljS2V5U2lncyA9IG9wZW5wZ3AuYXJtb3Iob3BlbnBncC5lbnVtcy5hcm1vci5wdWJsaWNLZXksIGZpbmFsS2V5LndyaXRlKCkpO1xuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLnZlcmlmeVdhbGxldFNpZ25hdHVyZXModXNlckxvY2FsQmFja3VwR3BnS2V5LnB1YmxpY0tleSwgdXNlckxvY2FsQmFja3VwR3BnS2V5LnB1YmxpY0tleSwgYml0Z29LZXljaGFpbiwgJycsIDEpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKGBJbnZhbGlkIHdhbGxldCBzaWduYXR1cmVzYCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gZ2VuZXJhdGUgVFNTIGtleWNoYWlucyB3aGVuIHdhbGxldCBzaWduYXR1cmUgZmluZ2VycHJpbnRzIGRvIG5vdCBtYXRjaCBwYXNzZWQgdXNlci9iYWNrdXAgZmluZ2VycHJpbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY3VzdG9tVXNlcktleVNoYXJlID0gYXdhaXQgTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgICAgY29uc3QgY3VzdG9tQmFja3VwS2V5U2hhcmUgPSBhd2FpdCBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG4gICAgICBjb25zdCBiYWNrdXBTaGFyZUhvbGRlcjogQmFja3VwS2V5U2hhcmUgPSB7XG4gICAgICAgIHVzZXJIZWxkS2V5U2hhcmU6IGN1c3RvbUJhY2t1cEtleVNoYXJlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGJhY2t1cEdwZ0tleTogQmFja3VwR3BnS2V5ID0gdXNlckxvY2FsQmFja3VwR3BnS2V5O1xuXG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlQml0Z29LZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlOiBjdXN0b21Vc2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlOiBiYWNrdXBTaGFyZUhvbGRlcixcbiAgICAgICAgYml0Z29QdWJsaWNHcGdLZXk6IGJpdGdvUHVibGljS2V5LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIHVzaW5nIHRoZSBiYWNrdXAgZ3BnIGhlcmUgaW5zdGVhZCBvZiB0aGUgdXNlciBncGcga2V5IHRvIHNpbXVsYXRlIHRoYXQgdGhlIGZpcnN0IHNpZ25hdHVyZSBoYXMgYSBkaWZmZXJlbnRcbiAgICAgIC8vIGZpbmdlcnByaW50IGZyb20gdGhlIHBhc3NlZCBpbiBmaXJzdCBncGcga2V5XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAudmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyh1c2VyTG9jYWxCYWNrdXBHcGdLZXkucHVibGljS2V5LCB1c2VyTG9jYWxCYWNrdXBHcGdLZXkucHVibGljS2V5LCBiaXRnb0tleWNoYWluLCAnJywgMSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgYGZpcnN0IHdhbGxldCBzaWduYXR1cmUncyBmaW5nZXJwcmludCBkb2VzIG5vdCBtYXRjaCBwYXNzZWQgdXNlciBncGcga2V5J3MgZmluZ2VycHJpbnRgXG4gICAgICAgICk7XG5cbiAgICAgIC8vIHVzaW5nIHRoZSB1c2VyIGdwZyBoZXJlIGluc3RlYWQgb2YgdGhlIGJhY2t1cCBncGcga2V5IHRvIHNpbXVsYXRlIHRoYXQgdGhlIHNlY29uZCBzaWduYXR1cmUgaGFzIGEgZGlmZmVyZW50XG4gICAgICAvLyBmaW5nZXJwcmludCBmcm9tIHRoZSBwYXNzZWQgaW4gc2Vjb25kIGdwZyBrZXlcbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC52ZXJpZnlXYWxsZXRTaWduYXR1cmVzKHVzZXJHcGdLZXkucHVibGljS2V5LCB1c2VyR3BnS2V5LnB1YmxpY0tleSwgYml0Z29LZXljaGFpbiwgJycsIDEpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIGBzZWNvbmQgd2FsbGV0IHNpZ25hdHVyZSdzIGZpbmdlcnByaW50IGRvZXMgbm90IG1hdGNoIHBhc3NlZCBiYWNrdXAgZ3BnIGtleSdzIGZpbmdlcnByaW50YFxuICAgICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2lnblR4UmVxdWVzdDonLCAoKSA9PiB7XG4gICAgY29uc3QgdHhSZXF1ZXN0SWQgPSAncmFuZG9taWRFY2RzYSc7XG4gICAgY29uc3QgdHhSZXF1ZXN0OiBUeFJlcXVlc3QgPSB7XG4gICAgICB0eFJlcXVlc3RJZCxcbiAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgLy8gaHRldGggdHhpZDogMHhjNWE3YmZlNmIxM2NlYWU1NjNkYTBmOWZlYWE5YzRhZDFjMTAxYTE1MzY2YTJhNDg4ODI4YTVkZDI3Y2I5ZGEzXG4gICAgICAgICAgICBzZXJpYWxpemVkVHhIZXg6XG4gICAgICAgICAgICAgICcwMmYzODI0MjY4ODA4NDQ0OGI5YjgwODQ0NDhiOWI5MDgzMDE2Mzc4OTRhMWNmYjlkNTFjMGFmMTkxZmYyMWM1ZjBmMDE3MjNlMDU2ZjdkYzEyODY1YWYzMTA3YTQwMDA4MGMwODA4MDgwJyxcbiAgICAgICAgICAgIHNpZ25hYmxlSGV4OlxuICAgICAgICAgICAgICAnMDJmMDgyNDI2ODgwODQ0NDhiOWI4MDg0NDQ4YjliOTA4MzAxNjM3ODk0YTFjZmI5ZDUxYzBhZjE5MWZmMjFjNWYwZjAxNzIzZTA1NmY3ZGMxMjg2NWFmMzEwN2E0MDAwODBjMCcsXG4gICAgICAgICAgICBkZXJpdmF0aW9uUGF0aDogJycsIC8vIE5lZWRzIHRoaXMgd2hlbiBrZXkgZGVyaXZhdGlvbiBpcyBzdXBwb3J0ZWRcbiAgICAgICAgICB9LFxuICAgICAgICAgIHN0YXRlOiAncGVuZGluZ1NpZ25hdHVyZScsXG4gICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICB1bnNpZ25lZFR4czogW1xuICAgICAgICB7XG4gICAgICAgICAgLy8gaHRldGggdHhpZDogMHhjNWE3YmZlNmIxM2NlYWU1NjNkYTBmOWZlYWE5YzRhZDFjMTAxYTE1MzY2YTJhNDg4ODI4YTVkZDI3Y2I5ZGEzXG4gICAgICAgICAgc2VyaWFsaXplZFR4SGV4OlxuICAgICAgICAgICAgJzAyZjM4MjQyNjg4MDg0NDQ4YjliODA4NDQ0OGI5YjkwODMwMTYzNzg5NGExY2ZiOWQ1MWMwYWYxOTFmZjIxYzVmMGYwMTcyM2UwNTZmN2RjMTI4NjVhZjMxMDdhNDAwMDgwYzA4MDgwODAnLFxuICAgICAgICAgIHNpZ25hYmxlSGV4OlxuICAgICAgICAgICAgJzAyZjM4MjQyNjg4MDg0NDQ4YjliODA4NDQ0OGI5YjkwODMwMTYzNzg5NGExY2ZiOWQ1MWMwYWYxOTFmZjIxYzVmMGYwMTcyM2UwNTZmN2RjMTI4NjVhZjMxMDdhNDAwMDgwYzA4MDgwODAnLFxuICAgICAgICAgIGRlcml2YXRpb25QYXRoOiAnJywgLy8gTmVlZHMgdGhpcyB3aGVuIGtleSBkZXJpdmF0aW9uIGlzIHN1cHBvcnRlZFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRhdGU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGludGVudDoge1xuICAgICAgICBpbnRlbnRUeXBlOiAncGF5bWVudCcsXG4gICAgICB9LFxuICAgICAgbGF0ZXN0OiB0cnVlLFxuICAgICAgc3RhdGU6ICdwZW5kaW5nVXNlclNpZ25hdHVyZScsXG4gICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgIHdhbGxldElkOiAnd2FsbGV0SWQnLFxuICAgICAgcG9saWNpZXNDaGVja2VkOiB0cnVlLFxuICAgICAgdmVyc2lvbjogMSxcbiAgICAgIHVzZXJJZDogJ3VzZXJJZCcsXG4gICAgfTtcbiAgICBsZXQgYVNoYXJlLCBkU2hhcmUsIHdTaGFyZSwgb1NoYXJlLCB1c2VyU2lnblNoYXJlLCBiaXRnb0NoYWxsZW5nZXMsIGVudGVycHJpc2VDaGFsbGVuZ2VzO1xuXG4gICAgYmVmb3JlRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAvLyBJbml0aWFsaXppbmcgdXNlciBhbmQgYml0Z28gZm9yIGNyZWF0aW5nIHNoYXJlcyBmb3Igbm9ja3NcbiAgICAgIGNvbnN0IHVzZXJTaWduaW5nS2V5ID0gTVBDLmtleUNvbWJpbmUodXNlcktleVNoYXJlLnBTaGFyZSwgW2JpdGdvS2V5U2hhcmUublNoYXJlc1sxXSwgYmFja3VwS2V5U2hhcmUublNoYXJlc1sxXV0pO1xuICAgICAgY29uc3QgYml0Z29TaWduaW5nS2V5ID0gTVBDLmtleUNvbWJpbmUoYml0Z29LZXlTaGFyZS5wU2hhcmUsIFtcbiAgICAgICAgdXNlcktleVNoYXJlLm5TaGFyZXNbM10sXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbM10sXG4gICAgICBdKTtcblxuICAgICAgY29uc3Qgc2VyaWFsaXplZEVudENoYWxsZW5nZSA9IG1vY2tDaGFsbGVuZ2VBO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZEJpdGdvQ2hhbGxlbmdlID0gbW9ja0NoYWxsZW5nZUI7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZEVudENoYWxsZW5nZSA9IEVjZHNhVHlwZXMuZGVzZXJpYWxpemVOdGlsZGVXaXRoUHJvb2ZzKHNlcmlhbGl6ZWRFbnRDaGFsbGVuZ2UpO1xuICAgICAgc2lub24uc3R1YihFY2RzYVJhbmdlUHJvb2YsICdnZW5lcmF0ZU50aWxkZScpLnJlc29sdmVzKGRlc2VyaWFsaXplZEVudENoYWxsZW5nZSk7XG5cbiAgICAgIGNvbnN0IFt1c2VyVG9CaXRnb1BhaWxsaWVyQ2hhbGxlbmdlLCBiaXRnb1RvVXNlclBhaWxsaWVyQ2hhbGxlbmdlXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgRWNkc2FQYWlsbGllclByb29mLmdlbmVyYXRlUChoZXhUb0JpZ0ludCh1c2VyU2lnbmluZ0tleS55U2hhcmVzWzNdLm4pKSxcbiAgICAgICAgRWNkc2FQYWlsbGllclByb29mLmdlbmVyYXRlUChoZXhUb0JpZ0ludChiaXRnb1NpZ25pbmdLZXkueVNoYXJlc1sxXS5uKSksXG4gICAgICBdKTtcblxuICAgICAgYml0Z29DaGFsbGVuZ2VzID0ge1xuICAgICAgICAuLi5zZXJpYWxpemVkQml0Z29DaGFsbGVuZ2UsXG4gICAgICAgIHA6IEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiBiaXRnb1RvVXNlclBhaWxsaWVyQ2hhbGxlbmdlIH0pLnAsXG4gICAgICAgIG46IGJpdGdvU2lnbmluZ0tleS54U2hhcmUubixcbiAgICAgIH07XG4gICAgICBlbnRlcnByaXNlQ2hhbGxlbmdlcyA9IHtcbiAgICAgICAgLi4uc2VyaWFsaXplZEVudENoYWxsZW5nZSxcbiAgICAgICAgcDogRWNkc2FUeXBlcy5zZXJpYWxpemVQYWlsbGllckNoYWxsZW5nZSh7IHA6IHVzZXJUb0JpdGdvUGFpbGxpZXJDaGFsbGVuZ2UgfSkucCxcbiAgICAgICAgbjogYml0Z29TaWduaW5nS2V5LnhTaGFyZS5uLFxuICAgICAgfTtcbiAgICAgIHNpbm9uLnN0dWIoRUNEU0FVdGlscy5FY2RzYVV0aWxzLnByb3RvdHlwZSwgJ2dldEVjZHNhU2lnbmluZ0NoYWxsZW5nZXMnKS5yZXNvbHZlcyh7XG4gICAgICAgIGVudGVycHJpc2VDaGFsbGVuZ2U6IGVudGVycHJpc2VDaGFsbGVuZ2VzLFxuICAgICAgICBiaXRnb0NoYWxsZW5nZTogYml0Z29DaGFsbGVuZ2VzLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IFt1c2VyWFNoYXJlLCBiaXRnb1hTaGFyZV0gPSBbXG4gICAgICAgIE1QQy5hcHBlbmRDaGFsbGVuZ2UoXG4gICAgICAgICAgdXNlclNpZ25pbmdLZXkueFNoYXJlLFxuICAgICAgICAgIHNlcmlhbGl6ZWRFbnRDaGFsbGVuZ2UsXG4gICAgICAgICAgRWNkc2FUeXBlcy5zZXJpYWxpemVQYWlsbGllckNoYWxsZW5nZSh7IHA6IHVzZXJUb0JpdGdvUGFpbGxpZXJDaGFsbGVuZ2UgfSlcbiAgICAgICAgKSxcbiAgICAgICAgTVBDLmFwcGVuZENoYWxsZW5nZShcbiAgICAgICAgICBiaXRnb1NpZ25pbmdLZXkueFNoYXJlLFxuICAgICAgICAgIHNlcmlhbGl6ZWRCaXRnb0NoYWxsZW5nZSxcbiAgICAgICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogYml0Z29Ub1VzZXJQYWlsbGllckNoYWxsZW5nZSB9KVxuICAgICAgICApLFxuICAgICAgXTtcbiAgICAgIGNvbnN0IGJpdGdvWVNoYXJlID0gTVBDLmFwcGVuZENoYWxsZW5nZShcbiAgICAgICAgdXNlclNpZ25pbmdLZXkueVNoYXJlc1szXSxcbiAgICAgICAgc2VyaWFsaXplZEJpdGdvQ2hhbGxlbmdlLFxuICAgICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogYml0Z29Ub1VzZXJQYWlsbGllckNoYWxsZW5nZSB9KVxuICAgICAgKTtcbiAgICAgIC8qKlxuICAgICAgICogU1RBUlQgU1RFUCBPTkVcbiAgICAgICAqIDEpIFVzZXIgY3JlYXRlcyBzaWduU2hhcmUsIHNhdmVzIHdTaGFyZSBhbmQgc2VuZHMga1NoYXJlIHRvIGJpdGdvXG4gICAgICAgKiAyKSBCaXRnbyBwZXJmb3JtcyBzaWduQ29udmVydCBvcGVyYXRpb24gdXNpbmcgaXRzIHByaXZhdGUgeFNoYXJlICwgeVNoYXJlXG4gICAgICAgKiAgYW5kIEtTaGFyZSBmcm9tIHVzZXIgYW5kIHJlc3BvbmRzIGJhY2sgd2l0aCBhU2hhcmUgYW5kIHNhdmVzIGJTaGFyZSBmb3IgbGF0ZXIgdXNlXG4gICAgICAgKi9cbiAgICAgIHVzZXJTaWduU2hhcmUgPSBhd2FpdCBFQ0RTQU1ldGhvZHMuY3JlYXRlVXNlclNpZ25TaGFyZSh1c2VyWFNoYXJlLCBiaXRnb1lTaGFyZSk7XG4gICAgICB3U2hhcmUgPSB1c2VyU2lnblNoYXJlLndTaGFyZTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlT25lRnJvbVVzZXI6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgc2hhcmU6IEVDRFNBTWV0aG9kcy5jb252ZXJ0S1NoYXJlKHVzZXJTaWduU2hhcmUua1NoYXJlKS5zaGFyZS5yZXBsYWNlKEVDRFNBTWV0aG9kcy5kZWxpbWV0ZXIsICcnKSxcbiAgICAgIH07XG4gICAgICBjb25zdCBnZXRCaXRnb0FhbmRCU2hhcmUgPSBhd2FpdCBNUEMuc2lnbkNvbnZlcnRTdGVwMSh7XG4gICAgICAgIHhTaGFyZTogYml0Z29YU2hhcmUsXG4gICAgICAgIHlTaGFyZTogYml0Z29TaWduaW5nS2V5LnlTaGFyZXNbMV0sIC8vIGNvcnJlc3BvbmRzIHRvIHRoZSB1c2VyXG4gICAgICAgIGtTaGFyZTogdXNlclNpZ25TaGFyZS5rU2hhcmUsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGJpdGdvQXNoYXJlID0gZ2V0Qml0Z29BYW5kQlNoYXJlLmFTaGFyZTtcbiAgICAgIGFTaGFyZSA9IGJpdGdvQXNoYXJlO1xuICAgICAgY29uc3QgYVNoYXJlQml0Z29SZXNwb25zZSA9IEVDRFNBTWV0aG9kcy5jb252ZXJ0QVNoYXJlKGJpdGdvQXNoYXJlKS5zaGFyZS5yZXBsYWNlKEVDRFNBTWV0aG9kcy5kZWxpbWV0ZXIsICcnKTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlT25lRnJvbUJpdGdvOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHNoYXJlOiBhU2hhcmVCaXRnb1Jlc3BvbnNlLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IG5vY2tTZW5kU2lnbmF0dXJlU2hhcmVXaXRoUmVzcG9uc2Uoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlOiBzaWduYXR1cmVTaGFyZU9uZUZyb21Vc2VyLFxuICAgICAgICByZXNwb25zZTogc2lnbmF0dXJlU2hhcmVPbmVGcm9tQml0Z28sXG4gICAgICAgIHRzc1R5cGU6ICdlY2RzYScsXG4gICAgICB9KTtcbiAgICAgIC8qKiAgRU5EIFNURVAgT05FICovXG5cbiAgICAgIC8qKlxuICAgICAgICogU1RBUlQgU1RFUCBUV09cbiAgICAgICAqIDEpIFVzaW5nIHRoZSBhU2hhcmUgZ290IGZyb20gYml0Z28gYW5kIHdTaGFyZSBmcm9tIHByZXZpb3VzIHN0ZXAsXG4gICAgICAgKiB1c2VyIGNyZWF0ZXMgZ1NoYXJlIGFuZCBtdVNoYXJlIGFuZCBzZW5kcyBtdVNoYXJlIHRvIGJpdGdvXG4gICAgICAgKiAyKSBCaXRnbyB1c2luZyB0aGUgc2lnbkNvbnZlcnQgc3RlcCB1c2luZyBiU2hhcmUgZnJvbSBwcmV2aW91cyBzdGVwXG4gICAgICAgKiBhbmQgbXVTaGFyZSBmcm9tIHVzZXIgZ2VuZXJhdGVzIGl0cyBnU2hhcmUuXG4gICAgICAgKiAzKSBVc2luZyB0aGUgc2lnbkNvbWJpbmUgb3BlcmF0aW9uIHVzaW5nIGdTaGFyZSwgQml0Z28gZ2VuZXJhdGVzIG9TaGFyZVxuICAgICAgICogd2hpY2ggaXQgc2F2ZXMgYW5kIGRTaGFyZSB3aGljaCBpcyBzZW5kIGJhY2sgdG8gdGhlIHVzZXIuXG4gICAgICAgKi9cbiAgICAgIGNvbnN0IHVzZXJHYW1tYUFuZE11U2hhcmVzID0gYXdhaXQgRUNEU0FNZXRob2RzLmNyZWF0ZVVzZXJHYW1tYUFuZE11U2hhcmUodXNlclNpZ25TaGFyZS53U2hhcmUsIGJpdGdvQXNoYXJlKTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlVHdvRnJvbVVzZXI6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgc2hhcmU6IEVDRFNBTWV0aG9kcy5jb252ZXJ0TXVTaGFyZSh1c2VyR2FtbWFBbmRNdVNoYXJlcy5tdVNoYXJlISkuc2hhcmUucmVwbGFjZShFQ0RTQU1ldGhvZHMuZGVsaW1ldGVyLCAnJyksXG4gICAgICB9O1xuICAgICAgY29uc3QgZ2V0Qml0R29HU2hhcmVBbmRTaWduZXJJbmRleGVzID0gYXdhaXQgTVBDLnNpZ25Db252ZXJ0U3RlcDMoe1xuICAgICAgICBiU2hhcmU6IGdldEJpdGdvQWFuZEJTaGFyZS5iU2hhcmUsXG4gICAgICAgIG11U2hhcmU6IHVzZXJHYW1tYUFuZE11U2hhcmVzLm11U2hhcmUsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZ2V0Qml0Z29PU2hhcmVBbmREU2hhcmVzID0gTVBDLnNpZ25Db21iaW5lKHtcbiAgICAgICAgZ1NoYXJlOiBnZXRCaXRHb0dTaGFyZUFuZFNpZ25lckluZGV4ZXMuZ1NoYXJlIGFzIEVDRFNBLkdTaGFyZSxcbiAgICAgICAgc2lnbkluZGV4OiB7XG4gICAgICAgICAgaTogMSxcbiAgICAgICAgICBqOiAzLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBiaXRnb0RzaGFyZSA9IGdldEJpdGdvT1NoYXJlQW5kRFNoYXJlcy5kU2hhcmUgYXMgRUNEU0EuRFNoYXJlO1xuICAgICAgZFNoYXJlID0gYml0Z29Ec2hhcmU7XG4gICAgICBjb25zdCBkU2hhcmVCaXRnb1Jlc3BvbnNlID0gKGJpdGdvRHNoYXJlLmRlbHRhIGFzIHN0cmluZykgKyAoYml0Z29Ec2hhcmUuR2FtbWEgYXMgc3RyaW5nKTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlVHdvRnJvbUJpdGdvOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHNoYXJlOiBkU2hhcmVCaXRnb1Jlc3BvbnNlLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IG5vY2tTZW5kU2lnbmF0dXJlU2hhcmVXaXRoUmVzcG9uc2Uoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlOiBzaWduYXR1cmVTaGFyZVR3b0Zyb21Vc2VyLFxuICAgICAgICByZXNwb25zZTogc2lnbmF0dXJlU2hhcmVUd29Gcm9tQml0Z28sXG4gICAgICAgIHRzc1R5cGU6ICdlY2RzYScsXG4gICAgICB9KTtcbiAgICAgIC8qKiAgRU5EIFNURVAgVFdPICovXG5cbiAgICAgIC8qKlxuICAgICAgICogU1RBUlQgU1RFUCBUSFJFRVxuICAgICAgICogMSkgVXNlciBjcmVhdGVzIGl0cyBvU2hhcmUgYW5kICBkU2hhcmUgdXNpbmcgdGhlICBwcml2YXRlIGdTaGFyZVxuICAgICAgICogZnJvbSBzdGVwIHR3b1xuICAgICAgICogMikgVXNlciB1c2VzIHRoZSBwcml2YXRlIG9TaGFyZSBhbmQgZFNoYXJlIGZyb20gYml0Z28gZnJvbSBzdGVwXG4gICAgICAgKiB0d28gdG8gZ2VuZXJhdGUgaXRzIHNpZ25hdHVyZSBzaGFyZSB3aGljaCBpdCBzZW5kcyBiYWNrIGFsb25nIHdpdGggZFNoYXJlIHRoYXRcbiAgICAgICAqIHVzZXIgZ2VuZXJhdGVkIGZyb20gdGhlIGFib3ZlIHN0ZXBcbiAgICAgICAqIDMpIEJpdGdvIHVzaW5nIGl0cyBwcml2YXRlIG9TaGFyZSBmcm9tIHN0ZXAgdHdvIGFuZCBkU2hhcmUgZnJvbSBiaXRnbyBjcmVhdGVzXG4gICAgICAgKiBpdHMgc2lnbmF0dXJlIHNoYXJlLiBVc2luZyB0aGUgU2lnbmF0dXJlIFNoYXJlIHJlY2VpdmVkIGZyb20gdXNlciBmcm9tIHRoZSBhYm92ZVxuICAgICAgICogc3RlcCwgYml0Z28gY29uc3RydWN0cyB0aGUgZmluYWwgc2lnbmF0dXJlIGFuZCBpcyByZXR1cm5lZCB0byB0aGUgdXNlclxuICAgICAgICovXG4gICAgICBjb25zdCB1c2VyT21pY3JvbkFuZERlbHRhU2hhcmUgPSBhd2FpdCBFQ0RTQU1ldGhvZHMuY3JlYXRlVXNlck9taWNyb25BbmREZWx0YVNoYXJlKFxuICAgICAgICB1c2VyR2FtbWFBbmRNdVNoYXJlcy5nU2hhcmUgYXMgRUNEU0EuR1NoYXJlXG4gICAgICApO1xuICAgICAgb1NoYXJlID0gdXNlck9taWNyb25BbmREZWx0YVNoYXJlLm9TaGFyZTtcbiAgICAgIGNvbnN0IHNpZ25hYmxlUGF5bG9hZCA9IEJ1ZmZlci5mcm9tKHR4UmVxdWVzdC51bnNpZ25lZFR4c1swXS5zaWduYWJsZUhleCwgJ2hleCcpO1xuICAgICAgY29uc3QgdXNlclNTaGFyZSA9IGF3YWl0IEVDRFNBTWV0aG9kcy5jcmVhdGVVc2VyU2lnbmF0dXJlU2hhcmUoXG4gICAgICAgIHVzZXJPbWljcm9uQW5kRGVsdGFTaGFyZS5vU2hhcmUsXG4gICAgICAgIGJpdGdvRHNoYXJlLFxuICAgICAgICBzaWduYWJsZVBheWxvYWRcbiAgICAgICk7XG4gICAgICBjb25zdCBzaWduYXR1cmVTaGFyZVRocmVlRnJvbVVzZXI6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgc2hhcmU6XG4gICAgICAgICAgdXNlclNTaGFyZS5SICtcbiAgICAgICAgICB1c2VyU1NoYXJlLnMgK1xuICAgICAgICAgIHVzZXJTU2hhcmUueSArXG4gICAgICAgICAgdXNlck9taWNyb25BbmREZWx0YVNoYXJlLmRTaGFyZS5kZWx0YSArXG4gICAgICAgICAgdXNlck9taWNyb25BbmREZWx0YVNoYXJlLmRTaGFyZS5HYW1tYSxcbiAgICAgIH07XG4gICAgICBjb25zdCBnZXRCaXRHb1NTaGFyZSA9IE1QQy5zaWduKFxuICAgICAgICBzaWduYWJsZVBheWxvYWQsXG4gICAgICAgIGdldEJpdGdvT1NoYXJlQW5kRFNoYXJlcy5vU2hhcmUsXG4gICAgICAgIHVzZXJPbWljcm9uQW5kRGVsdGFTaGFyZS5kU2hhcmUsXG4gICAgICAgIGNyZWF0ZUtlY2Nha0hhc2goJ2tlY2NhazI1NicpIGFzIEhhc2hcbiAgICAgICk7XG4gICAgICBjb25zdCBnZXRCaXRHb0ZpbmFsU2lnbmF0dXJlID0gTVBDLmNvbnN0cnVjdFNpZ25hdHVyZShbZ2V0Qml0R29TU2hhcmUsIHVzZXJTU2hhcmVdKTtcbiAgICAgIGNvbnN0IGZpbmFsU2lnYW50dXJlQml0Z29SZXNwb25zZSA9XG4gICAgICAgIGdldEJpdEdvRmluYWxTaWduYXR1cmUuciArIGdldEJpdEdvRmluYWxTaWduYXR1cmUucyArIGdldEJpdEdvRmluYWxTaWduYXR1cmUueTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlVGhyZWVGcm9tQml0Z286IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgc2hhcmU6IGZpbmFsU2lnYW50dXJlQml0Z29SZXNwb25zZSxcbiAgICAgIH07XG4gICAgICBhd2FpdCBub2NrU2VuZFNpZ25hdHVyZVNoYXJlV2l0aFJlc3BvbnNlKHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgICBzaWduYXR1cmVTaGFyZTogc2lnbmF0dXJlU2hhcmVUaHJlZUZyb21Vc2VyLFxuICAgICAgICByZXNwb25zZTogc2lnbmF0dXJlU2hhcmVUaHJlZUZyb21CaXRnbyxcbiAgICAgICAgdHNzVHlwZTogJ2VjZHNhJyxcbiAgICAgIH0pO1xuICAgICAgLyogRU5EIFNURVAgVEhSRUUgKi9cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IE1QQy5jb25zdHJ1Y3RTaWduYXR1cmUoW3VzZXJTU2hhcmUsIGdldEJpdEdvU1NoYXJlXSk7XG4gICAgICBNUEMudmVyaWZ5KHNpZ25hYmxlUGF5bG9hZCwgc2lnbmF0dXJlLCBjcmVhdGVLZWNjYWtIYXNoKCdrZWNjYWsyNTYnKSBhcyBIYXNoKS5zaG91bGQuYmUudHJ1ZTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICBzaW5vbi5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2lnblR4UmVxdWVzdCBzaG91bGQgZmFpbCBpZiB3YWxsZXQgaXMgaW4gcGVuZGluZ0VjZHNhVHNzSW5pdGlhbGl6YXRpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kYm94LnN0dWIod2FsbGV0LCAnY29pblNwZWNpZmljJykucmV0dXJucyh7XG4gICAgICAgIGN1c3RvbUNoYW5nZVdhbGxldElkOiAnJyxcbiAgICAgICAgcGVuZGluZ0VjZHNhVHNzSW5pdGlhbGl6YXRpb246IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgICB0eFJlcXVlc3QsXG4gICAgICAgICAgcHJ2OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBwU2hhcmU6IHVzZXJLZXlTaGFyZS5wU2hhcmUsXG4gICAgICAgICAgICBiaXRnb05TaGFyZTogYml0Z29LZXlTaGFyZS5uU2hhcmVzWzFdLFxuICAgICAgICAgICAgYmFja3VwTlNoYXJlOiBiYWNrdXBLZXlTaGFyZS5uU2hhcmVzWzFdLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHJlcUlkLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAnV2FsbGV0IGlzIG5vdCByZWFkeSBmb3IgVFNTIEVDRFNBIHNpZ25pbmcuIFBsZWFzZSBjb250YWN0IHlvdXIgZW50ZXJwcmlzZSBhZG1pbiB0byBmaW5pc2ggdGhlIGVudGVycHJpc2UgVFNTIGluaXRpYWxpemF0aW9uLidcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIHdpdGggdHhSZXF1ZXN0IG9iamVjdCBhcyBpbnB1dCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlbmRTaGFyZVNweSA9IHNpbm9uLnNweShFQ0RTQU1ldGhvZHMsICdzZW5kU2hhcmVUb0JpdGdvJyBhcyBhbnkpO1xuICAgICAgYXdhaXQgc2V0dXBTaWduVHhSZXF1ZXN0Tm9ja3MoZmFsc2UsIHVzZXJTaWduU2hhcmUsIGFTaGFyZSwgZFNoYXJlLCBlbnRlcnByaXNlRGF0YSk7XG4gICAgICBjb25zdCBzaWduZWRUeFJlcXVlc3QgPSBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0LFxuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBwU2hhcmU6IHVzZXJLZXlTaGFyZS5wU2hhcmUsXG4gICAgICAgICAgYml0Z29OU2hhcmU6IGJpdGdvS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgIH0pLFxuICAgICAgICByZXFJZCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkVHhSZXF1ZXN0LnVuc2lnbmVkVHhzLnNob3VsZC5kZWVwRXF1YWwodHhSZXF1ZXN0LnVuc2lnbmVkVHhzKTtcbiAgICAgIGNvbnN0IHVzZXJHcGdBY3R1YWwgPSBzZW5kU2hhcmVTcHkuZ2V0Q2FsbHMoKVswXS5hcmdzWzEwXSBhcyBzdHJpbmc7XG4gICAgICB1c2VyR3BnQWN0dWFsLnNob3VsZC5zdGFydFdpdGgoJy0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NpZ25UeFJlcXVlc3Qgc2hvdWxkIHN1Y2NlZWQgd2l0aCB0eFJlcXVlc3QgaWQgYXMgaW5wdXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZW5kU2hhcmVTcHkgPSBzaW5vbi5zcHkoRUNEU0FNZXRob2RzLCAnc2VuZFNoYXJlVG9CaXRnbycgYXMgYW55KTtcbiAgICAgIGF3YWl0IHNldHVwU2lnblR4UmVxdWVzdE5vY2tzKHRydWUsIHVzZXJTaWduU2hhcmUsIGFTaGFyZSwgZFNoYXJlLCBlbnRlcnByaXNlRGF0YSk7XG4gICAgICBjb25zdCBzaWduZWRUeFJlcXVlc3QgPSBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RJZCxcbiAgICAgICAgcHJ2OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgcFNoYXJlOiB1c2VyS2V5U2hhcmUucFNoYXJlLFxuICAgICAgICAgIGJpdGdvTlNoYXJlOiBiaXRnb0tleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgYmFja3VwTlNoYXJlOiBiYWNrdXBLZXlTaGFyZS5uU2hhcmVzWzFdLFxuICAgICAgICB9KSxcbiAgICAgICAgcmVxSWQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4UmVxdWVzdC51bnNpZ25lZFR4cy5zaG91bGQuZGVlcEVxdWFsKHR4UmVxdWVzdC51bnNpZ25lZFR4cyk7XG4gICAgICBjb25zdCB1c2VyR3BnQWN0dWFsID0gc2VuZFNoYXJlU3B5LmdldENhbGxzKClbMF0uYXJnc1sxMF0gYXMgc3RyaW5nO1xuICAgICAgdXNlckdwZ0FjdHVhbC5zaG91bGQuc3RhcnRXaXRoKCctLS0tLUJFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBmYWlsIHdpdGggd3JvbmcgcmVjaXBpZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVG8gZ2VuZXJhdGUgdGhlc2UgSGV4IHZhbHVlcywgd2UgdXNlZCB0aGUgYml0Z28tdWkgdG8gY3JlYXRlIGEgdHJhbnNhY3Rpb24gYW5kIHRoZW5cbiAgICAgIC8vIHVzZWQgdGhlIGBzaWduYWJsZUhleGAgYW5kIGBzZXJpYWxpemVkVHhIZXhgIHZhbHVlcyBmcm9tIHRoZSBwcmVidWlsZC5cbiAgICAgIGNvbnN0IHNpZ25hYmxlSGV4ID1cbiAgICAgICAgJzAyZjI4MzA4OGJiMDAzODQwNmYxODc1ODg0N2YzNDQzYzY4MzAxNjM3ODk0OTcyNmVhNThiZTU3YjE1Mzc5MWE4ZmY1YjI4MmQ3NzZhYWYyOGUzYzg3MDM4ZDdlYTRjNjgwMDA4MGMwJztcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUeEhleCA9XG4gICAgICAgICcwMmY1ODMwODhiYjAwMzg0MDZmMTg3NTg4NDdmMzQ0M2M2ODMwMTYzNzg5NDk3MjZlYTU4YmU1N2IxNTM3OTFhOGZmNWIyODJkNzc2YWFmMjhlM2M4NzAzOGQ3ZWE0YzY4MDAwODBjMDgwODA4MCc7XG4gICAgICBhd2FpdCBzZXR1cFNpZ25UeFJlcXVlc3ROb2Nrcyh0cnVlLCB1c2VyU2lnblNoYXJlLCBhU2hhcmUsIGRTaGFyZSwgZW50ZXJwcmlzZURhdGEsIHtcbiAgICAgICAgc2lnbmFibGVIZXgsXG4gICAgICAgIHNlcmlhbGl6ZWRUeEhleCxcbiAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuc2lnblR4UmVxdWVzdCh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RJZCxcbiAgICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHBTaGFyZTogdXNlcktleVNoYXJlLnBTaGFyZSxcbiAgICAgICAgICAgIGJpdGdvTlNoYXJlOiBiaXRnb0tleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgcmVxSWQsXG4gICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzB4MTIzNCcsIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAnIH1dLCB0eXBlOiAndHJhbnNmZXInIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdkZXN0aW5hdGlvbiBhZGRyZXNzIGRvZXMgbm90IG1hdGNoIHdpdGggdGhlIHJlY2lwaWVudCBhZGRyZXNzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2lnblR4UmVxdWVzdCBzaG91bGQgZmFpbCB3aXRoIGluY29ycmVjdCB2YWx1ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICAgIC8vIFRvIGdlbmVyYXRlIHRoZXNlIEhleCB2YWx1ZXMsIHdlIHVzZWQgdGhlIGJpdGdvLXVpIHRvIGNyZWF0ZSBhIHRyYW5zYWN0aW9uIGFuZCB0aGVuXG4gICAgICAvLyB1c2VkIHRoZSBgc2lnbmFibGVIZXhgIGFuZCBgc2VyaWFsaXplZFR4SGV4YCB2YWx1ZXMgZnJvbSB0aGUgcHJlYnVpbGQuXG4gICAgICBjb25zdCBzaWduYWJsZUhleCA9XG4gICAgICAgICcwMmYyODMwODhiYjAwMzg0MDZmMTg3NTg4NDdmMzQ0M2M2ODMwMTYzNzg5NDk3MjZlYTU4YmU1N2IxNTM3OTFhOGZmNWIyODJkNzc2YWFmMjhlM2M4NzAzOGQ3ZWE0YzY4MDAwODBjMCc7XG4gICAgICBjb25zdCBzZXJpYWxpemVkVHhIZXggPVxuICAgICAgICAnMDJmNTgzMDg4YmIwMDM4NDA2ZjE4NzU4ODQ3ZjM0NDNjNjgzMDE2Mzc4OTQ5NzI2ZWE1OGJlNTdiMTUzNzkxYThmZjViMjgyZDc3NmFhZjI4ZTNjODcwMzhkN2VhNGM2ODAwMDgwYzA4MDgwODAnO1xuICAgICAgYXdhaXQgc2V0dXBTaWduVHhSZXF1ZXN0Tm9ja3ModHJ1ZSwgdXNlclNpZ25TaGFyZSwgYVNoYXJlLCBkU2hhcmUsIGVudGVycHJpc2VEYXRhLCB7XG4gICAgICAgIHNpZ25hYmxlSGV4LFxuICAgICAgICBzZXJpYWxpemVkVHhIZXgsXG4gICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgICAgIHR4UmVxdWVzdDogdHhSZXF1ZXN0SWQsXG4gICAgICAgICAgcHJ2OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBwU2hhcmU6IHVzZXJLZXlTaGFyZS5wU2hhcmUsXG4gICAgICAgICAgICBiaXRnb05TaGFyZTogYml0Z29LZXlTaGFyZS5uU2hhcmVzWzFdLFxuICAgICAgICAgICAgYmFja3VwTlNoYXJlOiBiYWNrdXBLZXlTaGFyZS5uU2hhcmVzWzFdLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHJlcUlkLFxuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHhhMWNmYjlkNTFjMGFmMTkxZmYyMWM1ZjBmMDE3MjNlMDU2ZjdkYzEyJywgYW1vdW50OiAnMScgfV0sXG4gICAgICAgICAgICB0eXBlOiAndHJhbnNmZXInLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCd0aGUgdHJhbnNhY3Rpb24gYW1vdW50IGluIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggdGhlIHZhbHVlIGdpdmVuIGJ5IGNsaWVudCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NpZ25UeFJlcXVlc3Qgc2hvdWxkIGZhaWwgd2l0aCBpbmNvcnJlY3QgdmFsdWUgZm9yIHRva2VuIHR4bicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICAgIC8vIFRvIGdlbmVyYXRlIHRoZXNlIEhleCB2YWx1ZXMsIHdlIHVzZWQgdGhlIGJpdGdvLXVpIHRvIGNyZWF0ZSBhIHRyYW5zYWN0aW9uIGFuZCB0aGVuXG4gICAgICAvLyB1c2VkIHRoZSBgc2lnbmFibGVIZXhgIGFuZCBgc2VyaWFsaXplZFR4SGV4YCB2YWx1ZXMgZnJvbSB0aGUgcHJlYnVpbGQuXG4gICAgICBjb25zdCBzaWduYWJsZUhleCA9XG4gICAgICAgICcwMmY4NmY4MzA4OGJiMDAyODNlMWQ3ZGQ4NDc2OGVhNjg5ODMwMWUwNGI5NGQ5MzI3ZmQzNmMzMzEyNDY2ZWZlZDIzZmYwNDkzNDUzZWUzMmY1NTE4MGI4NDRhOTA1OWNiYjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDdkN2U2M2FmNTgzYmE3M2JhNWM5MjdkYmQwMjgxNTM5NjM1NjZiZWYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQ3MGRlNGRmODIwMDAwYzAnO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFR4SGV4ID1cbiAgICAgICAgJzAyZjg3MjgzMDg4YmIwMDI4M2UxZDdkZDg0NzY4ZWE2ODk4MzAxZTA0Yjk0ZDkzMjdmZDM2YzMzMTI0NjZlZmVkMjNmZjA0OTM0NTNlZTMyZjU1MTgwYjg0NGE5MDU5Y2JiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwN2Q3ZTYzYWY1ODNiYTczYmE1YzkyN2RiZDAyODE1Mzk2MzU2NmJlZjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDcwZGU0ZGY4MjAwMDBjMDgwODA4MCc7XG4gICAgICBhd2FpdCBzZXR1cFNpZ25UeFJlcXVlc3ROb2Nrcyh0cnVlLCB1c2VyU2lnblNoYXJlLCBhU2hhcmUsIGRTaGFyZSwgZW50ZXJwcmlzZURhdGEsIHtcbiAgICAgICAgc2lnbmFibGVIZXgsXG4gICAgICAgIHNlcmlhbGl6ZWRUeEhleCxcbiAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuc2lnblR4UmVxdWVzdCh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RJZCxcbiAgICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHBTaGFyZTogdXNlcktleVNoYXJlLnBTaGFyZSxcbiAgICAgICAgICAgIGJpdGdvTlNoYXJlOiBiaXRnb0tleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgcmVxSWQsXG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6ICcweDJiMGQ2Y2IyZjhjMzg4NzU3ZjRkN2FkODU3ZmNjYWIxODI5MGRiYzknLCBhbW91bnQ6ICc3MDcnIH1dLFxuICAgICAgICAgICAgdHlwZTogJ3RyYW5zZmVyJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgndGhlIHRyYW5zYWN0aW9uIGFtb3VudCBpbiB0eFByZWJ1aWxkIGRvZXMgbm90IG1hdGNoIHRoZSB2YWx1ZSBnaXZlbiBieSBjbGllbnQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIGZvciBXYWxsZXRDb25uZWN0IEVSQzIwIHRyYW5zZmVyIHdpdGggZGF0YSBmaWVsZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICAgIC8vIFdhbGxldENvbm5lY3QgRVJDMjAgdHJhbnNmZXI6IHJlY2lwaWVudHNbMF0uYWRkcmVzcyBpcyB0b2tlbiBjb250cmFjdCwgcmVjaXBpZW50c1swXS5hbW91bnQgaXMgMCAobm8gbmF0aXZlIGNvaW5zKVxuICAgICAgLy8gcmVjaXBpZW50c1swXS5kYXRhIGNvbnRhaW5zIHRoZSBhY3R1YWwgcmVjaXBpZW50IGFuZCB0b2tlbiBhbW91bnRcbiAgICAgIGNvbnN0IHNpZ25hYmxlSGV4ID1cbiAgICAgICAgJzAyZjg2ZjgzMDg4YmIwMDI4M2UxZDdkZDg0NzY4ZWE2ODk4MzAxZTA0Yjk0ZDkzMjdmZDM2YzMzMTI0NjZlZmVkMjNmZjA0OTM0NTNlZTMyZjU1MTgwYjg0NGE5MDU5Y2JiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwN2Q3ZTYzYWY1ODNiYTczYmE1YzkyN2RiZDAyODE1Mzk2MzU2NmJlZjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDcwZGU0ZGY4MjAwMDBjMCc7XG4gICAgICBjb25zdCBzZXJpYWxpemVkVHhIZXggPVxuICAgICAgICAnMDJmODcyODMwODhiYjAwMjgzZTFkN2RkODQ3NjhlYTY4OTgzMDFlMDRiOTRkOTMyN2ZkMzZjMzMxMjQ2NmVmZWQyM2ZmMDQ5MzQ1M2VlMzJmNTUxODBiODQ0YTkwNTljYmIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA3ZDdlNjNhZjU4M2JhNzNiYTVjOTI3ZGJkMDI4MTUzOTYzNTY2YmVmMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA0NzBkZTRkZjgyMDAwMGMwODA4MDgwJztcbiAgICAgIGF3YWl0IHNldHVwU2lnblR4UmVxdWVzdE5vY2tzKHRydWUsIHVzZXJTaWduU2hhcmUsIGFTaGFyZSwgZFNoYXJlLCBlbnRlcnByaXNlRGF0YSwge1xuICAgICAgICBzaWduYWJsZUhleCxcbiAgICAgICAgc2VyaWFsaXplZFR4SGV4LFxuICAgICAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdElkLFxuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBwU2hhcmU6IHVzZXJLZXlTaGFyZS5wU2hhcmUsXG4gICAgICAgICAgYml0Z29OU2hhcmU6IGJpdGdvS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgIH0pLFxuICAgICAgICByZXFJZCxcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6ICcweGQ5MzI3ZmQzNmMzMzEyNDY2ZWZlZDIzZmYwNDkzNDUzZWUzMmY1NTEnLCAvLyBUb2tlbiBjb250cmFjdCBhZGRyZXNzXG4gICAgICAgICAgICAgIGFtb3VudDogJzAnLCAvLyBObyBuYXRpdmUgY29pbnMgc2VudFxuICAgICAgICAgICAgICBkYXRhOiAnMHhhOTA1OWNiYjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDdkN2U2M2FmNTgzYmE3M2JhNWM5MjdkYmQwMjgxNTM5NjM1NjZiZWYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQ3MGRlNGRmODIwMDAwJywgLy8gRVJDMjAgdHJhbnNmZXIgY2FsbGRhdGEgd2l0aCBhY3R1YWwgcmVjaXBpZW50IGFuZCB0b2tlbiBhbW91bnRcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0eXBlOiAndHJhbnNmZXInLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2V0T2ZmbGluZVNpZ25lclBhaWxsaWVyTW9kdWx1cyBzaG91bGQgc3VjY2VlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhaWxsaWVyTW9kdWx1cyA9IHRzc1V0aWxzLmdldE9mZmxpbmVTaWduZXJQYWlsbGllck1vZHVsdXMoe1xuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBwU2hhcmU6IHVzZXJLZXlTaGFyZS5wU2hhcmUsXG4gICAgICAgICAgYml0Z29OU2hhcmU6IGJpdGdvS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgIH0pLFxuICAgICAgfSk7XG4gICAgICBwYWlsbGllck1vZHVsdXMudXNlclBhaWxsaWVyTW9kdWx1cy5zaG91bGQuZXF1YWwodXNlcktleVNoYXJlLnBTaGFyZS5uKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVPZmZsaW5lS1NoYXJlIHNob3VsZCBzdWNjZWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja1Bhc3N3b3JkID0gJ3Bhc3N3b3JkJztcbiAgICAgIGNvbnN0IHN0ZXAxU2lnbmluZ01hdGVyaWFsID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlT2ZmbGluZUtTaGFyZSh7XG4gICAgICAgIHRzc1BhcmFtczoge1xuICAgICAgICAgIHR4UmVxdWVzdCxcbiAgICAgICAgICByZXFJZDogcmVxSWQsXG4gICAgICAgIH0sXG4gICAgICAgIGNoYWxsZW5nZXM6IHtcbiAgICAgICAgICBlbnRlcnByaXNlQ2hhbGxlbmdlOiBlbnRlcnByaXNlQ2hhbGxlbmdlcyxcbiAgICAgICAgICBiaXRnb0NoYWxsZW5nZTogYml0Z29DaGFsbGVuZ2VzLFxuICAgICAgICB9LFxuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBwU2hhcmU6IHVzZXJLZXlTaGFyZS5wU2hhcmUsXG4gICAgICAgICAgYml0Z29OU2hhcmU6IGJpdGdvS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgIH0pLFxuICAgICAgICByZXF1ZXN0VHlwZTogUmVxdWVzdFR5cGUudHgsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IG1vY2tQYXNzd29yZCxcbiAgICAgIH0pO1xuICAgICAgc3RlcDFTaWduaW5nTWF0ZXJpYWwucHJpdmF0ZVNoYXJlUHJvb2Yuc2hvdWxkLnN0YXJ0V2l0aCgnLS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJyk7XG4gICAgICBzdGVwMVNpZ25pbmdNYXRlcmlhbC52c3NQcm9vZj8ubGVuZ3RoLnNob3VsZC5lcXVhbCh1c2VyS2V5U2hhcmUublNoYXJlc1szXS52Py5sZW5ndGgpO1xuICAgICAgc3RlcDFTaWduaW5nTWF0ZXJpYWwucHVibGljU2hhcmUubGVuZ3RoLnNob3VsZC5lcXVhbChcbiAgICAgICAgdXNlcktleVNoYXJlLm5TaGFyZXNbM10ueS5sZW5ndGggKyB1c2VyS2V5U2hhcmUublNoYXJlc1szXS5jaGFpbmNvZGUubGVuZ3RoXG4gICAgICApO1xuICAgICAgc3RlcDFTaWduaW5nTWF0ZXJpYWwuZW5jcnlwdGVkU2lnbmVyT2Zmc2V0U2hhcmUuc2hvdWxkLnN0YXJ0V2l0aCgnLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tJyk7XG4gICAgICBzdGVwMVNpZ25pbmdNYXRlcmlhbC51c2VyUHVibGljR3BnS2V5LnNob3VsZC5zdGFydFdpdGgoJy0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLScpO1xuICAgICAgc3RlcDFTaWduaW5nTWF0ZXJpYWwua1NoYXJlLm4uc2hvdWxkLmVxdWFsKHVzZXJLZXlTaGFyZS5wU2hhcmUubik7XG4gICAgICBzdGVwMVNpZ25pbmdNYXRlcmlhbC53U2hhcmUuc2hvdWxkLnN0YXJ0V2l0aCgne1wiaXZcIjonKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVPZmZsaW5lS1NoYXJlIHNob3VsZCBmYWlsIHdpdGggdHhJZCBwYXNzZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrUGFzc3dvcmQgPSAncGFzc3dvcmQnO1xuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLmNyZWF0ZU9mZmxpbmVLU2hhcmUoe1xuICAgICAgICAgIHRzc1BhcmFtczoge1xuICAgICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgICAgICByZXFJZDogcmVxSWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjaGFsbGVuZ2VzOiB7XG4gICAgICAgICAgICBlbnRlcnByaXNlQ2hhbGxlbmdlOiBlbnRlcnByaXNlQ2hhbGxlbmdlcyxcbiAgICAgICAgICAgIGJpdGdvQ2hhbGxlbmdlOiBiaXRnb0NoYWxsZW5nZXMsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHBTaGFyZTogdXNlcktleVNoYXJlLnBTaGFyZSxcbiAgICAgICAgICAgIGJpdGdvTlNoYXJlOiBiaXRnb0tleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgICBiYWNrdXBOU2hhcmU6IGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgcmVxdWVzdFR5cGU6IFJlcXVlc3RUeXBlLnR4LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IG1vY2tQYXNzd29yZCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQgdHhSZXF1ZXN0IHR5cGUnKTtcbiAgICB9KTtcblxuICAgIC8vIFNlZW1zIHRvIGJlIGZsYWt5IG9uIENJLCBmYWlsZWQgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL0JpdEdvL0JpdEdvSlMvYWN0aW9ucy9ydW5zLzU5MDI0ODk5OTAvam9iLzE2MDEwNjIzODg4P3ByPTM4MjJcbiAgICB4aXQoJ2NyZWF0ZU9mZmxpbmVNdURlbHRhU2hhcmUgc2hvdWxkIHN1Y2NlZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrUGFzc3dvcmQgPSAncGFzc3dvcmQnO1xuICAgICAgY29uc3QgYWxwaGFMZW5ndGggPSAxNTM2O1xuICAgICAgY29uc3QgZGVsdGFMZW5ndGggPSA2NDtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgY29uc3Qgc3RlcDJTaWduaW5nTWF0ZXJpYWwgPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVPZmZsaW5lTXVEZWx0YVNoYXJlKHtcbiAgICAgICAgYVNoYXJlRnJvbUJpdGdvOiBhU2hhcmUsXG4gICAgICAgIGJpdGdvQ2hhbGxlbmdlOiBiaXRnb0NoYWxsZW5nZXMsXG4gICAgICAgIGVuY3J5cHRlZFdTaGFyZTogYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiBKU09OLnN0cmluZ2lmeSh3U2hhcmUpLCBwYXNzd29yZDogbW9ja1Bhc3N3b3JkIH0pLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBtb2NrUGFzc3dvcmQsXG4gICAgICB9KTtcbiAgICAgIHN0ZXAyU2lnbmluZ01hdGVyaWFsLm11RFNoYXJlLm11U2hhcmUuYWxwaGEubGVuZ3RoLnNob3VsZC5lcXVhbChhbHBoYUxlbmd0aCk7XG4gICAgICBzdGVwMlNpZ25pbmdNYXRlcmlhbC5tdURTaGFyZS5kU2hhcmUuZGVsdGEubGVuZ3RoLnNob3VsZC5lcXVhbChkZWx0YUxlbmd0aCk7XG4gICAgICBzdGVwMlNpZ25pbmdNYXRlcmlhbC5vU2hhcmUuc2hvdWxkLnN0YXJ0V2l0aCgne1wiaXZcIjonKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVPZmZsaW5lTXVEZWx0YVNoYXJlIHNob3VsZCBmYWlsIHdpdGggaW5jb3JyZWN0IHBhc3N3b3JkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja1Bhc3N3b3JkID0gJ3Bhc3N3b3JkJztcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLmNyZWF0ZU9mZmxpbmVNdURlbHRhU2hhcmUoe1xuICAgICAgICAgIGFTaGFyZUZyb21CaXRnbzogYVNoYXJlLFxuICAgICAgICAgIGJpdGdvQ2hhbGxlbmdlOiBiaXRnb0NoYWxsZW5nZXMsXG4gICAgICAgICAgZW5jcnlwdGVkV1NoYXJlOiBhd2FpdCBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6IEpTT04uc3RyaW5naWZ5KHdTaGFyZSksIHBhc3N3b3JkOiBtb2NrUGFzc3dvcmQgfSksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ3Bhc3N3b3JkMScsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdpbmNvcnJlY3QgcGFzc3dvcmQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVPZmZsaW5lTXVEZWx0YVNoYXJlIHNob3VsZCBzdWNjZWVkIHdpdGggdjItZW5jcnlwdGVkIHdTaGFyZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1vY2tQYXNzd29yZCA9ICdwYXNzd29yZCc7XG4gICAgICBjb25zdCBhbHBoYUxlbmd0aCA9IDE1MzY7XG4gICAgICBjb25zdCBkZWx0YUxlbmd0aCA9IDY0O1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCBlbmNyeXB0ZWRXU2hhcmUgPSBhd2FpdCBiaXRnby5lbmNyeXB0KHtcbiAgICAgICAgaW5wdXQ6IEpTT04uc3RyaW5naWZ5KHdTaGFyZSksXG4gICAgICAgIHBhc3N3b3JkOiBtb2NrUGFzc3dvcmQsXG4gICAgICAgIGVuY3J5cHRpb25WZXJzaW9uOiAyLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoSlNPTi5wYXJzZShlbmNyeXB0ZWRXU2hhcmUpLnYsIDIsICdwcmUtY29uZGl0aW9uOiB3U2hhcmUgbXVzdCBiZSB2Mi1lbmNyeXB0ZWQnKTtcbiAgICAgIGNvbnN0IHN0ZXAyU2lnbmluZ01hdGVyaWFsID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlT2ZmbGluZU11RGVsdGFTaGFyZSh7XG4gICAgICAgIGFTaGFyZUZyb21CaXRnbzogYVNoYXJlLFxuICAgICAgICBiaXRnb0NoYWxsZW5nZTogYml0Z29DaGFsbGVuZ2VzLFxuICAgICAgICBlbmNyeXB0ZWRXU2hhcmUsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IG1vY2tQYXNzd29yZCxcbiAgICAgIH0pO1xuICAgICAgc3RlcDJTaWduaW5nTWF0ZXJpYWwubXVEU2hhcmUubXVTaGFyZS5hbHBoYS5sZW5ndGguc2hvdWxkLmVxdWFsKGFscGhhTGVuZ3RoKTtcbiAgICAgIHN0ZXAyU2lnbmluZ01hdGVyaWFsLm11RFNoYXJlLmRTaGFyZS5kZWx0YS5sZW5ndGguc2hvdWxkLmVxdWFsKGRlbHRhTGVuZ3RoKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVPZmZsaW5lU1NoYXJlIHNob3VsZCBzdWNjZWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja1Bhc3N3b3JkID0gJ3Bhc3N3b3JkJztcbiAgICAgIGNvbnN0IHB1YktleUxlbmd0aCA9IDY2O1xuICAgICAgY29uc3QgcHJpdktleUxlbmd0aCA9IDY0O1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCBzdGVwM1NpZ25pbmdNYXRlcmlhbCA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZU9mZmxpbmVTU2hhcmUoe1xuICAgICAgICB0c3NQYXJhbXM6IHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdCxcbiAgICAgICAgICByZXFJZDogcmVxSWQsXG4gICAgICAgIH0sXG4gICAgICAgIGRTaGFyZUZyb21CaXRnbzogZFNoYXJlLFxuICAgICAgICBlbmNyeXB0ZWRPU2hhcmU6IGF3YWl0IGJpdGdvLmVuY3J5cHQoeyBpbnB1dDogSlNPTi5zdHJpbmdpZnkob1NoYXJlKSwgcGFzc3dvcmQ6IG1vY2tQYXNzd29yZCB9KSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogbW9ja1Bhc3N3b3JkLFxuICAgICAgICByZXF1ZXN0VHlwZTogUmVxdWVzdFR5cGUudHgsXG4gICAgICB9KTtcbiAgICAgIHN0ZXAzU2lnbmluZ01hdGVyaWFsLlIubGVuZ3RoLnNob3VsZC5lcXVhbChwdWJLZXlMZW5ndGgpO1xuICAgICAgc3RlcDNTaWduaW5nTWF0ZXJpYWwueS5sZW5ndGguc2hvdWxkLmVxdWFsKHB1YktleUxlbmd0aCk7XG4gICAgICBzdGVwM1NpZ25pbmdNYXRlcmlhbC5zLmxlbmd0aC5zaG91bGQuZXF1YWwocHJpdktleUxlbmd0aCk7XG4gICAgfSk7XG5cbiAgICBpdCgnY3JlYXRlT2ZmbGluZVNTaGFyZSBzaG91bGQgc3VjY2VlZCB3aXRoIHYyLWVuY3J5cHRlZCBvU2hhcmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrUGFzc3dvcmQgPSAncGFzc3dvcmQnO1xuICAgICAgY29uc3QgcHViS2V5TGVuZ3RoID0gNjY7XG4gICAgICBjb25zdCBwcml2S2V5TGVuZ3RoID0gNjQ7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGNvbnN0IGVuY3J5cHRlZE9TaGFyZSA9IGF3YWl0IGJpdGdvLmVuY3J5cHQoe1xuICAgICAgICBpbnB1dDogSlNPTi5zdHJpbmdpZnkob1NoYXJlKSxcbiAgICAgICAgcGFzc3dvcmQ6IG1vY2tQYXNzd29yZCxcbiAgICAgICAgZW5jcnlwdGlvblZlcnNpb246IDIsXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChKU09OLnBhcnNlKGVuY3J5cHRlZE9TaGFyZSkudiwgMiwgJ3ByZS1jb25kaXRpb246IG9TaGFyZSBtdXN0IGJlIHYyLWVuY3J5cHRlZCcpO1xuICAgICAgY29uc3Qgc3RlcDNTaWduaW5nTWF0ZXJpYWwgPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVPZmZsaW5lU1NoYXJlKHtcbiAgICAgICAgdHNzUGFyYW1zOiB7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3QsXG4gICAgICAgICAgcmVxSWQ6IHJlcUlkLFxuICAgICAgICB9LFxuICAgICAgICBkU2hhcmVGcm9tQml0Z286IGRTaGFyZSxcbiAgICAgICAgZW5jcnlwdGVkT1NoYXJlLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBtb2NrUGFzc3dvcmQsXG4gICAgICAgIHJlcXVlc3RUeXBlOiBSZXF1ZXN0VHlwZS50eCxcbiAgICAgIH0pO1xuICAgICAgc3RlcDNTaWduaW5nTWF0ZXJpYWwuUi5sZW5ndGguc2hvdWxkLmVxdWFsKHB1YktleUxlbmd0aCk7XG4gICAgICBzdGVwM1NpZ25pbmdNYXRlcmlhbC55Lmxlbmd0aC5zaG91bGQuZXF1YWwocHViS2V5TGVuZ3RoKTtcbiAgICAgIHN0ZXAzU2lnbmluZ01hdGVyaWFsLnMubGVuZ3RoLnNob3VsZC5lcXVhbChwcml2S2V5TGVuZ3RoKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVPZmZsaW5lU1NoYXJlIHNob3VsZCBmYWlsIHdpdGggdHhJZCBwYXNzZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrUGFzc3dvcmQgPSAncGFzc3dvcmQnO1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlT2ZmbGluZVNTaGFyZSh7XG4gICAgICAgICAgdHNzUGFyYW1zOiB7XG4gICAgICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgICAgICAgIHJlcUlkOiByZXFJZCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGRTaGFyZUZyb21CaXRnbzogZFNoYXJlLFxuICAgICAgICAgIGVuY3J5cHRlZE9TaGFyZTogYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiBKU09OLnN0cmluZ2lmeShvU2hhcmUpLCBwYXNzd29yZDogbW9ja1Bhc3N3b3JkIH0pLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IG1vY2tQYXNzd29yZCxcbiAgICAgICAgICByZXF1ZXN0VHlwZTogUmVxdWVzdFR5cGUudHgsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIHR4UmVxdWVzdCB0eXBlJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2lnblR4UmVxdWVzdCBzaG91bGQgZmFpbCB3aXRoIGludmFsaWQgdXNlciBwcnYnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkVXNlcktleSA9IHsgLi4udXNlcktleVNoYXJlLCBwU2hhcmU6IHsgLi4udXNlcktleVNoYXJlLnBTaGFyZSwgaTogMiB9IH07XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuc2lnblR4UmVxdWVzdCh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RJZCxcbiAgICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHBTaGFyZTogaW52YWxpZFVzZXJLZXkucFNoYXJlLFxuICAgICAgICAgICAgYml0Z29OU2hhcmU6IGJpdGdvS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICAgIGJhY2t1cE5TaGFyZTogYmFja3VwS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICByZXFJZCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQgdXNlciBrZXknKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBmYWlsIHdpdGggbm8gYmFja3VwTlNoYXJlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGdldFR4UmVxdWVzdCA9IHNhbmRib3guc3R1Yih0c3NVdGlscywgJ2dldFR4UmVxdWVzdCcpO1xuICAgICAgZ2V0VHhSZXF1ZXN0LnJlc29sdmVzKHR4UmVxdWVzdCk7XG4gICAgICBnZXRUeFJlcXVlc3QuY2FsbGVkV2l0aCh0eFJlcXVlc3RJZCk7XG4gICAgICBzZXR1cFNpZ25UeFJlcXVlc3ROb2NrcyhmYWxzZSwgdXNlclNpZ25TaGFyZSwgYVNoYXJlLCBkU2hhcmUsIGVudGVycHJpc2VEYXRhKTtcbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdElkLFxuICAgICAgICAgIHBydjogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgcFNoYXJlOiB1c2VyS2V5U2hhcmUucFNoYXJlLFxuICAgICAgICAgICAgYml0Z29OU2hhcmU6IGJpdGdvS2V5U2hhcmUublNoYXJlc1sxXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICByZXFJZCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQgdXNlciBrZXkgLSBtaXNzaW5nIGJhY2t1cE5TaGFyZScpO1xuICAgIH0pO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gc2V0dXBTaWduVHhSZXF1ZXN0Tm9ja3MoXG4gICAgICBpc1R4UmVxdWVzdCA9IHRydWUsXG4gICAgICB1c2VyU2lnblNoYXJlOiBFQ0RTQS5TaWduU2hhcmVSVCxcbiAgICAgIGFTaGFyZTogRUNEU0EuQVNoYXJlLFxuICAgICAgZFNoYXJlOiBFQ0RTQS5EU2hhcmUsXG4gICAgICBlbnRlcnByaXNlRGF0YTogRW50ZXJwcmlzZURhdGEsXG4gICAgICB7XG4gICAgICAgIHNpZ25hYmxlSGV4LFxuICAgICAgICBzZXJpYWxpemVkVHhIZXgsXG4gICAgICAgIGFwaVZlcnNpb24sXG4gICAgICB9OiB7IHNpZ25hYmxlSGV4Pzogc3RyaW5nOyBzZXJpYWxpemVkVHhIZXg/OiBzdHJpbmc7IGFwaVZlcnNpb24/OiAnZnVsbCcgfCAnbGl0ZScgfSA9IHt9XG4gICAgKSB7XG4gICAgICBpZiAoZW50ZXJwcmlzZURhdGEpIHtcbiAgICAgICAgYXdhaXQgbm9ja0dldEVudGVycHJpc2UoeyBlbnRlcnByaXNlSWQ6IGVudGVycHJpc2VEYXRhLmlkLCByZXNwb25zZTogZW50ZXJwcmlzZURhdGEsIHRpbWVzOiAxIH0pO1xuICAgICAgfVxuICAgICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSAnJztcbiAgICAgIHNpbm9uLnN0dWIoRUNEU0FNZXRob2RzLCAnY3JlYXRlVXNlclNpZ25TaGFyZScpLnJlc29sdmVzKHVzZXJTaWduU2hhcmUpO1xuICAgICAgbGV0IHJlc3BvbnNlID0ge1xuICAgICAgICB0eFJlcXVlc3RzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4udHhSZXF1ZXN0LFxuICAgICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAuLi50eFJlcXVlc3QsXG4gICAgICAgICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgICAgICAgc2lnbmFibGVIZXg6IHNpZ25hYmxlSGV4ID8/IHR4UmVxdWVzdC51bnNpZ25lZFR4c1swXS5zaWduYWJsZUhleCxcbiAgICAgICAgICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogc2VyaWFsaXplZFR4SGV4ID8/IHR4UmVxdWVzdC51bnNpZ25lZFR4c1swXS5zZXJpYWxpemVkVHhIZXgsXG4gICAgICAgICAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGFwaVZlcnNpb246IGFwaVZlcnNpb24sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBpZiAoaXNUeFJlcXVlc3QpIHtcbiAgICAgICAgYXdhaXQgbm9ja0dldFR4UmVxdWVzdCh7IHdhbGxldElkOiB3YWxsZXQuaWQoKSwgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCwgcmVzcG9uc2U6IHJlc3BvbnNlIH0pO1xuICAgICAgfVxuICAgICAgY29uc3QgYVJlY29yZCA9IEVDRFNBTWV0aG9kcy5jb252ZXJ0QVNoYXJlKGFTaGFyZSk7XG4gICAgICBjb25zdCBzaWduYXR1cmVTaGFyZXMgPSBbYVJlY29yZF07XG4gICAgICB0eFJlcXVlc3Quc2lnbmF0dXJlU2hhcmVzID0gc2lnbmF0dXJlU2hhcmVzO1xuICAgICAgcmVzcG9uc2UgPSB7XG4gICAgICAgIHR4UmVxdWVzdHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi50eFJlcXVlc3QsXG4gICAgICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC4uLnR4UmVxdWVzdCxcbiAgICAgICAgICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgICAgICAgICBzaWduYWJsZUhleDogdHhSZXF1ZXN0LnVuc2lnbmVkVHhzWzBdLnNpZ25hYmxlSGV4LFxuICAgICAgICAgICAgICAgICAgc2VyaWFsaXplZFR4SGV4OiB0eFJlcXVlc3QudW5zaWduZWRUeHNbMF0uc2VyaWFsaXplZFR4SGV4LFxuICAgICAgICAgICAgICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBhcGlWZXJzaW9uOiBhcGlWZXJzaW9uLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgYXdhaXQgbm9ja0dldFR4UmVxdWVzdCh7IHdhbGxldElkOiB3YWxsZXQuaWQoKSwgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCwgcmVzcG9uc2U6IHJlc3BvbnNlIH0pO1xuICAgICAgY29uc3QgZFJlY29yZCA9IEVDRFNBTWV0aG9kcy5jb252ZXJ0RFNoYXJlKGRTaGFyZSk7XG4gICAgICBzaWduYXR1cmVTaGFyZXMucHVzaChkUmVjb3JkKTtcbiAgICAgIHJlc3BvbnNlID0ge1xuICAgICAgICB0eFJlcXVlc3RzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4udHhSZXF1ZXN0LFxuICAgICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAuLi50eFJlcXVlc3QsXG4gICAgICAgICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgICAgICAgc2lnbmFibGVIZXg6IHR4UmVxdWVzdC51bnNpZ25lZFR4c1swXS5zaWduYWJsZUhleCxcbiAgICAgICAgICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogdHhSZXF1ZXN0LnVuc2lnbmVkVHhzWzBdLnNlcmlhbGl6ZWRUeEhleCxcbiAgICAgICAgICAgICAgICAgIGRlcml2YXRpb25QYXRoLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgYXBpVmVyc2lvbjogYXBpVmVyc2lvbixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IG5vY2tHZXRUeFJlcXVlc3QoeyB3YWxsZXRJZDogd2FsbGV0LmlkKCksIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsIHJlc3BvbnNlOiByZXNwb25zZSB9KTtcbiAgICAgIGF3YWl0IG5vY2tHZXRUeFJlcXVlc3QoeyB3YWxsZXRJZDogd2FsbGV0LmlkKCksIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsIHJlc3BvbnNlOiByZXNwb25zZSB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRFY2RzYVNpZ25pbmdDaGFsbGVuZ2VzJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IG1vY2tXYWxsZXRQYWlsbGllcktleSA9IHtcbiAgICAgIG46ICdmNDdiZTRjMmQ4YmMxZTI4Zjg4YzZjNGRhNjM0ZGE5N2Q5MmExYzI3OWE3YjBmZTdiODdjMzM3YzM2YTI3YjMyY2UwZmYwYzQ1ZjE2ZTRlMTViYmQyMGU0ZTY0MGRlMTIwNDdlZmY5YjFhMmI5ODE0NGY5YTI2OGQ0MDZiZDAwMGQxOTJhMzViNjg0N2ExN2U0MGZiODVmNTViMzE0ZDAwMWZmODczOTM0ODFjYWZlMzkxODA3ZDBlYjgzZWZmOWUzODYxNGIzOGU1ZjI1ZmM0NDQ5Y2IwMWNhZWQ4MDU1ODRkMDI2YjVkODY2YzcyM2YzZDRkNGYxZTQ2MjY2MmYyMTEzYjE1NjFlYjJiZjc1NWI0YjkxZDAzMDhkOGVhY2M0MzkxNjdkYThiN2Q2ZTEwODUyNGYyMjY5NjAzNjBhZjAwMjE1ZDk2MTQ0NTc0MTRlYmRiZTg4MzQ5OTk2ODllMmU5MDMyMDhjODcxM2ZmNWQ5OTAxZjllYWJhM2FhODFkNzA1MzIzY2JiYmE2MWJhN2ZhOWYzMjI4ZjMwODUzZmI1NWRhMWIzZDNlZDdkYjFkZmM2NTQ1YmM5NmFhOGQyZWI4NDg5MzFjMWI4MDdmZGZlOGY2NWFmNzJmNjg2MzhhODJmZTllMjJhYzFmMGYwMzJlNjIxMDY2ODA2YTFmMTQ0YjU3MTlhNWYwOTE5ODY4NjdiMzg0YmU2YzM0MTQ2YzgyNDFjYmZiZDc4MTk2NmViYmNkMTllNmNhYTI3ZmFiMDQwZTYyZTVhMTYyODg4YWE4NjI0ZDA0NmM4ZmUzYjcyMjQ0ZjA0YTcyNjRjNGEzNmI2MzY2ZGJlN2RhOThhZmIyMDFkMzRiZTJjMGQ2ZGQxMTk4MmFmMzViZjc1MzU1ODJiMjYzOTE0NzI1YWFlYzI4MGQ1MjI5MDUyNzM4MmQzYWIyOTdkNzQ2YzQxYWFjZDhkZTk4YzA5ZmNmYjg1YTk1ZTAyZGUxYjM0ZDQ5MzNlNTEwNDVlMmYxY2U4YWYnLFxuICAgICAgbGFtYmRhOlxuICAgICAgICAnZjQ3YmU0YzJkOGJjMWUyOGY4OGM2YzRkYTYzNGRhOTdkOTJhMWMyNzlhN2IwZmU3Yjg3YzMzN2MzNmEyN2IzMmNlMGZmMGM0NWYxNmU0ZTE1YmJkMjBlNGU2NDBkZTEyMDQ3ZWZmOWIxYTJiOTgxNDRmOWEyNjhkNDA2YmQwMDBkMTkyYTM1YjY4NDdhMTdlNDBmYjg1ZjU1YjMxNGQwMDFmZjg3MzkzNDgxY2FmZTM5MTgwN2QwZWI4M2VmZjllMzg2MTRiMzhlNWYyNWZjNDQ0OWNiMDFjYWVkODA1NTg0ZDAyNmI1ZDg2NmM3MjNmM2Q0ZDRmMWU0NjI2NjJmMjExM2IxNTYxZWIyYmY3NTViNGI5MWQwMzA4ZDhlYWNjNDM5MTY3ZGE4YjdkNmUxMDg1MjRmMjI2OTYwMzYwYWYwMDIxNWQ5NjE0NDU3NDE0ZWJkYmU4ODM0OTk5Njg5ZTJlOTAzMjA4Yzg3MTNmZjVkOTkwMWY5ZWFiYTNhYTdmYzNkMGMwYmNjNWJmZjY0NDE1NmFiODg3MTQ2ZDUxYmNlZTFlZWY3MGY0NWM0ODYxNDdkNjg3ZWUzN2RlZjFmOGExNmJjOTQ1ZWZmMjJkZDRkY2EzNjE0YTk5MTU4ODIzYWNkOTQ5MmUzNDdmN2VjNzlhNzc3MTAyNDIwNWQwN2YyN2IzMGNkMjAzNDBlMzMwNDExZGE4ZmEyZGEyMDllNWNjNjg4ZGE5NGQxZGJlZjU0YmZkOWM2OWI0ZTk5Y2YwNmQ2NzMwOWEzNDIwYjgyYzc4YTBmZTBkZDBiOWMzMTM4MmVhZTM4NzQ2Y2ZkZDI3ZmE5MDAyMmE1MDUzMjI0NmM4YWUxMzM5YzkzZTE4M2MwM2JmNmZkNzAxNGJlMzY1OGFiYzczYmFhZTFmYTViODZkYWI5NGI5ZjEyNTM5NWE4MThlNTRkZGU2MjM1YzQ1ZDNkYmMwMzJiMzA3OGU5ZGYxY2FkNjlkOGFjMTlhN2NiNjQwNWE1NThiN2JmYmE4JyxcbiAgICB9O1xuICAgIGNvbnN0IG1vY2tCaXRnb1BhaWxsaWVyS2V5ID0ge1xuICAgICAgbjogJ2YwMTBkMjk0ZWZmY2ViOGM0Zjk2YWYxOTc4YWIzNjdjNGZiYjI3MmMyMTY5MzE3ZTQxYWU4NzIyMDY1MmNhZTJjZTkyOTY5NmVlNTVlYzY4MzFhYTZiNGIzYjkzMWJhYmMyYmFjOWMxYTIwZmRkYmNhOTI1Y2M5OTY4MDc5MWY3YzMxNTdiM2QzMTI1NmVlNzJjNDdkNDdkYjU2N2UwZjA3MGRjZTEyMWMzYTRkOWUwMDNjMWYxMzg5MDczYWNiMjUyYzY1ZDJiMDcyM2U4NmUzMjY1ZjY3YTEzN2NiMWUyM2Y0NTUxNTQ0NDA1NjQ0ZDBhZTYzZDM1ZjI1ZjQwYmVjZDJiNjkzODc5ZjNiZGJlYzNmNzI1MDc5MWEzZjNjOTc1YTVhYzc4YTBlODFkY2QxYTg3ZWIyY2E2NzAxMGRmZjg4MGIyMzM4NTU2Mjc1ZGUyM2Q5ZTg4ZDIxYjc3ZGEwZDUyNGRkYzJiMzk0ZjhkZTAwYjFhZjBjZTg1ZjZlZWUyZTA1YTE4NGUwNTQ5NGQ2NmQyYzYzNjA0NWJmNzBlZDE1ZWJkMGY0MWE4ZWVhMjkyMGFmODVlNmQ2OGEwY2UxMWZjMmFiYmNiM2NlYmNjM2MyM2VjMmUxNDhjMzE4NjgzYTU0MjZlMTViNTIwN2VmZDNiOWIwNWNiOTE5ZWM0MzQwZjc0ZGZmMzM2OTg2ZDBjOTIzZGYxMGE3ODkwMDdiMWRhOWRhZGRmOGVkZjMwMTRlOTM5ODlmMzAyNDNmMjdmOWEzMDdkNTVkNjMwY2JmY2QxNmNkNmE5NWE0MWRlZTEwYzMxYWNjMjkzZGY2ODM0Y2UwZTNlYTViNjhmMTcwYmQ3OTM4ZWEwYzJlZWI3ODhlMTZmMzBhZjU3YjNmMDg4OGZiNDRkMzYxMGU3ZWViYTYwZTdmZDhjYzRhOGYwNDQ3MThkZmM2MTc0YmY0YTM4MDY5MGRjMWRjNzc0NzJhNDg4OTJlYjNlODE3NzU1NDBlYTBhY2M5ZTg5YjYzOScsXG4gICAgICBsYW1iZGE6XG4gICAgICAgICdmMDEwZDI5NGVmZmNlYjhjNGY5NmFmMTk3OGFiMzY3YzRmYmIyNzJjMjE2OTMxN2U0MWFlODcyMjA2NTJjYWUyY2U5Mjk2OTZlZTU1ZWM2ODMxYWE2YjRiM2I5MzFiYWJjMmJhYzljMWEyMGZkZGJjYTkyNWNjOTk2ODA3OTFmN2MzMTU3YjNkMzEyNTZlZTcyYzQ3ZDQ3ZGI1NjdlMGYwNzBkY2UxMjFjM2E0ZDllMDAzYzFmMTM4OTA3M2FjYjI1MmM2NWQyYjA3MjNlODZlMzI2NWY2N2ExMzdjYjFlMjNmNDU1MTU0NDQwNTY0NGQwYWU2M2QzNWYyNWY0MGJlY2QyYjY5Mzg3OWYzYmRiZWMzZjcyNTA3OTFhM2YzYzk3NWE1YWM3OGEwZTgxZGNkMWE4N2ViMmNhNjcwMTBkZmY4ODBiMjMzODU1NjI3NWRlMjNkOWU4OGQyMWI3N2RhMGQ1MjRkZGMyYjM5NGY4ZGUwMGIxYWYwY2U4NWY2ZWNkZWY4YTRiYzk1NWEyOGVjZWY3ZDk3Y2RlZDA3OWQzOTBlNzdjODA5OThkNzhhZDk1MTBjYmFiZmViOGYwYTE1N2RiZmM1OTBiNGQ1OWVlOGMwYjA4OGY5ZDg5NDczYjU1NzMyMDA3OGExMTc0Nzg2MjRmNWQxZGYzNmUzMGYzMjBiNjcyMmE0MjE3ZGNiNDZiOTc4Y2M2YzhmMWEyMWM4YTZjNzRiY2U4NGQ4MmM0ODE0MDJjOTlhNjliNzk4ZTNjMDVmMjMzNTBiNGFhZGU0Zjc5Nzg0YjFjMDk2OTJiNmEzM2NmYmE3ZjE0NTU5N2Q4MmI3OTljY2NlZjYyMGMzNmYxZmJiZTJjYjRhYzBlYTM5NWM0NzZlMzgxYmM0NzVkNDE3MjIzMjBmNTQxYWU5YmY1NmFhNGExMmRmZjNlYTdhYjExMTc0ZmI1YjhkZjc0MjljOWY1N2QzNmY4ZmM1MWUxYThjNjQ3ZDViOGZhMDE4OWZiOGFjZGJkMGE3ODAnLFxuICAgIH07XG4gICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgY29uc3QgdHhSZXF1ZXN0SWQgPSAnZmFrZVR4UmVxdWVzdElkJztcbiAgICBjb25zdCByYXdFbnRDaGFsbGVuZ2VXaXRoUHJvb2ZzOiBFY2RzYVR5cGVzLlNlcmlhbGl6ZWROdGlsZGVXaXRoUHJvb2ZzID0gbW9ja1NlcmlhbGl6ZWRDaGFsbGVuZ2VXaXRoUHJvb2ZzO1xuICAgIGxldCByYXdCaXRnb0NoYWxsZW5nZTogRWNkc2FUeXBlcy5TZXJpYWxpemVkRWNkc2FDaGFsbGVuZ2VzICYgeyBuOiBzdHJpbmcgfTtcbiAgICBjb25zdCBhZG1pbkVjZGhLZXkgPSBiaXRnby5rZXljaGFpbnMoKS5jcmVhdGUoKTtcbiAgICBjb25zdCBmYWtlQWRtaW5FY2RoS2V5ID0gYml0Z28ua2V5Y2hhaW5zKCkuY3JlYXRlKCk7XG4gICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSAnbS8wLzAnO1xuICAgIGNvbnN0IG1vY2tlZFNpZ25pbmdLZXkgPSB7XG4gICAgICB1c2VySWQ6ICdpZCcsXG4gICAgICB1c2VyRW1haWw6ICd1c2VyQGJpdGdvLmNvbScsXG4gICAgICBkZXJpdmVkUHVia2V5OiBiaXAzMi5mcm9tQmFzZTU4KGFkbWluRWNkaEtleS54cHViKS5kZXJpdmVQYXRoKGRlcml2YXRpb25QYXRoKS5wdWJsaWNLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgZGVyaXZhdGlvblBhdGg6IGRlcml2YXRpb25QYXRoLFxuICAgICAgZWNkaEtleWNoYWluOiAnbXkga2V5Y2hhaW4nLFxuICAgIH07XG5cbiAgICBiZWZvcmUoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcCA9IGF3YWl0IEVjZHNhUGFpbGxpZXJQcm9vZi5nZW5lcmF0ZVAoaGV4VG9CaWdJbnQobW9ja1dhbGxldFBhaWxsaWVyS2V5Lm4pKTtcbiAgICAgIHJhd0JpdGdvQ2hhbGxlbmdlID0ge1xuICAgICAgICAuLi5FY2RzYVR5cGVzLnNlcmlhbGl6ZU50aWxkZShFY2RzYVR5cGVzLmRlc2VyaWFsaXplTnRpbGRlKG1vY2tTZXJpYWxpemVkQ2hhbGxlbmdlV2l0aFByb29mczIpKSxcbiAgICAgICAgcDogRWNkc2FUeXBlcy5zZXJpYWxpemVQYWlsbGllckNoYWxsZW5nZSh7IHAgfSkucCxcbiAgICAgICAgbjogbW9ja0JpdGdvUGFpbGxpZXJLZXkubixcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2lub24ucmVzdG9yZSgpO1xuICAgICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmZXRjaCBzdGF0aWMgZW50IGFuZCBiaXRnbyBjaGFsbGVuZ2VzIHdpdGggdGhlIGVudCBmZWF0dXJlIGZsYWcgYW5kIHZlcmlmeSB0aGVtJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgbm9ja0dldENoYWxsZW5nZSh7IHdhbGxldElkLCB0eFJlcXVlc3RJZCwgYWRkZW5kdW06ICcvdHJhbnNhY3Rpb25zLzAnLCByZXNwb25zZTogcmF3Qml0Z29DaGFsbGVuZ2UgfSk7XG4gICAgICBhd2FpdCBub2NrR2V0U2lnbmluZ0tleSh7IGVudGVycHJpc2VJZCwgdXNlcklkOiBtb2NrZWRTaWduaW5nS2V5LnVzZXJJZCwgcmVzcG9uc2U6IG1vY2tlZFNpZ25pbmdLZXksIHRpbWVzOiAxIH0pO1xuICAgICAgY29uc3QgYWRtaW5TaWduYXR1cmVFbnRDaGFsbGVuZ2UgPSBFQ0RTQVV0aWxzLkVjZHNhVXRpbHMuc2lnbkNoYWxsZW5nZShcbiAgICAgICAgcmF3RW50Q2hhbGxlbmdlV2l0aFByb29mcyxcbiAgICAgICAgYWRtaW5FY2RoS2V5LnhwcnYsXG4gICAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgICApO1xuICAgICAgY29uc3QgYWRtaW5TaWduYXR1cmVCaXRHb0NoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICByYXdCaXRnb0NoYWxsZW5nZSxcbiAgICAgICAgYWRtaW5FY2RoS2V5LnhwcnYsXG4gICAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgICApO1xuICAgICAgY29uc3QgbW9ja0NoYWxsZW5nZXNSZXNwb25zZSA9IHtcbiAgICAgICAgZW50ZXJwcmlzZUNoYWxsZW5nZToge1xuICAgICAgICAgIC4uLnJhd0VudENoYWxsZW5nZVdpdGhQcm9vZnMsXG4gICAgICAgICAgdmVyaWZpZXJzOiB7XG4gICAgICAgICAgICBhZG1pblNpZ25hdHVyZTogYWRtaW5TaWduYXR1cmVFbnRDaGFsbGVuZ2UudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGJpdGdvQ2hhbGxlbmdlOiB7XG4gICAgICAgICAgLi4ucmF3Qml0Z29DaGFsbGVuZ2UsXG4gICAgICAgICAgdmVyaWZpZXJzOiB7XG4gICAgICAgICAgICBhZG1pblNpZ25hdHVyZTogYWRtaW5TaWduYXR1cmVCaXRHb0NoYWxsZW5nZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgY3JlYXRlZEJ5OiAnaWQnLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgbm9ja0dldENoYWxsZW5nZXMoeyB3YWxsZXRJZDogd2FsbGV0SWQsIHJlc3BvbnNlOiBtb2NrQ2hhbGxlbmdlc1Jlc3BvbnNlIH0pO1xuICAgICAgY29uc3QgY2hhbGxlbmdlcyA9IGF3YWl0IHRzc1V0aWxzLmdldEVjZHNhU2lnbmluZ0NoYWxsZW5nZXModHhSZXF1ZXN0SWQsIDAsIG1vY2tXYWxsZXRQYWlsbGllcktleS5uLCAwKTtcbiAgICAgIHNob3VsZC5leGlzdChjaGFsbGVuZ2VzKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkUmFuZ2VQcm9vZkNoYWxsZW5nZXMgPSB7XG4gICAgICAgIGVudGVycHJpc2VDaGFsbGVuZ2U6IHtcbiAgICAgICAgICBudGlsZGU6IGNoYWxsZW5nZXMuZW50ZXJwcmlzZUNoYWxsZW5nZS5udGlsZGUsXG4gICAgICAgICAgaDE6IGNoYWxsZW5nZXMuZW50ZXJwcmlzZUNoYWxsZW5nZS5oMSxcbiAgICAgICAgICBoMjogY2hhbGxlbmdlcy5lbnRlcnByaXNlQ2hhbGxlbmdlLmgyLFxuICAgICAgICB9LFxuICAgICAgICBiaXRnb0NoYWxsZW5nZTogcmF3Qml0Z29DaGFsbGVuZ2UsXG4gICAgICB9O1xuICAgICAgZXhwZWN0ZWRSYW5nZVByb29mQ2hhbGxlbmdlcy5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgZW50ZXJwcmlzZUNoYWxsZW5nZToge1xuICAgICAgICAgIG50aWxkZTogcmF3RW50Q2hhbGxlbmdlV2l0aFByb29mcy5udGlsZGUsXG4gICAgICAgICAgaDE6IHJhd0VudENoYWxsZW5nZVdpdGhQcm9vZnMuaDEsXG4gICAgICAgICAgaDI6IHJhd0VudENoYWxsZW5nZVdpdGhQcm9vZnMuaDIsXG4gICAgICAgIH0sXG4gICAgICAgIGJpdGdvQ2hhbGxlbmdlOiByYXdCaXRnb0NoYWxsZW5nZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ0ZhaWxzIGlmIHRoZSBlbnRlcnByaXNlIGNoYWxsZW5nZSBzaWduYXR1cmUgaXMgZGlmZmVyZW50IGZyb20gdGhlIGFkbWluIGVjZGgga2V5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgbm9ja0dldENoYWxsZW5nZSh7IHdhbGxldElkLCB0eFJlcXVlc3RJZCwgYWRkZW5kdW06ICcvdHJhbnNhY3Rpb25zLzAnLCByZXNwb25zZTogcmF3Qml0Z29DaGFsbGVuZ2UgfSk7XG4gICAgICBhd2FpdCBub2NrR2V0RW50ZXJwcmlzZSh7XG4gICAgICAgIGVudGVycHJpc2VJZDogZW50ZXJwcmlzZURhdGEuaWQsXG4gICAgICAgIHJlc3BvbnNlOiB7XG4gICAgICAgICAgLi4uZW50ZXJwcmlzZURhdGEsXG4gICAgICAgICAgZmVhdHVyZUZsYWdzOiBbJ3VzZUVudGVycHJpc2VFY2RzYVRzc0NoYWxsZW5nZSddLFxuICAgICAgICB9LFxuICAgICAgICB0aW1lczogMSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgbm9ja0dldFNpZ25pbmdLZXkoeyBlbnRlcnByaXNlSWQsIHVzZXJJZDogbW9ja2VkU2lnbmluZ0tleS51c2VySWQsIHJlc3BvbnNlOiBtb2NrZWRTaWduaW5nS2V5LCB0aW1lczogMSB9KTtcbiAgICAgIC8vIEJhZCBzaWduXG4gICAgICBjb25zdCBhZG1pblNpZ25lZEVudENoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICByYXdFbnRDaGFsbGVuZ2VXaXRoUHJvb2ZzLFxuICAgICAgICBmYWtlQWRtaW5FY2RoS2V5LnhwcnYsXG4gICAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgICApO1xuICAgICAgY29uc3QgYWRtaW5TaWduZWRCaXRHb0NoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICByYXdCaXRnb0NoYWxsZW5nZSxcbiAgICAgICAgYWRtaW5FY2RoS2V5LnhwcnYsXG4gICAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgICApO1xuICAgICAgY29uc3QgbW9ja0NoYWxsZW5nZXNSZXNwb25zZSA9IHtcbiAgICAgICAgZW50ZXJwcmlzZUNoYWxsZW5nZToge1xuICAgICAgICAgIC4uLnJhd0VudENoYWxsZW5nZVdpdGhQcm9vZnMsXG4gICAgICAgICAgdmVyaWZpZXJzOiB7XG4gICAgICAgICAgICBhZG1pblNpZ25hdHVyZTogYWRtaW5TaWduZWRFbnRDaGFsbGVuZ2UudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGJpdGdvQ2hhbGxlbmdlOiB7XG4gICAgICAgICAgLi4ucmF3Qml0Z29DaGFsbGVuZ2UsXG4gICAgICAgICAgdmVyaWZpZXJzOiB7XG4gICAgICAgICAgICBhZG1pblNpZ25hdHVyZTogYWRtaW5TaWduZWRCaXRHb0NoYWxsZW5nZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgY3JlYXRlZEJ5OiAnaWQnLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IG5vY2tHZXRDaGFsbGVuZ2VzKHsgd2FsbGV0SWQ6IHdhbGxldElkLCByZXNwb25zZTogbW9ja0NoYWxsZW5nZXNSZXNwb25zZSB9KTtcbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC5nZXRFY2RzYVNpZ25pbmdDaGFsbGVuZ2VzKHR4UmVxdWVzdElkLCAwLCBtb2NrV2FsbGV0UGFpbGxpZXJLZXkubilcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ0FkbWluIHNpZ25hdHVyZSBmb3IgZW50ZXJwcmlzZSBjaGFsbGVuZ2UgaXMgbm90IHZhbGlkLiBQbGVhc2UgY29udGFjdCB5b3VyIGVudGVycHJpc2UgYWRtaW4uJ1xuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ0ZhaWxzIGlmIHRoZSBiaXRnbyBjaGFsbGVuZ2Ugc2lnbmF0dXJlIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBhZG1pbiBlY2RoIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IG5vY2tHZXRDaGFsbGVuZ2UoeyB3YWxsZXRJZCwgdHhSZXF1ZXN0SWQsIGFkZGVuZHVtOiAnL3RyYW5zYWN0aW9ucy8wJywgcmVzcG9uc2U6IHJhd0JpdGdvQ2hhbGxlbmdlIH0pO1xuICAgICAgYXdhaXQgbm9ja0dldEVudGVycHJpc2Uoe1xuICAgICAgICBlbnRlcnByaXNlSWQ6IGVudGVycHJpc2VEYXRhLmlkLFxuICAgICAgICByZXNwb25zZToge1xuICAgICAgICAgIC4uLmVudGVycHJpc2VEYXRhLFxuICAgICAgICAgIGZlYXR1cmVGbGFnczogWyd1c2VFbnRlcnByaXNlRWNkc2FUc3NDaGFsbGVuZ2UnXSxcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXM6IDEsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IG5vY2tHZXRTaWduaW5nS2V5KHsgZW50ZXJwcmlzZUlkLCB1c2VySWQ6IG1vY2tlZFNpZ25pbmdLZXkudXNlcklkLCByZXNwb25zZTogbW9ja2VkU2lnbmluZ0tleSwgdGltZXM6IDEgfSk7XG4gICAgICBjb25zdCBhZG1pblNpZ25lZEVudENoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICByYXdFbnRDaGFsbGVuZ2VXaXRoUHJvb2ZzLFxuICAgICAgICBhZG1pbkVjZGhLZXkueHBydixcbiAgICAgICAgZGVyaXZhdGlvblBhdGhcbiAgICAgICk7XG4gICAgICAvLyBCYWQgc2lnblxuICAgICAgY29uc3QgYWRtaW5TaWduZWRCaXRHb0NoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICByYXdCaXRnb0NoYWxsZW5nZSxcbiAgICAgICAgZmFrZUFkbWluRWNkaEtleS54cHJ2LFxuICAgICAgICBkZXJpdmF0aW9uUGF0aFxuICAgICAgKTtcbiAgICAgIGNvbnN0IG1vY2tDaGFsbGVuZ2VzUmVzcG9uc2UgPSB7XG4gICAgICAgIGVudGVycHJpc2VDaGFsbGVuZ2U6IHtcbiAgICAgICAgICAuLi5yYXdFbnRDaGFsbGVuZ2VXaXRoUHJvb2ZzLFxuICAgICAgICAgIHZlcmlmaWVyczoge1xuICAgICAgICAgICAgYWRtaW5TaWduYXR1cmU6IGFkbWluU2lnbmVkRW50Q2hhbGxlbmdlLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBiaXRnb0NoYWxsZW5nZToge1xuICAgICAgICAgIC4uLnJhd0JpdGdvQ2hhbGxlbmdlLFxuICAgICAgICAgIHZlcmlmaWVyczoge1xuICAgICAgICAgICAgYWRtaW5TaWduYXR1cmU6IGFkbWluU2lnbmVkQml0R29DaGFsbGVuZ2UudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGNyZWF0ZWRCeTogJ2lkJyxcbiAgICAgIH07XG4gICAgICBhd2FpdCBub2NrR2V0Q2hhbGxlbmdlcyh7IHdhbGxldElkOiB3YWxsZXRJZCwgcmVzcG9uc2U6IG1vY2tDaGFsbGVuZ2VzUmVzcG9uc2UgfSk7XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuZ2V0RWNkc2FTaWduaW5nQ2hhbGxlbmdlcyh0eFJlcXVlc3RJZCwgMCwgbW9ja1dhbGxldFBhaWxsaWVyS2V5Lm4pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIFwiQWRtaW4gc2lnbmF0dXJlIGZvciBCaXRHbydzIGNoYWxsZW5nZSBpcyBub3QgdmFsaWQuIFBsZWFzZSBjb250YWN0IHlvdXIgZW50ZXJwcmlzZSBhZG1pbi5cIlxuICAgICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZ2V0VmVyaWZ5QW5kU2lnbkJpdEdvQ2hhbGxlbmdlcycsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBjb25zdCBhZG1pbkVjZGhLZXkgPSBiaXRnby5rZXljaGFpbnMoKS5jcmVhdGUoKTtcbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAvMCc7XG4gICAgY29uc3QgYml0Z29JbnN0Q2hhbGxlbmdlID0gbW9ja0NoYWxsZW5nZUE7XG4gICAgY29uc3QgYml0Z29OaXRyb0NoYWxsZW5nZSA9IG1vY2tDaGFsbGVuZ2VCO1xuICAgIGNvbnN0IHVzZXJQYXNzd29yZCA9ICdwYXNzd29yZDEyMyc7XG4gICAgbGV0IGVuY3J5cHRlZFhwcnY6IHN0cmluZztcblxuICAgIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBlbmNyeXB0ZWRYcHJ2ID0gYXdhaXQgYml0Z28uZW5jcnlwdCh7XG4gICAgICAgIHBhc3N3b3JkOiB1c2VyUGFzc3dvcmQsXG4gICAgICAgIGlucHV0OiBhZG1pbkVjZGhLZXkueHBydixcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBzaW5vbi5zdHViKGJpdGdvLCAnZ2V0U2lnbmluZ0tleUZvclVzZXInKS5yZXNvbHZlcyh7XG4gICAgICAgIHVzZXJJZDogJ2lkJyxcbiAgICAgICAgdXNlckVtYWlsOiAndXNlckBiaXRnby5jb20nLFxuICAgICAgICBkZXJpdmVkUHVia2V5OiBiaXAzMi5mcm9tQmFzZTU4KGFkbWluRWNkaEtleS54cHViKS5kZXJpdmVQYXRoKGRlcml2YXRpb25QYXRoKS5wdWJsaWNLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBkZXJpdmF0aW9uUGF0aDogZGVyaXZhdGlvblBhdGgsXG4gICAgICAgIGVjZGhLZXljaGFpbjogJ215IGtleWNoYWluJyxcbiAgICAgIH0pO1xuICAgICAgc2lub24uc3R1YihiaXRnbywgJ2dldEVDREhLZXljaGFpbicpLnJlc29sdmVzKHtcbiAgICAgICAgZW5jcnlwdGVkWHBydjogZW5jcnlwdGVkWHBydixcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIG5vY2tHZXRCaXRnb0NoYWxsZW5nZXMocmVzcG9uc2U6IHVua25vd24pOiBub2NrLlNjb3BlIHtcbiAgICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KGAvYXBpL3YyL3Rzcy9lY2RzYS9jaGFsbGVuZ2VzYClcbiAgICAgICAgLnRpbWVzKDEpXG4gICAgICAgIC5yZXBseSgoKSA9PiBbMjAwLCByZXNwb25zZV0pO1xuICAgIH1cblxuICAgIGl0KCdzdWNjZWVkcyBmb3IgdmFsaWQgYml0Z28gcHJvb2ZzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaSA9IG5vY2tHZXRCaXRnb0NoYWxsZW5nZXMoe1xuICAgICAgICBiaXRnb05pdHJvSHNtOiBiaXRnb05pdHJvQ2hhbGxlbmdlLFxuICAgICAgICBiaXRnb0luc3RpdHV0aW9uYWxIc206IGJpdGdvSW5zdENoYWxsZW5nZSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBFQ0RTQVV0aWxzLkVjZHNhVXRpbHMuZ2V0VmVyaWZ5QW5kU2lnbkJpdEdvQ2hhbGxlbmdlcyhcbiAgICAgICAgYml0Z28sXG4gICAgICAgICdlbnRfaWQnLFxuICAgICAgICB1c2VyUGFzc3dvcmRcbiAgICAgICkuc2hvdWxkLm5vdC5iZS5yZWplY3RlZCgpO1xuICAgICAgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ0ZhaWxzIGlmIGJpdGdvIGNoYWxsZW5nZSBwcm9vZnMgYXJlIG5vdCBwcmVzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaSA9IG5vY2tHZXRCaXRnb0NoYWxsZW5nZXMoe1xuICAgICAgICBiaXRnb05pdHJvSHNtOiB7XG4gICAgICAgICAgLi4uYml0Z29OaXRyb0NoYWxsZW5nZSxcbiAgICAgICAgICBudGlsZGVQcm9vZjogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgICBiaXRnb0luc3RpdHV0aW9uYWxIc206IGJpdGdvSW5zdENoYWxsZW5nZSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgRUNEU0FVdGlscy5FY2RzYVV0aWxzLmdldFZlcmlmeUFuZFNpZ25CaXRHb0NoYWxsZW5nZXMoYml0Z28sICdlbnRfaWQnLCB1c2VyUGFzc3dvcmQpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICdFeHBlY3RlZCBCaXRHbyBjaGFsbGVuZ2UgcHJvb2YgdG8gYmUgcHJlc2VudC4gQ29udGFjdCBzdXBwb3J0QGJpdGdvLmNvbS4nXG4gICAgICApO1xuICAgICAgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ0ZhaWxzIGlmIHRoZSB1c2VyIHBhc3N3b3JkIHRvIGRlY3J5cHQgdGhlIGVjZGhrZXljaGFpbiBpcyB3cm9uZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vY2tHZXRCaXRnb0NoYWxsZW5nZXNBcGkgPSBub2NrR2V0Qml0Z29DaGFsbGVuZ2VzKHtcbiAgICAgICAgYml0Z29OaXRyb0hzbTogYml0Z29OaXRyb0NoYWxsZW5nZSxcbiAgICAgICAgYml0Z29JbnN0aXR1dGlvbmFsSHNtOiBiaXRnb0luc3RDaGFsbGVuZ2UsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5nZXRWZXJpZnlBbmRTaWduQml0R29DaGFsbGVuZ2VzKGJpdGdvLCAnZW50X2lkJywgJ2JybycpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICdJbmNvcnJlY3QgcGFzc3dvcmQuIFBsZWFzZSB0cnkgYWdhaW4uJ1xuICAgICAgKTtcbiAgICAgIG5vY2tHZXRCaXRnb0NoYWxsZW5nZXNBcGkuaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdGYWlscyBiaXRnbyBjaGFsbGVuZ2UgcHJvb2ZzIGZvciBmYXVsdHkgbml0cm8gaDJXcnRIMSBwcm9vZicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vY2tHZXRCaXRnb0NoYWxsZW5nZXNBcGkgPSBub2NrR2V0Qml0Z29DaGFsbGVuZ2VzKHtcbiAgICAgICAgYml0Z29OaXRyb0hzbToge1xuICAgICAgICAgIC4uLmJpdGdvTml0cm9DaGFsbGVuZ2UsXG4gICAgICAgICAgbnRpbGRlUHJvb2Y6IHtcbiAgICAgICAgICAgIC4uLmJpdGdvTml0cm9DaGFsbGVuZ2UubnRpbGRlUHJvb2YsXG4gICAgICAgICAgICBoMldydEgxOiBiaXRnb05pdHJvQ2hhbGxlbmdlLm50aWxkZVByb29mLmgxV3J0SDIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgYml0Z29JbnN0aXR1dGlvbmFsSHNtOiBiaXRnb0luc3RDaGFsbGVuZ2UsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5nZXRWZXJpZnlBbmRTaWduQml0R29DaGFsbGVuZ2VzKGJpdGdvLCAnZW50X2lkJywgdXNlclBhc3N3b3JkKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICBcIkZhaWxlZCB0byB2ZXJpZnkgQml0R28ncyBjaGFsbGVuZ2UgbmVlZGVkIHRvIGVuYWJsZSBFQ0RTQSBzaWduaW5nLiBQbGVhc2UgY29udGFjdCBzdXBwb3J0QGJpdGdvLmNvbVwiXG4gICAgICApO1xuICAgICAgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ0ZhaWxzIGJpdGdvIGNoYWxsZW5nZSBwcm9vZnMgZm9yIGZhdWx0eSBuaXRybyBoMVdydEgyIHByb29mJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaSA9IG5vY2tHZXRCaXRnb0NoYWxsZW5nZXMoe1xuICAgICAgICBiaXRnb05pdHJvSHNtOiB7XG4gICAgICAgICAgLi4uYml0Z29OaXRyb0NoYWxsZW5nZSxcbiAgICAgICAgICBudGlsZGVQcm9vZjoge1xuICAgICAgICAgICAgLi4uYml0Z29OaXRyb0NoYWxsZW5nZS5udGlsZGVQcm9vZixcbiAgICAgICAgICAgIGgxV3J0SDI6IGJpdGdvTml0cm9DaGFsbGVuZ2UubnRpbGRlUHJvb2YuaDJXcnRIMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBiaXRnb0luc3RpdHV0aW9uYWxIc206IGJpdGdvSW5zdENoYWxsZW5nZSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgRUNEU0FVdGlscy5FY2RzYVV0aWxzLmdldFZlcmlmeUFuZFNpZ25CaXRHb0NoYWxsZW5nZXMoYml0Z28sICdlbnRfaWQnLCB1c2VyUGFzc3dvcmQpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgIFwiRmFpbGVkIHRvIHZlcmlmeSBCaXRHbydzIGNoYWxsZW5nZSBuZWVkZWQgdG8gZW5hYmxlIEVDRFNBIHNpZ25pbmcuIFBsZWFzZSBjb250YWN0IHN1cHBvcnRAYml0Z28uY29tXCJcbiAgICAgICk7XG4gICAgICBub2NrR2V0Qml0Z29DaGFsbGVuZ2VzQXBpLmlzRG9uZSgpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnRmFpbHMgYml0Z28gY2hhbGxlbmdlIHByb29mcyBmb3IgZmF1bHR5IGluc3QgaDJXcnRIMSBwcm9vZicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vY2tHZXRCaXRnb0NoYWxsZW5nZXNBcGkgPSBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KGAvYXBpL3YyL3Rzcy9lY2RzYS9jaGFsbGVuZ2VzYClcbiAgICAgICAgLnRpbWVzKDEpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBiaXRnb05pdHJvSHNtOiBiaXRnb05pdHJvQ2hhbGxlbmdlLFxuICAgICAgICAgIGJpdGdvSW5zdGl0dXRpb25hbEhzbToge1xuICAgICAgICAgICAgLi4uYml0Z29JbnN0Q2hhbGxlbmdlLFxuICAgICAgICAgICAgbnRpbGRlUHJvb2Y6IHtcbiAgICAgICAgICAgICAgLi4uYml0Z29JbnN0Q2hhbGxlbmdlLm50aWxkZVByb29mLFxuICAgICAgICAgICAgICBoMldydEgxOiBiaXRnb0luc3RDaGFsbGVuZ2UubnRpbGRlUHJvb2YuaDFXcnRIMixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICBhd2FpdCBFQ0RTQVV0aWxzLkVjZHNhVXRpbHMuZ2V0VmVyaWZ5QW5kU2lnbkJpdEdvQ2hhbGxlbmdlcyhiaXRnbywgJ2VudF9pZCcsIHVzZXJQYXNzd29yZCkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgXCJGYWlsZWQgdG8gdmVyaWZ5IEJpdEdvJ3MgY2hhbGxlbmdlIG5lZWRlZCB0byBlbmFibGUgRUNEU0Egc2lnbmluZy4gUGxlYXNlIGNvbnRhY3Qgc3VwcG9ydEBiaXRnby5jb21cIlxuICAgICAgKTtcbiAgICAgIG5vY2tHZXRCaXRnb0NoYWxsZW5nZXNBcGkuaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdGYWlscyBiaXRnbyBjaGFsbGVuZ2UgcHJvb2ZzIGZvciBmYXVsdHkgaW5zdCBoMVdydEgyIHByb29mJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaSA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjIvdHNzL2VjZHNhL2NoYWxsZW5nZXNgKVxuICAgICAgICAudGltZXMoMSlcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGJpdGdvTml0cm9Ic206IGJpdGdvTml0cm9DaGFsbGVuZ2UsXG4gICAgICAgICAgYml0Z29JbnN0aXR1dGlvbmFsSHNtOiB7XG4gICAgICAgICAgICAuLi5iaXRnb0luc3RDaGFsbGVuZ2UsXG4gICAgICAgICAgICBudGlsZGVQcm9vZjoge1xuICAgICAgICAgICAgICAuLi5iaXRnb0luc3RDaGFsbGVuZ2UubnRpbGRlUHJvb2YsXG4gICAgICAgICAgICAgIGgxV3J0SDI6IGJpdGdvSW5zdENoYWxsZW5nZS5udGlsZGVQcm9vZi5oMldydEgxLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIGF3YWl0IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5nZXRWZXJpZnlBbmRTaWduQml0R29DaGFsbGVuZ2VzKGJpdGdvLCAnZW50X2lkJywgdXNlclBhc3N3b3JkKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICBcIkZhaWxlZCB0byB2ZXJpZnkgQml0R28ncyBjaGFsbGVuZ2UgbmVlZGVkIHRvIGVuYWJsZSBFQ0RTQSBzaWduaW5nLiBQbGVhc2UgY29udGFjdCBzdXBwb3J0QGJpdGdvLmNvbVwiXG4gICAgICApO1xuICAgICAgbm9ja0dldEJpdGdvQ2hhbGxlbmdlc0FwaS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3JldHVybnMgb25seSBmdWxsIGZvciBob3Qgd2FsbGV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGhvdFdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB7IHR5cGU6ICdob3QnLCBtdWx0aXNpZ1R5cGU6ICd0c3MnIH0pO1xuICAgICAgY29uc3QgaG90V2FsbGV0VHNzVXRpbHMgPSBuZXcgRUNEU0FVdGlscy5FY2RzYVV0aWxzKGJpdGdvLCBiYXNlQ29pbiwgaG90V2FsbGV0KTtcbiAgICAgIGhvdFdhbGxldFRzc1V0aWxzLnN1cHBvcnRlZFR4UmVxdWVzdFZlcnNpb25zKCkuc2hvdWxkLmRlZXBFcXVhbChbJ2Z1bGwnXSk7XG4gICAgfSk7XG4gICAgaXQoJ3JldHVybnMgb25seSBmdWxsIGZvciBjb2xkIHdhbGxldHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2xkV2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZUNvaW4sIHtcbiAgICAgICAgdHlwZTogJ2NvbGQnLFxuICAgICAgICBtdWx0aXNpZ1R5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBjb2xkV2FsbGV0VHNzVXRpbHMgPSBuZXcgRUNEU0FVdGlscy5FY2RzYVV0aWxzKGJpdGdvLCBiYXNlQ29pbiwgY29sZFdhbGxldCk7XG5cbiAgICAgIGNvbGRXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpLnNob3VsZC5kZWVwRXF1YWwoWydmdWxsJ10pO1xuICAgIH0pO1xuICAgIGl0KCdyZXR1cm5zIG9ubHkgZnVsbCBmb3IgY3VzdG9kaWFsIHdhbGxldHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjdXN0b2RpYWxXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgeyB0eXBlOiAnY3VzdG9kaWFsJywgbXVsdGlzaWdUeXBlOiAndHNzJyB9KTtcbiAgICAgIGNvbnN0IGN1c3RvZGlhbFdhbGxldFRzc1V0aWxzID0gbmV3IEVDRFNBVXRpbHMuRWNkc2FVdGlscyhiaXRnbywgYmFzZUNvaW4sIGN1c3RvZGlhbFdhbGxldCk7XG4gICAgICBjdXN0b2RpYWxXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpLnNob3VsZC5kZWVwRXF1YWwoWydmdWxsJ10pO1xuICAgIH0pO1xuICAgIGl0KCdyZXR1cm5zIGVtcHR5IGZvciB0cmFkaW5nIHdhbGxldHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0cmFkaW5nV2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZUNvaW4sIHsgdHlwZTogJ3RyYWRpbmcnLCBtdWx0aXNpZ1R5cGU6ICd0c3MnIH0pO1xuICAgICAgY29uc3QgdHJhZGluZ1dhbGxldFRzc1V0aWxzID0gbmV3IEVDRFNBVXRpbHMuRWNkc2FVdGlscyhiaXRnbywgYmFzZUNvaW4sIHRyYWRpbmdXYWxsZXQpO1xuICAgICAgdHJhZGluZ1dhbGxldFRzc1V0aWxzLnN1cHBvcnRlZFR4UmVxdWVzdFZlcnNpb25zKCkuc2hvdWxkLmRlZXBFcXVhbChbXSk7XG4gICAgfSk7XG4gICAgaXQoJ3JldHVybnMgZW1wdHkgZm9yIG5vbi10c3Mgd2FsbGV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vblRzc1dhbGxldERhdGEgPSB7IGNvaW46ICd0YnRjJywgbXVsdGlzaWdUeXBlOiAnb25jaGFpbicgfTtcbiAgICAgIGNvbnN0IGJ0Y0NvaW4gPSBiaXRnby5jb2luKCd0YnRjJyk7XG4gICAgICBjb25zdCBub25Uc3NXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBidGNDb2luLCBub25Uc3NXYWxsZXREYXRhKTtcbiAgICAgIGNvbnN0IG5vblRzc1dhbGxldFRzc1V0aWxzID0gbmV3IFRzc1V0aWxzKGJpdGdvLCBidGNDb2luLCBub25Uc3NXYWxsZXQpO1xuICAgICAgbm9uVHNzV2FsbGV0VHNzVXRpbHMuc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMoKS5zaG91bGQuZGVlcEVxdWFsKFtdKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2luaXRpYXRlQ2hhbGxlbmdlc0ZvckVudGVycHJpc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgY29uc3QgYWRtaW5FY2RoS2V5ID0gYml0Z28ua2V5Y2hhaW5zKCkuY3JlYXRlKCk7XG4gICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSAnbS8wLzAnO1xuICAgIGNvbnN0IGJpdGdvSW5zdENoYWxsZW5nZSA9IG1vY2tDaGFsbGVuZ2VBO1xuICAgIGNvbnN0IGJpdGdvTml0cm9DaGFsbGVuZ2UgPSBtb2NrQ2hhbGxlbmdlQjtcbiAgICBjb25zdCBzZXJpYWxpemVkRW50Q2hhbGxlbmdlID0gbW9ja0NoYWxsZW5nZUM7XG4gICAgY29uc3QgdXNlclBhc3N3b3JkID0gJ3Bhc3N3b3JkMTIzJztcbiAgICBsZXQgZW5jcnlwdGVkWHBydjogc3RyaW5nO1xuXG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGVuY3J5cHRlZFhwcnYgPSBhd2FpdCBiaXRnby5lbmNyeXB0KHtcbiAgICAgICAgcGFzc3dvcmQ6IHVzZXJQYXNzd29yZCxcbiAgICAgICAgaW5wdXQ6IGFkbWluRWNkaEtleS54cHJ2LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNpbm9uLnN0dWIoYml0Z28sICdnZXRTaWduaW5nS2V5Rm9yVXNlcicpLnJlc29sdmVzKHtcbiAgICAgICAgdXNlcklkOiAnaWQnLFxuICAgICAgICB1c2VyRW1haWw6ICd1c2VyQGJpdGdvLmNvbScsXG4gICAgICAgIGRlcml2ZWRQdWJrZXk6IGJpcDMyLmZyb21CYXNlNTgoYWRtaW5FY2RoS2V5LnhwdWIpLmRlcml2ZVBhdGgoZGVyaXZhdGlvblBhdGgpLnB1YmxpY0tleS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIGRlcml2YXRpb25QYXRoOiBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgZWNkaEtleWNoYWluOiAnbXkga2V5Y2hhaW4nLFxuICAgICAgfSk7XG5cbiAgICAgIHNpbm9uLnN0dWIoYml0Z28sICdnZXRFQ0RIS2V5Y2hhaW4nKS5yZXNvbHZlcyh7XG4gICAgICAgIGVuY3J5cHRlZFhwcnY6IGVuY3J5cHRlZFhwcnYsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBzaW5vbi5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHVwbG9hZCBjaGFsbGVuZ2Ugd2l0aG91dCBnZW5lcmF0aW5nIGlmIHBhc3NlZCBpbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0dWJVcGxvYWRDaGFsbGVuZ2UgPSBzaW5vbi5zdHViKEVDRFNBVXRpbHMuRWNkc2FVdGlscywgJ3VwbG9hZENoYWxsZW5nZXNUb0VudGVycHJpc2UnKTtcbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZEVudENoYWxsZW5nZSA9IEVjZHNhVHlwZXMuZGVzZXJpYWxpemVOdGlsZGVXaXRoUHJvb2ZzKHNlcmlhbGl6ZWRFbnRDaGFsbGVuZ2UpO1xuXG4gICAgICBjb25zdCBzaWduZWRFbnRDaGFsbGVuZ2UgPSBFQ0RTQVV0aWxzLkVjZHNhVXRpbHMuc2lnbkNoYWxsZW5nZShcbiAgICAgICAgc2VyaWFsaXplZEVudENoYWxsZW5nZSxcbiAgICAgICAgYWRtaW5FY2RoS2V5LnhwcnYsXG4gICAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgICApO1xuICAgICAgY29uc3Qgc2lnbmVkSW5zdENoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICBiaXRnb0luc3RDaGFsbGVuZ2UsXG4gICAgICAgIGFkbWluRWNkaEtleS54cHJ2LFxuICAgICAgICBkZXJpdmF0aW9uUGF0aFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNpZ25lZE5pdHJvQ2hhbGxlbmdlID0gRUNEU0FVdGlscy5FY2RzYVV0aWxzLnNpZ25DaGFsbGVuZ2UoXG4gICAgICAgIGJpdGdvTml0cm9DaGFsbGVuZ2UsXG4gICAgICAgIGFkbWluRWNkaEtleS54cHJ2LFxuICAgICAgICBkZXJpdmF0aW9uUGF0aFxuICAgICAgKTtcblxuICAgICAgYXdhaXQgRUNEU0FVdGlscy5FY2RzYVV0aWxzLmluaXRpYXRlQ2hhbGxlbmdlc0ZvckVudGVycHJpc2UoXG4gICAgICAgIGJpdGdvLFxuICAgICAgICAnZW50X2lkJyxcbiAgICAgICAgdXNlclBhc3N3b3JkLFxuICAgICAgICBzaWduZWRJbnN0Q2hhbGxlbmdlLFxuICAgICAgICBzaWduZWROaXRyb0NoYWxsZW5nZSxcbiAgICAgICAgb3BlblNTTEJ5dGVzLFxuICAgICAgICBkZXNlcmlhbGl6ZWRFbnRDaGFsbGVuZ2VcbiAgICAgICkuc2hvdWxkLm5vdC5iZS5yZWplY3RlZCgpO1xuICAgICAgc3R1YlVwbG9hZENoYWxsZW5nZS5jYWxsZWRXaXRoKFxuICAgICAgICBiaXRnbyxcbiAgICAgICAgJ2VudF9pZCcsXG4gICAgICAgIHNlcmlhbGl6ZWRFbnRDaGFsbGVuZ2UsXG4gICAgICAgIHNpZ25lZEVudENoYWxsZW5nZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIHNpZ25lZEluc3RDaGFsbGVuZ2UudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBzaWduZWROaXRyb0NoYWxsZW5nZS50b1N0cmluZygnaGV4JylcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGEgY2hhbGxlbmdlIGFuZCBpZiBvbmUgaXMgbm90IHByb3ZpZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3R1YlVwbG9hZENoYWxsZW5nZSA9IHNpbm9uLnN0dWIoRUNEU0FVdGlscy5FY2RzYVV0aWxzLCAndXBsb2FkQ2hhbGxlbmdlc1RvRW50ZXJwcmlzZScpO1xuICAgICAgY29uc3QgZGVzZXJpYWxpemVkRW50Q2hhbGxlbmdlID0gRWNkc2FUeXBlcy5kZXNlcmlhbGl6ZU50aWxkZVdpdGhQcm9vZnMoc2VyaWFsaXplZEVudENoYWxsZW5nZSk7XG4gICAgICBzaW5vbi5zdHViKEVjZHNhUmFuZ2VQcm9vZiwgJ2dlbmVyYXRlTnRpbGRlJykucmVzb2x2ZXMoZGVzZXJpYWxpemVkRW50Q2hhbGxlbmdlKTtcblxuICAgICAgY29uc3Qgc2lnbmVkRW50Q2hhbGxlbmdlID0gRUNEU0FVdGlscy5FY2RzYVV0aWxzLnNpZ25DaGFsbGVuZ2UoXG4gICAgICAgIHNlcmlhbGl6ZWRFbnRDaGFsbGVuZ2UsXG4gICAgICAgIGFkbWluRWNkaEtleS54cHJ2LFxuICAgICAgICBkZXJpdmF0aW9uUGF0aFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNpZ25lZEluc3RDaGFsbGVuZ2UgPSBFQ0RTQVV0aWxzLkVjZHNhVXRpbHMuc2lnbkNoYWxsZW5nZShcbiAgICAgICAgYml0Z29JbnN0Q2hhbGxlbmdlLFxuICAgICAgICBhZG1pbkVjZGhLZXkueHBydixcbiAgICAgICAgZGVyaXZhdGlvblBhdGhcbiAgICAgICk7XG4gICAgICBjb25zdCBzaWduZWROaXRyb0NoYWxsZW5nZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5zaWduQ2hhbGxlbmdlKFxuICAgICAgICBiaXRnb05pdHJvQ2hhbGxlbmdlLFxuICAgICAgICBhZG1pbkVjZGhLZXkueHBydixcbiAgICAgICAgZGVyaXZhdGlvblBhdGhcbiAgICAgICk7XG5cbiAgICAgIGF3YWl0IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5pbml0aWF0ZUNoYWxsZW5nZXNGb3JFbnRlcnByaXNlKFxuICAgICAgICBiaXRnbyxcbiAgICAgICAgJ2VudF9pZCcsXG4gICAgICAgIHVzZXJQYXNzd29yZCxcbiAgICAgICAgc2lnbmVkSW5zdENoYWxsZW5nZSxcbiAgICAgICAgc2lnbmVkTml0cm9DaGFsbGVuZ2UsXG4gICAgICAgIG9wZW5TU0xCeXRlc1xuICAgICAgKS5zaG91bGQubm90LmJlLnJlamVjdGVkKCk7XG4gICAgICBzdHViVXBsb2FkQ2hhbGxlbmdlLmNhbGxlZFdpdGgoXG4gICAgICAgIGJpdGdvLFxuICAgICAgICAnZW50X2lkJyxcbiAgICAgICAgc2VyaWFsaXplZEVudENoYWxsZW5nZSxcbiAgICAgICAgc2lnbmVkRW50Q2hhbGxlbmdlLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgc2lnbmVkSW5zdENoYWxsZW5nZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIHNpZ25lZE5pdHJvQ2hhbGxlbmdlLnRvU3RyaW5nKCdoZXgnKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoJ2dldE1lc3NhZ2VUb1NpZ25Gcm9tQ2hhbGxlbmdlIGNvbmNhdGVuYXRlcyB0aGUgY2hhbGxlbmdlIHZhbHVlcyBvbmx5JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNoYWxsZW5nZSA9IG1vY2tDaGFsbGVuZ2VBO1xuICAgIGNvbnN0IGV4cGVjdGVkTWVzc2FnZVRvU2lnbiA9IGNoYWxsZW5nZS5udGlsZGUuY29uY2F0KGNoYWxsZW5nZS5oMSkuY29uY2F0KGNoYWxsZW5nZS5oMik7XG4gICAgY29uc3QgbWVzc2FnZSA9IEVDRFNBVXRpbHMuRWNkc2FVdGlscy5nZXRNZXNzYWdlVG9TaWduRnJvbUNoYWxsZW5nZShjaGFsbGVuZ2UpO1xuICAgIG1lc3NhZ2Uuc2hvdWxkLmVxdWFsKGV4cGVjdGVkTWVzc2FnZVRvU2lnbik7XG4gIH0pO1xuICBkZXNjcmliZSgndmFsaWRhdGVDb21tb25LZXljaGFpblB1YmxpY0tleScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgndmFsaWRhdGVDb21tb25LZXljaGFpblB1YmxpY0tleSByZXR1cm5zIGNvcnJlY3QgcHVibGljIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbW1vbktleWNoYWluID1cbiAgICAgICAgJzAzZjQwYzcwNTQ1YjUxOWJiN2JiYzcxOTVmZDRiN2Q1YmJmYzg3M2JmZDM4YjE4NTk2ZTRiNDdhMDViNmE4OGQ1NTJlMmU4MzE5Y2IzMWUyNzliOTlkYmU1NDExNWE5ODNkMzVlODY2NzlhZjk2ZDgxYjc0NzhkMWRmMzY4Zjc2YTgnO1xuICAgICAgY29uc3QgZXhwZWN0ZWRQdWJLZXlSZXN1bHQgPSBgZjQwYzcwNTQ1YjUxOWJiN2JiYzcxOTVmZDRiN2Q1YmJmYzg3M2JmZDM4YjE4NTk2ZTRiNDdhMDViNmE4OGQ1NTZhMTBkNmFiODA1NWRjMGIzYTlhZjlkYzRlNDJmNGY5NzczYzU5MGFmY2MyOThkMDE3YzFiMWNlMjlhODgwNDFgO1xuICAgICAgY29uc3QgYWN0dWFsUHViS2V5ID0gRUNEU0FVdGlscy5FY2RzYVV0aWxzLnZhbGlkYXRlQ29tbW9uS2V5Y2hhaW5QdWJsaWNLZXkoY29tbW9uS2V5Y2hhaW4pO1xuICAgICAgYWN0dWFsUHViS2V5LnNob3VsZC5lcXVhbChleHBlY3RlZFB1YktleVJlc3VsdCk7XG4gICAgfSk7XG4gICAgaXQoJ3ZhbGlkYXRlQ29tbW9uS2V5Y2hhaW5QdWJsaWNLZXkgdGhyb3dzIGNvcnJlY3RseSB3aXRoIGludmFsaWQgbGVuZ3RoJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPSAnMDNmNDBjNzA1NDgnO1xuICAgICAgc2hvdWxkKCgpID0+IEVDRFNBVXRpbHMuRWNkc2FVdGlscy52YWxpZGF0ZUNvbW1vbktleWNoYWluUHVibGljS2V5KGNvbW1vbktleWNoYWluKSkudGhyb3dFcnJvcihcbiAgICAgICAgJ0ludmFsaWQgY29tbW9uS2V5Y2hhaW4gbGVuZ3RoLCBleHBlY3RlZCAxMzAsIGdvdCAxMSdcbiAgICAgICk7XG4gICAgfSk7XG4gICAgaXQoJ3ZhbGlkYXRlQ29tbW9uS2V5Y2hhaW5QdWJsaWNLZXkgdGhyb3dzIGNvcnJlY3RseSB3aXRoIGludmFsaWQgY29tbW9uS2V5Y2hhaW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb21tb25LZXljaGFpbldpdGhJbnZhbGlkQ2hhcmFjdGVycyA9XG4gICAgICAgICchQCMkXjBjNzA1NDViNTE5YmI3YmJjNzE5NWZkNGI3ZDViZmM4NzNiZmQzOGIxODU5NmU0YjQ3YTA1YjZhODhkNTUyZTJlODMxOWNiMzFlMjc5Yjk5ZGJlNTQxMTVhOTgzZDM1ZTg2Njc5YWY5NmQ4MWI3NDc4ZDFkZjM2OGY3NmE4JzsgLy8gMTI5IGNoYXJzXG4gICAgICBzaG91bGQoKCkgPT5cbiAgICAgICAgRUNEU0FVdGlscy5FY2RzYVV0aWxzLnZhbGlkYXRlQ29tbW9uS2V5Y2hhaW5QdWJsaWNLZXkoY29tbW9uS2V5Y2hhaW5XaXRoSW52YWxpZENoYXJhY3RlcnMpXG4gICAgICApLnRocm93RXJyb3IoL15JbnZhbGlkIGNvbW1vbktleWNoYWluLCBlcnJvcjovKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gI3JlZ2lvbiBOb2NrIGhlbHBlcnNcbiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlSW5jb21wbGV0ZUJpdGdvSGVsZEJhY2t1cEtleVNoYXJlKFxuICAgIHVzZXJHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPixcbiAgICBiYWNrdXBLZXlTaGFyZTogS2V5U2hhcmUsXG4gICAgYml0Z29HcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPlxuICApOiBQcm9taXNlPEJpdGdvSGVsZEJhY2t1cEtleVNoYXJlPiB7XG4gICAgY29uc3QgblNoYXJlUHJvbWlzZXMgPSBbXG4gICAgICBlbmNyeXB0TlNoYXJlKGJhY2t1cEtleVNoYXJlLCAxLCB1c2VyR3BnS2V5LnB1YmxpY0tleSwgdXNlckdwZ0tleSwgZmFsc2UpLFxuICAgICAgZW5jcnlwdE5TaGFyZShiYWNrdXBLZXlTaGFyZSwgMywgYml0Z29HcGdLZXkucHVibGljS2V5LCB1c2VyR3BnS2V5LCBmYWxzZSksXG4gICAgXTtcblxuICAgIGNvbnN0IGJhY2t1cFRvVXNlclB1YmxpY1NoYXJlID0gQnVmZmVyLmNvbmNhdChbXG4gICAgICBCdWZmZXIuZnJvbShiYWNrdXBLZXlTaGFyZS5uU2hhcmVzWzFdLnksICdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbMV0uY2hhaW5jb2RlLCAnaGV4JyksXG4gICAgXSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgY29uc3QgYmFja3VwVG9CaXRnb1B1YmxpY1NoYXJlID0gQnVmZmVyLmNvbmNhdChbXG4gICAgICBCdWZmZXIuZnJvbShiYWNrdXBLZXlTaGFyZS5uU2hhcmVzWzNdLnksICdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKGJhY2t1cEtleVNoYXJlLm5TaGFyZXNbM10uY2hhaW5jb2RlLCAnaGV4JyksXG4gICAgXSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiAnNDcxMScsXG4gICAgICBrZXlTaGFyZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGZyb206ICdiYWNrdXAnLFxuICAgICAgICAgIHRvOiAndXNlcicsXG4gICAgICAgICAgcHVibGljU2hhcmU6IGJhY2t1cFRvVXNlclB1YmxpY1NoYXJlLFxuICAgICAgICAgIHByaXZhdGVTaGFyZTogKGF3YWl0IG5TaGFyZVByb21pc2VzWzBdKS5lbmNyeXB0ZWRQcml2YXRlU2hhcmUsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBmcm9tOiAnYmFja3VwJyxcbiAgICAgICAgICB0bzogJ2JpdGdvJyxcbiAgICAgICAgICBwdWJsaWNTaGFyZTogYmFja3VwVG9CaXRnb1B1YmxpY1NoYXJlLFxuICAgICAgICAgIHByaXZhdGVTaGFyZTogKGF3YWl0IG5TaGFyZVByb21pc2VzWzFdKS5lbmNyeXB0ZWRQcml2YXRlU2hhcmUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrR2V0Qml0Z29QdWJsaWNLZXlCYXNlZE9uRmVhdHVyZUZsYWdzKFxuICAgIGNvaW46IHN0cmluZyxcbiAgICBlbnRlcnByaXNlSWQ6IHN0cmluZyxcbiAgICBiaXRnb0dwZ0tleVBhaXI6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPlxuICApOiBQcm9taXNlPEJpdGdvR1BHUHVibGljS2V5PiB7XG4gICAgY29uc3QgYml0Z29HUEdQdWJsaWNLZXlSZXNwb25zZTogQml0Z29HUEdQdWJsaWNLZXkgPSB7XG4gICAgICBuYW1lOiAnaXJyZWxldmFudCcsXG4gICAgICBwdWJsaWNLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBtcGN2MlB1YmxpY0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGVudGVycHJpc2VJZCxcbiAgICB9O1xuICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi8ke2NvaW59L3Rzcy9wdWJrZXlgKS5xdWVyeSh7IGVudGVycHJpc2VJZCB9KS5yZXBseSgyMDAsIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2UpO1xuXG4gICAgcmV0dXJuIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2U7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrQ3JlYXRlQml0Z29IZWxkQmFja3VwS2V5U2hhcmUoXG4gICAgY29pbjogc3RyaW5nLFxuICAgIGVudGVycHJpc2VJZDogc3RyaW5nLFxuICAgIHVzZXJHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPixcbiAgICBiYWNrdXBLZXlTaGFyZTogS2V5U2hhcmUsXG4gICAgYml0Z29HcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPlxuICApOiBQcm9taXNlPEJpdGdvSGVsZEJhY2t1cEtleVNoYXJlPiB7XG4gICAgY29uc3Qga2V5U2hhcmUgPSBhd2FpdCBjcmVhdGVJbmNvbXBsZXRlQml0Z29IZWxkQmFja3VwS2V5U2hhcmUodXNlckdwZ0tleSwgYmFja3VwS2V5U2hhcmUsIGJpdGdvR3BnS2V5KTtcblxuICAgIG5vY2soYmdVcmwpXG4gICAgICAucG9zdChcbiAgICAgICAgYC9hcGkvdjIvJHtjb2lufS9rcnMvYmFja3Vwa2V5c2AsXG4gICAgICAgIF8ubWF0Y2hlcyh7IGVudGVycHJpc2U6IGVudGVycHJpc2VJZCwgdXNlckdQR1B1YmxpY0tleTogdXNlckdwZ0tleS5wdWJsaWNLZXkgfSlcbiAgICAgIClcbiAgICAgIC5yZXBseSgyMDEsIGtleVNoYXJlKTtcblxuICAgIHJldHVybiBrZXlTaGFyZTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIG5vY2tGaW5hbGl6ZUJpdGdvSGVsZEJhY2t1cEtleVNoYXJlKFxuICAgIGNvaW46IHN0cmluZyxcbiAgICBvcmlnaW5hbEtleVNoYXJlOiBCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZSxcbiAgICBjb21tb25LZXljaGFpbjogc3RyaW5nLFxuICAgIHVzZXJLZXlTaGFyZTogS2V5U2hhcmUsXG4gICAgdXNlckxvY2FsQmFja3VwR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz4sXG4gICAgYml0Z29LZXljaGFpbjogS2V5Y2hhaW5cbiAgKTogUHJvbWlzZTxCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZT4ge1xuICAgIGNvbnN0IGVuY3J5cHRlZFVzZXJUb0JhY2t1cEtleVNoYXJlID0gYXdhaXQgZW5jcnlwdE5TaGFyZShcbiAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgIDIsXG4gICAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXkucHVibGljS2V5LFxuICAgICAgdXNlckdwZ0tleSxcbiAgICAgIGZhbHNlXG4gICAgKTtcblxuICAgIGFzc2VydC5vayhiaXRnb0tleWNoYWluLmtleVNoYXJlcyk7XG4gICAgY29uc3QgYml0Z29Ub0JhY2t1cEtleVNoYXJlID0gYml0Z29LZXljaGFpbi5rZXlTaGFyZXMuZmluZChcbiAgICAgIChrZXlTaGFyZSkgPT4ga2V5U2hhcmUuZnJvbSA9PT0gJ2JpdGdvJyAmJiBrZXlTaGFyZS50byA9PT0gJ2JhY2t1cCdcbiAgICApO1xuICAgIGFzc2VydC5vayhiaXRnb1RvQmFja3VwS2V5U2hhcmUpO1xuXG4gICAgY29uc3QgdXNlclB1YmxpY1NoYXJlID0gQnVmZmVyLmNvbmNhdChbXG4gICAgICBCdWZmZXIuZnJvbSh1c2VyS2V5U2hhcmUublNoYXJlc1syXS55LCAnaGV4JyksXG4gICAgICBCdWZmZXIuZnJvbSh1c2VyS2V5U2hhcmUublNoYXJlc1syXS5jaGFpbmNvZGUsICdoZXgnKSxcbiAgICBdKS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICBjb25zdCBleHBlY3RlZEtleVNoYXJlcyA9IFtcbiAgICAgIHtcbiAgICAgICAgZnJvbTogJ3VzZXInLFxuICAgICAgICB0bzogJ2JhY2t1cCcsXG4gICAgICAgIHB1YmxpY1NoYXJlOiB1c2VyUHVibGljU2hhcmUsXG4gICAgICAgIC8vIE9taXR0aW5nIHRoZSBwcml2YXRlIHNoYXJlLCB0aGUgYWN0dWFsIGVuY3J5cHRpb24gaGFwcGVucyBpbnNpZGUgdGhlIGZ1bmN0aW9uIHdoZXJlIHdlIG1ha2UgdGhlIG1hdGNoaW5nIGNhbGxcbiAgICAgICAgLy8gdG8gdGhpcyBub2NrLiBXZSBjYW5ub3QgcmVjcmVhdGUgdGhlIHNhbWUgZW5jcnlwdGVkIHZhbHVlIGhlcmUgYmVjYXVzZSBncGcgZW5jcnlwdGlvbiBpcyBub3QgZGV0ZXJtaW5pc3RpY1xuICAgICAgfSxcbiAgICAgIGJpdGdvVG9CYWNrdXBLZXlTaGFyZSxcbiAgICBdO1xuXG4gICAgY29uc3QgdXBkYXRlZEtleVNoYXJlOiBCaXRnb0hlbGRCYWNrdXBLZXlTaGFyZSA9IHtcbiAgICAgIGlkOiBvcmlnaW5hbEtleVNoYXJlLmlkLFxuICAgICAgY29tbW9uS2V5Y2hhaW4sXG4gICAgICBrZXlTaGFyZXM6IFtcbiAgICAgICAgLi4ub3JpZ2luYWxLZXlTaGFyZS5rZXlTaGFyZXMsXG4gICAgICAgIHtcbiAgICAgICAgICBmcm9tOiAndXNlcicsXG4gICAgICAgICAgdG86ICdiYWNrdXAnLFxuICAgICAgICAgIHB1YmxpY1NoYXJlOiB1c2VyUHVibGljU2hhcmUsXG4gICAgICAgICAgcHJpdmF0ZVNoYXJlOiBlbmNyeXB0ZWRVc2VyVG9CYWNrdXBLZXlTaGFyZS5lbmNyeXB0ZWRQcml2YXRlU2hhcmUsXG4gICAgICAgIH0sXG4gICAgICAgIGJpdGdvVG9CYWNrdXBLZXlTaGFyZSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIG5vY2soYmdVcmwpXG4gICAgICAucHV0KFxuICAgICAgICBgL2FwaS92Mi8ke2NvaW59L2tycy9iYWNrdXBrZXlzLyR7b3JpZ2luYWxLZXlTaGFyZS5pZH1gLFxuICAgICAgICBfLm1hdGNoZXMoeyBjb21tb25LZXljaGFpbiwga2V5U2hhcmVzOiBleHBlY3RlZEtleVNoYXJlcyB9KVxuICAgICAgKVxuICAgICAgLnJlcGx5KDIwMCwgdXBkYXRlZEtleVNoYXJlKTtcblxuICAgIHJldHVybiB1cGRhdGVkS2V5U2hhcmU7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGEgYml0Z28ga2V5Y2hhaW4gZ2l2ZW4gdGhlIGZ1bGwgc2V0IG9mIGtleXNoYXJlcyBhbmQgR1BHIGtleXMuXG4gICAqIEFsc28gbW9ja3MgdGhlIHdhbGxldCBzaWduYXR1cmVzIGFkZGVkIGJ5IHRoZSBIU00uXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlQml0Z29LZXljaGFpbihwYXJhbXM6IHtcbiAgICBjb2luOiBzdHJpbmc7XG4gICAgdXNlcktleVNoYXJlOiBLZXlTaGFyZTtcbiAgICBiYWNrdXBLZXlTaGFyZTogS2V5U2hhcmU7XG4gICAgYml0Z29LZXlTaGFyZTogS2V5U2hhcmU7XG4gICAgdXNlckdwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICAgIHVzZXJMb2NhbEJhY2t1cEdwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICAgIGJpdGdvR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gIH0pOiBQcm9taXNlPEtleWNoYWluPiB7XG4gICAgY29uc3QgYml0Z29Db21iaW5lZCA9IE1QQy5rZXlDb21iaW5lKHBhcmFtcy5iaXRnb0tleVNoYXJlLnBTaGFyZSwgW1xuICAgICAgcGFyYW1zLnVzZXJLZXlTaGFyZS5uU2hhcmVzWzNdLFxuICAgICAgcGFyYW1zLmJhY2t1cEtleVNoYXJlLm5TaGFyZXNbM10sXG4gICAgXSk7XG4gICAgY29uc3QgdXNlckdwZ0tleUFjdHVhbCA9IGF3YWl0IG9wZW5wZ3AucmVhZEtleSh7IGFybW9yZWRLZXk6IHBhcmFtcy51c2VyR3BnS2V5LnB1YmxpY0tleSB9KTtcbiAgICBjb25zdCBiYWNrdXBHcGdLZXlBY3R1YWwgPSBhd2FpdCBvcGVucGdwLnJlYWRLZXkoeyBhcm1vcmVkS2V5OiBwYXJhbXMudXNlckxvY2FsQmFja3VwR3BnS2V5LnB1YmxpY0tleSB9KTtcblxuICAgIGNvbnN0IG5TaGFyZVByb21pc2VzID0gW1xuICAgICAgZW5jcnlwdE5TaGFyZShwYXJhbXMuYml0Z29LZXlTaGFyZSwgMSwgcGFyYW1zLnVzZXJHcGdLZXkucHVibGljS2V5LCBwYXJhbXMudXNlckdwZ0tleSwgZmFsc2UpLFxuICAgICAgZW5jcnlwdE5TaGFyZShcbiAgICAgICAgcGFyYW1zLmJpdGdvS2V5U2hhcmUsXG4gICAgICAgIDIsXG4gICAgICAgIHBhcmFtcy51c2VyTG9jYWxCYWNrdXBHcGdLZXkucHVibGljS2V5LFxuICAgICAgICBwYXJhbXMudXNlckxvY2FsQmFja3VwR3BnS2V5LFxuICAgICAgICBmYWxzZVxuICAgICAgKSxcbiAgICBdO1xuICAgIGNvbnN0IFt1c2VyVG9CaXRnb1NoYXJlLCBiYWNrdXBUb0JpdGdvU2hhcmVdID0gYXdhaXQgUHJvbWlzZS5hbGwoblNoYXJlUHJvbWlzZXMpO1xuICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW46IEtleWNoYWluID0ge1xuICAgICAgaWQ6ICczJyxcbiAgICAgIHB1YjogJycsXG4gICAgICBjb21tb25LZXljaGFpbjogYml0Z29Db21iaW5lZC54U2hhcmUueSArIGJpdGdvQ29tYmluZWQueFNoYXJlLmNoYWluY29kZSxcbiAgICAgIGtleVNoYXJlczogW1xuICAgICAgICB7XG4gICAgICAgICAgZnJvbTogJ2JpdGdvJyxcbiAgICAgICAgICB0bzogJ3VzZXInLFxuICAgICAgICAgIHB1YmxpY1NoYXJlOiB1c2VyVG9CaXRnb1NoYXJlLnB1YmxpY1NoYXJlLFxuICAgICAgICAgIHByaXZhdGVTaGFyZTogdXNlclRvQml0Z29TaGFyZS5lbmNyeXB0ZWRQcml2YXRlU2hhcmUsXG4gICAgICAgICAgbjogdXNlclRvQml0Z29TaGFyZS5uLFxuICAgICAgICAgIHZzc1Byb29mOiB1c2VyVG9CaXRnb1NoYXJlLnZzc1Byb29mLFxuICAgICAgICAgIHByaXZhdGVTaGFyZVByb29mOiB1c2VyVG9CaXRnb1NoYXJlLnByaXZhdGVTaGFyZVByb29mLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgZnJvbTogJ2JpdGdvJyxcbiAgICAgICAgICB0bzogJ2JhY2t1cCcsXG4gICAgICAgICAgcHVibGljU2hhcmU6IGJhY2t1cFRvQml0Z29TaGFyZS5wdWJsaWNTaGFyZSxcbiAgICAgICAgICBwcml2YXRlU2hhcmU6IGJhY2t1cFRvQml0Z29TaGFyZS5lbmNyeXB0ZWRQcml2YXRlU2hhcmUsXG4gICAgICAgICAgbjogYmFja3VwVG9CaXRnb1NoYXJlLm4sXG4gICAgICAgICAgdnNzUHJvb2Y6IGJhY2t1cFRvQml0Z29TaGFyZS52c3NQcm9vZixcbiAgICAgICAgICBwcml2YXRlU2hhcmVQcm9vZjogYmFja3VwVG9CaXRnb1NoYXJlLnByaXZhdGVTaGFyZVByb29mLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHR5cGU6ICd0c3MnLFxuICAgIH07XG5cbiAgICBjb25zdCB1c2VyS2V5SWQgPSB1c2VyR3BnS2V5QWN0dWFsLmtleVBhY2tldC5nZXRGaW5nZXJwcmludCgpO1xuICAgIGNvbnN0IGJhY2t1cEtleUlkID0gYmFja3VwR3BnS2V5QWN0dWFsLmtleVBhY2tldC5nZXRGaW5nZXJwcmludCgpO1xuICAgIGNvbnN0IGJpdGdvVG9Vc2VyUHVibGljVSA9XG4gICAgICBCdWZmZXIuZnJvbShcbiAgICAgICAgZWNjLnBvaW50RnJvbVNjYWxhcihCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS5uU2hhcmVzWzFdLnUsICdoZXgnKSwgdHJ1ZSkgYXMgVWludDhBcnJheVxuICAgICAgKS50b1N0cmluZygnaGV4JykgKyBwYXJhbXMuYml0Z29LZXlTaGFyZS5uU2hhcmVzWzFdLmNoYWluY29kZTtcbiAgICBjb25zdCBiaXRnb1RvQmFja3VwUHVibGljVSA9XG4gICAgICBCdWZmZXIuZnJvbShcbiAgICAgICAgZWNjLnBvaW50RnJvbVNjYWxhcihCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS5uU2hhcmVzWzJdLnUsICdoZXgnKSwgdHJ1ZSkgYXMgVWludDhBcnJheVxuICAgICAgKS50b1N0cmluZygnaGV4JykgKyBwYXJhbXMuYml0Z29LZXlTaGFyZS5uU2hhcmVzWzJdLmNoYWluY29kZTtcblxuICAgIGJpdGdvS2V5Y2hhaW4ud2FsbGV0SFNNR1BHUHVibGljS2V5U2lncyA9IGF3YWl0IGNyZWF0ZVdhbGxldFNpZ25hdHVyZXMoXG4gICAgICBwYXJhbXMuYml0Z29HcGdLZXkucHJpdmF0ZUtleSxcbiAgICAgIHBhcmFtcy51c2VyR3BnS2V5LnB1YmxpY0tleSxcbiAgICAgIHBhcmFtcy51c2VyTG9jYWxCYWNrdXBHcGdLZXkucHVibGljS2V5LFxuICAgICAgW1xuICAgICAgICB7IG5hbWU6ICdjb21tb25LZXljaGFpbicsIHZhbHVlOiBiaXRnb0NvbWJpbmVkLnhTaGFyZS55ICsgYml0Z29Db21iaW5lZC54U2hhcmUuY2hhaW5jb2RlIH0sXG4gICAgICAgIHsgbmFtZTogJ3VzZXJLZXlJZCcsIHZhbHVlOiB1c2VyS2V5SWQgfSxcbiAgICAgICAgeyBuYW1lOiAnYmFja3VwS2V5SWQnLCB2YWx1ZTogYmFja3VwS2V5SWQgfSxcbiAgICAgICAgeyBuYW1lOiAnYml0Z29Ub1VzZXJQdWJsaWNTaGFyZScsIHZhbHVlOiBiaXRnb1RvVXNlclB1YmxpY1UgfSxcbiAgICAgICAgeyBuYW1lOiAnYml0Z29Ub0JhY2t1cFB1YmxpY1NoYXJlJywgdmFsdWU6IGJpdGdvVG9CYWNrdXBQdWJsaWNVIH0sXG4gICAgICBdXG4gICAgKTtcblxuICAgIHJldHVybiBiaXRnb0tleWNoYWluO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gbm9ja0JpdGdvS2V5Y2hhaW4ocGFyYW1zOiB7XG4gICAgY29pbjogc3RyaW5nO1xuICAgIHVzZXJLZXlTaGFyZTogS2V5U2hhcmU7XG4gICAgYmFja3VwS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIGJpdGdvS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIHVzZXJHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgICB1c2VyTG9jYWxCYWNrdXBHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgICBiaXRnb0dwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICB9KTogUHJvbWlzZTxLZXljaGFpbj4ge1xuICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCBnZW5lcmF0ZUJpdGdvS2V5Y2hhaW4ocGFyYW1zKTtcblxuICAgIG5vY2soYmdVcmwpXG4gICAgICAucGVyc2lzdCgpXG4gICAgICAucG9zdChgL2FwaS92Mi8ke3BhcmFtcy5jb2lufS9rZXlgLCBfLm1hdGNoZXMoeyBrZXlUeXBlOiAndHNzJywgc291cmNlOiAnYml0Z28nIH0pKVxuICAgICAgLnJlcGx5KDIwMCwgYml0Z29LZXljaGFpbik7XG5cbiAgICByZXR1cm4gYml0Z29LZXljaGFpbjtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIG5vY2tLZXljaGFpbihwYXJhbXM6IHtcbiAgICBjb2luOiBzdHJpbmc7XG4gICAga2V5Q2hhaW46IEtleWNoYWluO1xuICAgIHNvdXJjZTogJ3VzZXInIHwgJ2JhY2t1cCc7XG4gIH0pOiBQcm9taXNlPEtleWNoYWluPiB7XG4gICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgIC5wZXJzaXN0KClcbiAgICAgIC5wb3N0KGAvYXBpL3YyLyR7cGFyYW1zLmNvaW59L2tleWAsIF8ubWF0Y2hlcyh7IGtleVR5cGU6ICd0c3MnLCBzb3VyY2U6IHBhcmFtcy5zb3VyY2UgfSkpXG4gICAgICAucmVwbHkoMjAwLCBwYXJhbXMua2V5Q2hhaW4pO1xuXG4gICAgcmV0dXJuIHBhcmFtcy5rZXlDaGFpbjtcbiAgfVxuICAvLyAjZW5kcmVnaW9uIE5vY2sgaGVscGVyc1xufSk7XG4iXX0=