UNPKG

bitgo

Version:
216 lines • 39.5 kB
"use strict"; 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==