bitgo
Version:
BitGo JavaScript SDK
216 lines • 39.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_test_1 = require("@bitgo/sdk-test");
const src_1 = require("../../../../../src");
const openpgp = require("openpgp");
const nock = require("nock");
const assert = require("assert");
class TestEcdsaMpcv2Utils extends sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils {
async testPickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId) {
return this.pickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId);
}
}
class TestEddsaMpcv1Utils extends sdk_core_1.EddsaUtils {
async testPickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId, isEddsaMpcv2) {
return this.pickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId, isEddsaMpcv2);
}
}
class TestEddsaMpcv2Utils extends sdk_core_1.EDDSAUtils.EddsaMPCv2Utils {
async testPickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId, isEddsaMpcv2) {
return this.pickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId, isEddsaMpcv2);
}
}
describe('TSS MPC Pick BitGo GPG Pub Key Utils:', function () {
const walletId = '5b34252f1bf349930e34020a00000000';
const enterpriseId = '6449153a6f6bc20006d66771cdbe15d3';
const ecdsaCoinName = 'hteth';
const eddsaCoinName = 'tsol';
const ecdsaWalletData = {
id: walletId,
enterprise: enterpriseId,
coin: ecdsaCoinName,
coinSpecific: {},
multisigType: 'tss',
keys: ['key1', 'key2', 'key3'],
};
const eddsaWalletData = {
id: walletId,
enterprise: enterpriseId,
coin: eddsaCoinName,
coinSpecific: {},
multisigType: 'tss',
keys: ['key1', 'key2', 'key3'],
};
const envs = ['test', 'staging', 'prod'];
const ecdsaMpcv2Utils = [];
const eddsaMpcv1Utils = [];
const eddsaMpcv2Utils = [];
before(async function () {
nock.cleanAll();
for (const env of envs) {
const bitgoInstance = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env });
bitgoInstance.initializeTestVars();
let coinInstance = bitgoInstance.coin(ecdsaCoinName);
ecdsaMpcv2Utils.push(new TestEcdsaMpcv2Utils(bitgoInstance, coinInstance, new sdk_core_1.Wallet(bitgoInstance, coinInstance, ecdsaWalletData)));
coinInstance = bitgoInstance.coin(eddsaCoinName);
eddsaMpcv1Utils.push(new TestEddsaMpcv1Utils(bitgoInstance, coinInstance, new sdk_core_1.Wallet(bitgoInstance, coinInstance, eddsaWalletData)));
eddsaMpcv2Utils.push(new TestEddsaMpcv2Utils(bitgoInstance, coinInstance, new sdk_core_1.Wallet(bitgoInstance, coinInstance, eddsaWalletData)));
}
});
beforeEach(async function () {
for (const env of envs) {
const bgUrl = sdk_core_1.common.Environments[env].uri;
nock(bgUrl).get(`/api/v2/${ecdsaCoinName}/key/key3`).times(envs.length).reply(200, { hsmType: 'onprem' });
nock(bgUrl).get(`/api/v2/${eddsaCoinName}/key/key3`).times(envs.length).reply(200, { hsmType: 'nitro' });
}
});
envs.forEach(async function (env, index) {
it(`should pick correct Mpcv2 BitGo GPG Pub Key for ${env} env`, async function () {
const bitgoGpgPubKey = await ecdsaMpcv2Utils[index].testPickBitgoPubGpgKeyForSigning(true);
bitgoGpgPubKey
.armor()
.should.equal(sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv2']['onprem'][env === 'staging' ? 'test' : env]);
});
});
envs.forEach(async function (env, index) {
it(`should pick correct Mpcv1 BitGo GPG Pub Key for ${env} env`, async function () {
const bitgoGpgPubKey = await eddsaMpcv1Utils[index].testPickBitgoPubGpgKeyForSigning(false);
bitgoGpgPubKey
.armor()
.should.equal(sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv1']['nitro'][env === 'staging' ? 'test' : env]);
});
});
it(`should pick BitGo GPG Pub Key based on enterprise flag for mock env`, async function () {
const bgUrl = sdk_core_1.common.Environments['mock'].uri;
const testBitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const testCoin = testBitgo.coin(ecdsaCoinName);
const bitgoGPGKey = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: 'bitgo@test.com',
},
],
});
nock(bgUrl)
.get(`/api/v2/${ecdsaCoinName}/tss/pubkey`)
.query({ enterpriseId })
.reply(200, { mpcv2PublicKey: bitgoGPGKey.publicKey });
const ecdsaMpcv2Util = new TestEcdsaMpcv2Utils(testBitgo, testCoin, new sdk_core_1.Wallet(testBitgo, testCoin, ecdsaWalletData));
const bitgoGpgPubKey = await ecdsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true, undefined, enterpriseId);
bitgoGpgPubKey.armor().should.equal(bitgoGPGKey.publicKey);
});
it(`should pick BitGo GPG Pub Key based on constants api for mock env if enterprise flag based fetch fails`, async function () {
nock.cleanAll();
const bgUrl = sdk_core_1.common.Environments['mock'].uri;
const testBitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const testCoin = testBitgo.coin(ecdsaCoinName);
const bitgoGPGKey = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: 'bitgo@test.com',
},
],
});
const constants = {
mpc: {
bitgoMPCv2PublicKey: bitgoGPGKey.publicKey,
bitgoPublicKey: bitgoGPGKey.publicKey,
},
};
nock(bgUrl).get('/api/v1/client/constants').times(2).reply(200, { ttl: 3600, constants });
const ecdsaMpcv2Util = new TestEcdsaMpcv2Utils(testBitgo, testCoin, new sdk_core_1.Wallet(testBitgo, testCoin, ecdsaWalletData));
const bitgoGpgPubKey = await ecdsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true, undefined, enterpriseId);
bitgoGpgPubKey.armor().should.equal(bitgoGPGKey.publicKey);
});
it(`should throw an error if config is not available in one of test, staging, or prod`, async function () {
nock.cleanAll();
const testBitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'test' });
const testCoin = testBitgo.coin(ecdsaCoinName);
const ecdsaMpcv2Util = new TestEcdsaMpcv2Utils(testBitgo, testCoin, new sdk_core_1.Wallet(testBitgo, testCoin, ecdsaWalletData));
await assert.rejects(async () => await ecdsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true));
});
it('should select the correct GPG key for verifyWalletSignatures with hardcoded options', async function () {
// Test environment setup
const env = 'test';
const bitgoInstance = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env });
bitgoInstance.initializeTestVars();
const coinInstance = bitgoInstance.coin(eddsaCoinName);
const eddsaMpcv1Util = new TestEddsaMpcv1Utils(bitgoInstance, coinInstance, new sdk_core_1.Wallet(bitgoInstance, coinInstance, eddsaWalletData));
// Get the key that would be selected when using hardcoded BitGo keys
// mpcv1 and nitro are passed as options
const gpgKey = await eddsaMpcv1Util.testPickBitgoPubGpgKeyForSigning(false, undefined, undefined);
// Mock implementation of verifyWalletSignatures to capture the bitgoGpgKey that gets used
let capturedKey;
eddsaMpcv1Util.verifyWalletSignatures = async function (userGpgPub, backupGpgPub, bitgoKeychain, decryptedShare, verifierIndex, useHardcodedBitGoKeys) {
// Save the key that would be used when specifying hardcoded options
if (useHardcodedBitGoKeys) {
const hardcodedKey = await openpgp.readKey({
armoredKey: sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv1']['nitro']['test'],
});
capturedKey = hardcodedKey.armor();
}
// Not actually verifying in this test
return;
};
// Call with hardcoded key options
await eddsaMpcv1Util.verifyWalletSignatures('mock-user-key', 'mock-backup-key', {
commonKeychain: 'mock-keychain',
walletHSMGPGPublicKeySigs: '',
id: '',
type: 'tss',
}, 'decrypted-share', 1, { env: 'test', pubKeyType: 'nitro' });
// Verify the hardcoded key matches what we expect
capturedKey.should.equal(sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv1']['nitro']['test']);
// Also verify it's the same as what's returned by testPickBitgoPubGpgKeyForSigning
gpgKey.armor().should.equal(capturedKey);
});
describe('EdDSA MPCv2 pickBitgoPubGpgKeyForSigning', function () {
it('should pick correct EdDSA MPCv2 BitGo GPG Pub Key when keychain returns hsmType onprem', async function () {
nock.cleanAll();
// Mock hsmType as 'onprem' for the EdDSA coin so the onprem eddsaMpcv2 key is selected
const bgUrl = sdk_core_1.common.Environments['test'].uri;
nock(bgUrl).get(`/api/v2/${eddsaCoinName}/key/key3`).reply(200, { hsmType: 'onprem' });
const bitgoGpgPubKey = await eddsaMpcv2Utils[0].testPickBitgoPubGpgKeyForSigning(true, undefined, undefined, true);
bitgoGpgPubKey.armor().should.equal(sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['eddsaMpcv2']['onprem']['test']);
});
it('should pick EdDSA MPCv2 BitGo GPG Pub Key based on feature flags for mock env', async function () {
const bgUrl = sdk_core_1.common.Environments['mock'].uri;
const testBitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
const testCoin = testBitgo.coin(eddsaCoinName);
const bitgoGPGKey = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: 'bitgo@test.com',
},
],
type: 'ecc',
curve: 'ed25519',
});
nock(bgUrl)
.get(`/api/v2/${eddsaCoinName}/tss/pubkey`)
.query({ enterpriseId })
.reply(200, { mpcv2PublicKey: bitgoGPGKey.publicKey, eddsaMpcv2PublicKey: bitgoGPGKey.publicKey });
const eddsaMpcv2Util = new TestEddsaMpcv2Utils(testBitgo, testCoin, new sdk_core_1.Wallet(testBitgo, testCoin, eddsaWalletData));
const bitgoGpgPubKey = await eddsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true, undefined, enterpriseId, true);
bitgoGpgPubKey.armor().should.equal(bitgoGPGKey.publicKey);
});
});
describe('BitgoMpcGpgPubKeys.isBitgoEddsaMpcv2PubKey', function () {
it('should return true for the hardcoded on-prem test EdDSA MPCv2 key', function () {
const key = sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['eddsaMpcv2']['onprem']['test'];
assert.ok(sdk_core_1.BitgoMpcGpgPubKeys.isBitgoEddsaMpcv2PubKey(key));
});
it('should return false for the ECDSA MPCv2 on-prem test key', function () {
const key = sdk_core_1.BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv2']['onprem']['test'];
assert.ok(!sdk_core_1.BitgoMpcGpgPubKeys.isBitgoEddsaMpcv2PubKey(key));
});
it('should return false for an arbitrary string', function () {
assert.ok(!sdk_core_1.BitgoMpcGpgPubKeys.isBitgoEddsaMpcv2PubKey('not-a-known-key'));
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Z29NcGNHcGdQdWJLZXlzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGVzdC92Mi91bml0L2ludGVybmFsL3Rzc1V0aWxzL2JpdGdvTXBjR3BnUHViS2V5cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDhDQVN5QjtBQUN6Qiw4Q0FBNEM7QUFFNUMsNENBQTJDO0FBQzNDLG1DQUFtQztBQUNuQyw2QkFBOEI7QUFDOUIsaUNBQWtDO0FBRWxDLE1BQU0sbUJBQW9CLFNBQVEscUJBQVUsQ0FBQyxlQUFlO0lBQ25ELEtBQUssQ0FBQyxnQ0FBZ0MsQ0FDM0MsT0FBZ0IsRUFDaEIsS0FBc0IsRUFDdEIsWUFBcUI7UUFFckIsT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN6RSxDQUFDO0NBQ0Y7QUFFRCxNQUFNLG1CQUFvQixTQUFRLHFCQUFVO0lBQ25DLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FDM0MsT0FBZ0IsRUFDaEIsS0FBc0IsRUFDdEIsWUFBcUIsRUFDckIsWUFBc0I7UUFFdEIsT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDdkYsQ0FBQztDQUNGO0FBRUQsTUFBTSxtQkFBb0IsU0FBUSxxQkFBVSxDQUFDLGVBQWU7SUFDbkQsS0FBSyxDQUFDLGdDQUFnQyxDQUMzQyxPQUFnQixFQUNoQixLQUFzQixFQUN0QixZQUFxQixFQUNyQixZQUFzQjtRQUV0QixPQUFPLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN2RixDQUFDO0NBQ0Y7QUFFRCxRQUFRLENBQUMsdUNBQXVDLEVBQUU7SUFDaEQsTUFBTSxRQUFRLEdBQUcsa0NBQWtDLENBQUM7SUFDcEQsTUFBTSxZQUFZ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LENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw2Q0FBNkMsRUFBRTtZQUNoRCxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsNkJBQWtCLENBQUMsdUJBQXVCLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO1FBQzVFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJpdGdvTXBjR3BnUHViS2V5cyxcbiAgY29tbW9uLFxuICBFQ0RTQVV0aWxzLFxuICBFRERTQVV0aWxzLFxuICBFZGRzYVV0aWxzLFxuICBFbnZpcm9ubWVudE5hbWUsXG4gIElSZXF1ZXN0VHJhY2VyLFxuICBXYWxsZXQsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuXG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL3NyYyc7XG5pbXBvcnQgKiBhcyBvcGVucGdwIGZyb20gJ29wZW5wZ3AnO1xuaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7XG5cbmNsYXNzIFRlc3RFY2RzYU1wY3YyVXRpbHMgZXh0ZW5kcyBFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscyB7XG4gIHB1YmxpYyBhc3luYyB0ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyhcbiAgICBpc01wY3YyOiBib29sZWFuLFxuICAgIHJlcUlkPzogSVJlcXVlc3RUcmFjZXIsXG4gICAgZW50ZXJwcmlzZUlkPzogc3RyaW5nXG4gICk6IFByb21pc2U8b3BlbnBncC5LZXk+IHtcbiAgICByZXR1cm4gdGhpcy5waWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKGlzTXBjdjIsIHJlcUlkLCBlbnRlcnByaXNlSWQpO1xuICB9XG59XG5cbmNsYXNzIFRlc3RFZGRzYU1wY3YxVXRpbHMgZXh0ZW5kcyBFZGRzYVV0aWxzIHtcbiAgcHVibGljIGFzeW5jIHRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKFxuICAgIGlzTXBjdjI6IGJvb2xlYW4sXG4gICAgcmVxSWQ/OiBJUmVxdWVzdFRyYWNlcixcbiAgICBlbnRlcnByaXNlSWQ/OiBzdHJpbmcsXG4gICAgaXNFZGRzYU1wY3YyPzogYm9vbGVhblxuICApOiBQcm9taXNlPG9wZW5wZ3AuS2V5PiB7XG4gICAgcmV0dXJuIHRoaXMucGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyhpc01wY3YyLCByZXFJZCwgZW50ZXJwcmlzZUlkLCBpc0VkZHNhTXBjdjIpO1xuICB9XG59XG5cbmNsYXNzIFRlc3RFZGRzYU1wY3YyVXRpbHMgZXh0ZW5kcyBFRERTQVV0aWxzLkVkZHNhTVBDdjJVdGlscyB7XG4gIHB1YmxpYyBhc3luYyB0ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyhcbiAgICBpc01wY3YyOiBib29sZWFuLFxuICAgIHJlcUlkPzogSVJlcXVlc3RUcmFjZXIsXG4gICAgZW50ZXJwcmlzZUlkPzogc3RyaW5nLFxuICAgIGlzRWRkc2FNcGN2Mj86IGJvb2xlYW5cbiAgKTogUHJvbWlzZTxvcGVucGdwLktleT4ge1xuICAgIHJldHVybiB0aGlzLnBpY2tCaXRnb1B1YkdwZ0tleUZvclNpZ25pbmcoaXNNcGN2MiwgcmVxSWQsIGVudGVycHJpc2VJZCwgaXNFZGRzYU1wY3YyKTtcbiAgfVxufVxuXG5kZXNjcmliZSgnVFNTIE1QQyBQaWNrIEJpdEdvIEdQRyBQdWIgS2V5IFV0aWxzOicsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3Qgd2FsbGV0SWQgPSAnNWIzNDI1MmYxYmYzNDk5MzBlMzQwMjBhMDAwMDAwMDAnO1xuICBjb25zdCBlbnRlcnByaXNlSWQgPSAnNjQ0OTE1M2E2ZjZiYzIwMDA2ZDY2NzcxY2RiZTE1ZDMnO1xuICBjb25zdCBlY2RzYUNvaW5OYW1lID0gJ2h0ZXRoJztcbiAgY29uc3QgZWRkc2FDb2luTmFtZSA9ICd0c29sJztcbiAgY29uc3QgZWNkc2FXYWxsZXREYXRhID0ge1xuICAgIGlkOiB3YWxsZXRJZCxcbiAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlSWQsXG4gICAgY29pbjogZWNkc2FDb2luTmFtZSxcbiAgICBjb2luU3BlY2lmaWM6IHt9LFxuICAgIG11bHRpc2lnVHlwZTogJ3RzcycsXG4gICAga2V5czogWydrZXkxJywgJ2tleTInLCAna2V5MyddLFxuICB9O1xuICBjb25zdCBlZGRzYVdhbGxldERhdGEgPSB7XG4gICAgaWQ6IHdhbGxldElkLFxuICAgIGVudGVycHJpc2U6IGVudGVycHJpc2VJZCxcbiAgICBjb2luOiBlZGRzYUNvaW5OYW1lLFxuICAgIGNvaW5TcGVjaWZpYzoge30sXG4gICAgbXVsdGlzaWdUeXBlOiAndHNzJyxcbiAgICBrZXlzOiBbJ2tleTEnLCAna2V5MicsICdrZXkzJ10sXG4gIH07XG4gIGNvbnN0IGVudnM6IEVudmlyb25tZW50TmFtZVtdID0gWyd0ZXN0JywgJ3N0YWdpbmcnLCAncHJvZCddO1xuICBjb25zdCBlY2RzYU1wY3YyVXRpbHM6IFRlc3RFY2RzYU1wY3YyVXRpbHNbXSA9IFtdO1xuICBjb25zdCBlZGRzYU1wY3YxVXRpbHM6IFRlc3RFZGRzYU1wY3YxVXRpbHNbXSA9IFtdO1xuICBjb25zdCBlZGRzYU1wY3YyVXRpbHM6IFRlc3RFZGRzYU1wY3YyVXRpbHNbXSA9IFtdO1xuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIGZvciAoY29uc3QgZW52IG9mIGVudnMpIHtcbiAgICAgIGNvbnN0IGJpdGdvSW5zdGFuY2UgPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52IH0pO1xuICAgICAgYml0Z29JbnN0YW5jZS5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICAgIGxldCBjb2luSW5zdGFuY2UgPSBiaXRnb0luc3RhbmNlLmNvaW4oZWNkc2FDb2luTmFtZSk7XG4gICAgICBlY2RzYU1wY3YyVXRpbHMucHVzaChcbiAgICAgICAgbmV3IFRlc3RFY2RzYU1wY3YyVXRpbHMoYml0Z29JbnN0YW5jZSwgY29pbkluc3RhbmNlLCBuZXcgV2FsbGV0KGJpdGdvSW5zdGFuY2UsIGNvaW5JbnN0YW5jZSwgZWNkc2FXYWxsZXREYXRhKSlcbiAgICAgICk7XG4gICAgICBjb2luSW5zdGFuY2UgPSBiaXRnb0luc3RhbmNlLmNvaW4oZWRkc2FDb2luTmFtZSk7XG4gICAgICBlZGRzYU1wY3YxVXRpbHMucHVzaChcbiAgICAgICAgbmV3IFRlc3RFZGRzYU1wY3YxVXRpbHMoYml0Z29JbnN0YW5jZSwgY29pbkluc3RhbmNlLCBuZXcgV2FsbGV0KGJpdGdvSW5zdGFuY2UsIGNvaW5JbnN0YW5jZSwgZWRkc2FXYWxsZXREYXRhKSlcbiAgICAgICk7XG4gICAgICBlZGRzYU1wY3YyVXRpbHMucHVzaChcbiAgICAgICAgbmV3IFRlc3RFZGRzYU1wY3YyVXRpbHMoYml0Z29JbnN0YW5jZSwgY29pbkluc3RhbmNlLCBuZXcgV2FsbGV0KGJpdGdvSW5zdGFuY2UsIGNvaW5JbnN0YW5jZSwgZWRkc2FXYWxsZXREYXRhKSlcbiAgICAgICk7XG4gICAgfVxuICB9KTtcblxuICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKGNvbnN0IGVudiBvZiBlbnZzKSB7XG4gICAgICBjb25zdCBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbZW52XS51cmk7XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvJHtlY2RzYUNvaW5OYW1lfS9rZXkva2V5M2ApLnRpbWVzKGVudnMubGVuZ3RoKS5yZXBseSgyMDAsIHsgaHNtVHlwZTogJ29ucHJlbScgfSk7XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvJHtlZGRzYUNvaW5OYW1lfS9rZXkva2V5M2ApLnRpbWVzKGVudnMubGVuZ3RoKS5yZXBseSgyMDAsIHsgaHNtVHlwZTogJ25pdHJvJyB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIGVudnMuZm9yRWFjaChhc3luYyBmdW5jdGlvbiAoZW52LCBpbmRleCkge1xuICAgIGl0KGBzaG91bGQgcGljayBjb3JyZWN0IE1wY3YyIEJpdEdvIEdQRyBQdWIgS2V5IGZvciAke2Vudn0gZW52YCwgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYml0Z29HcGdQdWJLZXkgPSBhd2FpdCBlY2RzYU1wY3YyVXRpbHNbaW5kZXhdLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKHRydWUpO1xuICAgICAgYml0Z29HcGdQdWJLZXlcbiAgICAgICAgLmFybW9yKClcbiAgICAgICAgLnNob3VsZC5lcXVhbChCaXRnb01wY0dwZ1B1YktleXMuYml0Z29NcGNHcGdQdWJLZXlzWydtcGN2MiddWydvbnByZW0nXVtlbnYgPT09ICdzdGFnaW5nJyA/ICd0ZXN0JyA6IGVudl0pO1xuICAgIH0pO1xuICB9KTtcblxuICBlbnZzLmZvckVhY2goYXN5bmMgZnVuY3Rpb24gKGVudiwgaW5kZXgpIHtcbiAgICBpdChgc2hvdWxkIHBpY2sgY29ycmVjdCBNcGN2MSBCaXRHbyBHUEcgUHViIEtleSBmb3IgJHtlbnZ9IGVudmAsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJpdGdvR3BnUHViS2V5ID0gYXdhaXQgZWRkc2FNcGN2MVV0aWxzW2luZGV4XS50ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyhmYWxzZSk7XG4gICAgICBiaXRnb0dwZ1B1YktleVxuICAgICAgICAuYXJtb3IoKVxuICAgICAgICAuc2hvdWxkLmVxdWFsKEJpdGdvTXBjR3BnUHViS2V5cy5iaXRnb01wY0dwZ1B1YktleXNbJ21wY3YxJ11bJ25pdHJvJ11bZW52ID09PSAnc3RhZ2luZycgPyAndGVzdCcgOiBlbnZdKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoYHNob3VsZCBwaWNrIEJpdEdvIEdQRyBQdWIgS2V5IGJhc2VkIG9uIGVudGVycHJpc2UgZmxhZyBmb3IgbW9jayBlbnZgLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzWydtb2NrJ10udXJpO1xuICAgIGNvbnN0IHRlc3RCaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBjb25zdCB0ZXN0Q29pbiA9IHRlc3RCaXRnby5jb2luKGVjZHNhQ29pbk5hbWUpO1xuICAgIGNvbnN0IGJpdGdvR1BHS2V5ID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICB1c2VySURzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnYml0Z28nLFxuICAgICAgICAgIGVtYWlsOiAnYml0Z29AdGVzdC5jb20nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgICBub2NrKGJnVXJsKVxuICAgICAgLmdldChgL2FwaS92Mi8ke2VjZHNhQ29pbk5hbWV9L3Rzcy9wdWJrZXlgKVxuICAgICAgLnF1ZXJ5KHsgZW50ZXJwcmlzZUlkIH0pXG4gICAgICAucmVwbHkoMjAwLCB7IG1wY3YyUHVibGljS2V5OiBiaXRnb0dQR0tleS5wdWJsaWNLZXkgfSk7XG4gICAgY29uc3QgZWNkc2FNcGN2MlV0aWwgPSBuZXcgVGVzdEVjZHNhTXBjdjJVdGlscyhcbiAgICAgIHRlc3RCaXRnbyxcbiAgICAgIHRlc3RDb2luLFxuICAgICAgbmV3IFdhbGxldCh0ZXN0Qml0Z28sIHRlc3RDb2luLCBlY2RzYVdhbGxldERhdGEpXG4gICAgKTtcbiAgICBjb25zdCBiaXRnb0dwZ1B1YktleSA9IGF3YWl0IGVjZHNhTXBjdjJVdGlsLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKHRydWUsIHVuZGVmaW5lZCwgZW50ZXJwcmlzZUlkKTtcbiAgICBiaXRnb0dwZ1B1YktleS5hcm1vcigpLnNob3VsZC5lcXVhbChiaXRnb0dQR0tleS5wdWJsaWNLZXkpO1xuICB9KTtcblxuICBpdChgc2hvdWxkIHBpY2sgQml0R28gR1BHIFB1YiBLZXkgYmFzZWQgb24gY29uc3RhbnRzIGFwaSBmb3IgbW9jayBlbnYgaWYgZW50ZXJwcmlzZSBmbGFnIGJhc2VkIGZldGNoIGZhaWxzYCwgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICBjb25zdCBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbJ21vY2snXS51cmk7XG4gICAgY29uc3QgdGVzdEJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGNvbnN0IHRlc3RDb2luID0gdGVzdEJpdGdvLmNvaW4oZWNkc2FDb2luTmFtZSk7XG4gICAgY29uc3QgYml0Z29HUEdLZXkgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgIHVzZXJJRHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdiaXRnbycsXG4gICAgICAgICAgZW1haWw6ICdiaXRnb0B0ZXN0LmNvbScsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIGNvbnN0IGNvbnN0YW50cyA9IHtcbiAgICAgIG1wYzoge1xuICAgICAgICBiaXRnb01QQ3YyUHVibGljS2V5OiBiaXRnb0dQR0tleS5wdWJsaWNLZXksXG4gICAgICAgIGJpdGdvUHVibGljS2V5OiBiaXRnb0dQR0tleS5wdWJsaWNLZXksXG4gICAgICB9LFxuICAgIH07XG4gICAgbm9jayhiZ1VybCkuZ2V0KCcvYXBpL3YxL2NsaWVudC9jb25zdGFudHMnKS50aW1lcygyKS5yZXBseSgyMDAsIHsgdHRsOiAzNjAwLCBjb25zdGFudHMgfSk7XG4gICAgY29uc3QgZWNkc2FNcGN2MlV0aWwgPSBuZXcgVGVzdEVjZHNhTXBjdjJVdGlscyhcbiAgICAgIHRlc3RCaXRnbyxcbiAgICAgIHRlc3RDb2luLFxuICAgICAgbmV3IFdhbGxldCh0ZXN0Qml0Z28sIHRlc3RDb2luLCBlY2RzYVdhbGxldERhdGEpXG4gICAgKTtcbiAgICBjb25zdCBiaXRnb0dwZ1B1YktleSA9IGF3YWl0IGVjZHNhTXBjdjJVdGlsLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKHRydWUsIHVuZGVmaW5lZCwgZW50ZXJwcmlzZUlkKTtcbiAgICBiaXRnb0dwZ1B1YktleS5hcm1vcigpLnNob3VsZC5lcXVhbChiaXRnb0dQR0tleS5wdWJsaWNLZXkpO1xuICB9KTtcblxuICBpdChgc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIGNvbmZpZyBpcyBub3QgYXZhaWxhYmxlIGluIG9uZSBvZiB0ZXN0LCBzdGFnaW5nLCBvciBwcm9kYCwgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICBjb25zdCB0ZXN0Qml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAndGVzdCcgfSk7XG4gICAgY29uc3QgdGVzdENvaW4gPSB0ZXN0Qml0Z28uY29pbihlY2RzYUNvaW5OYW1lKTtcbiAgICBjb25zdCBlY2RzYU1wY3YyVXRpbCA9IG5ldyBUZXN0RWNkc2FNcGN2MlV0aWxzKFxuICAgICAgdGVzdEJpdGdvLFxuICAgICAgdGVzdENvaW4sXG4gICAgICBuZXcgV2FsbGV0KHRlc3RCaXRnbywgdGVzdENvaW4sIGVjZHNhV2FsbGV0RGF0YSlcbiAgICApO1xuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGVjZHNhTXBjdjJVdGlsLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKHRydWUpKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBzZWxlY3QgdGhlIGNvcnJlY3QgR1BHIGtleSBmb3IgdmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyB3aXRoIGhhcmRjb2RlZCBvcHRpb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIC8vIFRlc3QgZW52aXJvbm1lbnQgc2V0dXBcbiAgICBjb25zdCBlbnYgPSAndGVzdCc7XG4gICAgY29uc3QgYml0Z29JbnN0YW5jZSA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnYgfSk7XG4gICAgYml0Z29JbnN0YW5jZS5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBjb25zdCBjb2luSW5zdGFuY2UgPSBiaXRnb0luc3RhbmNlLmNvaW4oZWRkc2FDb2luTmFtZSk7XG4gICAgY29uc3QgZWRkc2FNcGN2MVV0aWwgPSBuZXcgVGVzdEVkZHNhTXBjdjFVdGlscyhcbiAgICAgIGJpdGdvSW5zdGFuY2UsXG4gICAgICBjb2luSW5zdGFuY2UsXG4gICAgICBuZXcgV2FsbGV0KGJpdGdvSW5zdGFuY2UsIGNvaW5JbnN0YW5jZSwgZWRkc2FXYWxsZXREYXRhKVxuICAgICk7XG5cbiAgICAvLyBHZXQgdGhlIGtleSB0aGF0IHdvdWxkIGJlIHNlbGVjdGVkIHdoZW4gdXNpbmcgaGFyZGNvZGVkIEJpdEdvIGtleXNcbiAgICAvLyBtcGN2MSBhbmQgbml0cm8gYXJlIHBhc3NlZCBhcyBvcHRpb25zXG4gICAgY29uc3QgZ3BnS2V5ID0gYXdhaXQgZWRkc2FNcGN2MVV0aWwudGVzdFBpY2tCaXRnb1B1YkdwZ0tleUZvclNpZ25pbmcoZmFsc2UsIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcblxuICAgIC8vIE1vY2sgaW1wbGVtZW50YXRpb24gb2YgdmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyB0byBjYXB0dXJlIHRoZSBiaXRnb0dwZ0tleSB0aGF0IGdldHMgdXNlZFxuICAgIGxldCBjYXB0dXJlZEtleTtcbiAgICBlZGRzYU1wY3YxVXRpbC52ZXJpZnlXYWxsZXRTaWduYXR1cmVzID0gYXN5bmMgZnVuY3Rpb24gKFxuICAgICAgdXNlckdwZ1B1YixcbiAgICAgIGJhY2t1cEdwZ1B1YixcbiAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICBkZWNyeXB0ZWRTaGFyZSxcbiAgICAgIHZlcmlmaWVySW5kZXgsXG4gICAgICB1c2VIYXJkY29kZWRCaXRHb0tleXNcbiAgICApIHtcbiAgICAgIC8vIFNhdmUgdGhlIGtleSB0aGF0IHdvdWxkIGJlIHVzZWQgd2hlbiBzcGVjaWZ5aW5nIGhhcmRjb2RlZCBvcHRpb25zXG4gICAgICBpZiAodXNlSGFyZGNvZGVkQml0R29LZXlzKSB7XG4gICAgICAgIGNvbnN0IGhhcmRjb2RlZEtleSA9IGF3YWl0IG9wZW5wZ3AucmVhZEtleSh7XG4gICAgICAgICAgYXJtb3JlZEtleTogQml0Z29NcGNHcGdQdWJLZXlzLmJpdGdvTXBjR3BnUHViS2V5c1snbXBjdjEnXVsnbml0cm8nXVsndGVzdCddLFxuICAgICAgICB9KTtcbiAgICAgICAgY2FwdHVyZWRLZXkgPSBoYXJkY29kZWRLZXkuYXJtb3IoKTtcbiAgICAgIH1cbiAgICAgIC8vIE5vdCBhY3R1YWxseSB2ZXJpZnlpbmcgaW4gdGhpcyB0ZXN0XG4gICAgICByZXR1cm47XG4gICAgfTtcblxuICAgIC8vIENhbGwgd2l0aCBoYXJkY29kZWQga2V5IG9wdGlvbnNcbiAgICBhd2FpdCBlZGRzYU1wY3YxVXRpbC52ZXJpZnlXYWxsZXRTaWduYXR1cmVzKFxuICAgICAgJ21vY2stdXNlci1rZXknLFxuICAgICAgJ21vY2stYmFja3VwLWtleScsXG4gICAgICB7XG4gICAgICAgIGNvbW1vbktleWNoYWluOiAnbW9jay1rZXljaGFpbicsXG4gICAgICAgIHdhbGxldEhTTUdQR1B1YmxpY0tleVNpZ3M6ICcnLFxuICAgICAgICBpZDogJycsXG4gICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgfSxcbiAgICAgICdkZWNyeXB0ZWQtc2hhcmUnLFxuICAgICAgMSxcbiAgICAgIHsgZW52OiAndGVzdCcsIHB1YktleVR5cGU6ICduaXRybycgfVxuICAgICk7XG5cbiAgICAvLyBWZXJpZnkgdGhlIGhhcmRjb2RlZCBrZXkgbWF0Y2hlcyB3aGF0IHdlIGV4cGVjdFxuICAgIGNhcHR1cmVkS2V5LnNob3VsZC5lcXVhbChCaXRnb01wY0dwZ1B1YktleXMuYml0Z29NcGNHcGdQdWJLZXlzWydtcGN2MSddWyduaXRybyddWyd0ZXN0J10pO1xuICAgIC8vIEFsc28gdmVyaWZ5IGl0J3MgdGhlIHNhbWUgYXMgd2hhdCdzIHJldHVybmVkIGJ5IHRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nXG4gICAgZ3BnS2V5LmFybW9yKCkuc2hvdWxkLmVxdWFsKGNhcHR1cmVkS2V5KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0VkRFNBIE1QQ3YyIHBpY2tCaXRnb1B1YkdwZ0tleUZvclNpZ25pbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBwaWNrIGNvcnJlY3QgRWREU0EgTVBDdjIgQml0R28gR1BHIFB1YiBLZXkgd2hlbiBrZXljaGFpbiByZXR1cm5zIGhzbVR5cGUgb25wcmVtJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbm9jay5jbGVhbkFsbCgpO1xuICAgICAgLy8gTW9jayBoc21UeXBlIGFzICdvbnByZW0nIGZvciB0aGUgRWREU0EgY29pbiBzbyB0aGUgb25wcmVtIGVkZHNhTXBjdjIga2V5IGlzIHNlbGVjdGVkXG4gICAgICBjb25zdCBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbJ3Rlc3QnXS51cmk7XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvJHtlZGRzYUNvaW5OYW1lfS9rZXkva2V5M2ApLnJlcGx5KDIwMCwgeyBoc21UeXBlOiAnb25wcmVtJyB9KTtcbiAgICAgIGNvbnN0IGJpdGdvR3BnUHViS2V5ID0gYXdhaXQgZWRkc2FNcGN2MlV0aWxzWzBdLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKFxuICAgICAgICB0cnVlLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcbiAgICAgIGJpdGdvR3BnUHViS2V5LmFybW9yKCkuc2hvdWxkLmVxdWFsKEJpdGdvTXBjR3BnUHViS2V5cy5iaXRnb01wY0dwZ1B1YktleXNbJ2VkZHNhTXBjdjInXVsnb25wcmVtJ11bJ3Rlc3QnXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBpY2sgRWREU0EgTVBDdjIgQml0R28gR1BHIFB1YiBLZXkgYmFzZWQgb24gZmVhdHVyZSBmbGFncyBmb3IgbW9jayBlbnYnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbJ21vY2snXS51cmk7XG4gICAgICBjb25zdCB0ZXN0Qml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCB0ZXN0Q29pbiA9IHRlc3RCaXRnby5jb2luKGVkZHNhQ29pbk5hbWUpO1xuICAgICAgY29uc3QgYml0Z29HUEdLZXkgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgICAgdXNlcklEczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdiaXRnbycsXG4gICAgICAgICAgICBlbWFpbDogJ2JpdGdvQHRlc3QuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICB0eXBlOiAnZWNjJyxcbiAgICAgICAgY3VydmU6ICdlZDI1NTE5JyxcbiAgICAgIH0pO1xuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLmdldChgL2FwaS92Mi8ke2VkZHNhQ29pbk5hbWV9L3Rzcy9wdWJrZXlgKVxuICAgICAgICAucXVlcnkoeyBlbnRlcnByaXNlSWQgfSlcbiAgICAgICAgLnJlcGx5KDIwMCwgeyBtcGN2MlB1YmxpY0tleTogYml0Z29HUEdLZXkucHVibGljS2V5LCBlZGRzYU1wY3YyUHVibGljS2V5OiBiaXRnb0dQR0tleS5wdWJsaWNLZXkgfSk7XG4gICAgICBjb25zdCBlZGRzYU1wY3YyVXRpbCA9IG5ldyBUZXN0RWRkc2FNcGN2MlV0aWxzKFxuICAgICAgICB0ZXN0Qml0Z28sXG4gICAgICAgIHRlc3RDb2luLFxuICAgICAgICBuZXcgV2FsbGV0KHRlc3RCaXRnbywgdGVzdENvaW4sIGVkZHNhV2FsbGV0RGF0YSlcbiAgICAgICk7XG4gICAgICBjb25zdCBiaXRnb0dwZ1B1YktleSA9IGF3YWl0IGVkZHNhTXBjdjJVdGlsLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKHRydWUsIHVuZGVmaW5lZCwgZW50ZXJwcmlzZUlkLCB0cnVlKTtcbiAgICAgIGJpdGdvR3BnUHViS2V5LmFybW9yKCkuc2hvdWxkLmVxdWFsKGJpdGdvR1BHS2V5LnB1YmxpY0tleSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCaXRnb01wY0dwZ1B1YktleXMuaXNCaXRnb0VkZHNhTXBjdjJQdWJLZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdGhlIGhhcmRjb2RlZCBvbi1wcmVtIHRlc3QgRWREU0EgTVBDdjIga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5ID0gQml0Z29NcGNHcGdQdWJLZXlzLmJpdGdvTXBjR3BnUHViS2V5c1snZWRkc2FNcGN2MiddWydvbnByZW0nXVsndGVzdCddO1xuICAgICAgYXNzZXJ0Lm9rKEJpdGdvTXBjR3BnUHViS2V5cy5pc0JpdGdvRWRkc2FNcGN2MlB1YktleShrZXkpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciB0aGUgRUNEU0EgTVBDdjIgb24tcHJlbSB0ZXN0IGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleSA9IEJpdGdvTXBjR3BnUHViS2V5cy5iaXRnb01wY0dwZ1B1YktleXNbJ21wY3YyJ11bJ29ucHJlbSddWyd0ZXN0J107XG4gICAgICBhc3NlcnQub2soIUJpdGdvTXBjR3BnUHViS2V5cy5pc0JpdGdvRWRkc2FNcGN2MlB1YktleShrZXkpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBhbiBhcmJpdHJhcnkgc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0Lm9rKCFCaXRnb01wY0dwZ1B1YktleXMuaXNCaXRnb0VkZHNhTXBjdjJQdWJLZXkoJ25vdC1hLWtub3duLWtleScpKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==