bitgo
Version:
BitGo JavaScript SDK
164 lines • 28.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) {
return this.pickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId);
}
}
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 = [];
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)));
}
});
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);
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Z29NcGNHcGdQdWJLZXlzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGVzdC92Mi91bml0L2ludGVybmFsL3Rzc1V0aWxzL2JpdGdvTXBjR3BnUHViS2V5cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDhDQVF5QjtBQUN6Qiw4Q0FBNEM7QUFFNUMsNENBQTJDO0FBQzNDLG1DQUFtQztBQUNuQyw2QkFBOEI7QUFDOUIsaUNBQWtDO0FBRWxDLE1BQU0sbUJBQW9CLFNBQVEscUJBQVUsQ0FBQyxlQUFlO0lBQ25ELEtBQUssQ0FBQyxnQ0FBZ0MsQ0FDM0MsT0FBZ0IsRUFDaEIsS0FBc0IsRUFDdEIsWUFBcUI7UUFFckIsT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN6RSxDQUFDO0NBQ0Y7QUFFRCxNQUFNLG1CQUFvQixTQUFRLHFCQUFVO0lBQ25DLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FDM0MsT0FBZ0IsRUFDaEIsS0FBc0IsRUFDdEIsWUFBcUI7UUFFckIsT0FBTyxJQUFJLENBQUMsNEJBQTRCLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN6RSxDQUFDO0NBQ0Y7QUFFRCxRQUFRLENBQUMsdUNBQXVDLEVBQUU7SUFDaEQsTUFBTSxRQUFRLEdBQUcsa0NBQWtDLENBQUM7SUFDcEQsTUFBTSxZQUFZLEdBQUcsa0NBQWtDLENBQUM7SUFDeEQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDO0lBQzlCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQztJQUM3QixNQUFNLGVBQWUsR0FBRztRQUN0QixFQUFFLEVBQUUsUUFBUTtRQUNaLFVBQVUsRUFBRSxZQUFZO1FBQ3hCLElBQUksRUFBRSxhQUFhO1FBQ25CLFlBQVksRUFBRSxFQUFFO1FBQ2hCLFlBQVksRUFBRSxLQUFLO1FBQ25CLElBQUksRUFBRSxDQUFD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LGVBQWU7WUFDL0IseUJBQXlCLEVBQUUsRUFBRTtZQUM3QixFQUFFLEVBQUUsRUFBRTtZQUNOLElBQUksRUFBRSxLQUFLO1NBQ1osRUFDRCxpQkFBaUIsRUFDakIsQ0FBQyxFQUNELEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLENBQ3JDLENBQUM7UUFFRixrREFBa0Q7UUFDbEQsV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsNkJBQWtCLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUMxRixtRkFBbUY7UUFDbkYsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDM0MsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJpdGdvTXBjR3BnUHViS2V5cyxcbiAgY29tbW9uLFxuICBFQ0RTQVV0aWxzLFxuICBFZGRzYVV0aWxzLFxuICBFbnZpcm9ubWVudE5hbWUsXG4gIElSZXF1ZXN0VHJhY2VyLFxuICBXYWxsZXQsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuXG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL3NyYyc7XG5pbXBvcnQgKiBhcyBvcGVucGdwIGZyb20gJ29wZW5wZ3AnO1xuaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7XG5cbmNsYXNzIFRlc3RFY2RzYU1wY3YyVXRpbHMgZXh0ZW5kcyBFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscyB7XG4gIHB1YmxpYyBhc3luYyB0ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyhcbiAgICBpc01wY3YyOiBib29sZWFuLFxuICAgIHJlcUlkPzogSVJlcXVlc3RUcmFjZXIsXG4gICAgZW50ZXJwcmlzZUlkPzogc3RyaW5nXG4gICk6IFByb21pc2U8b3BlbnBncC5LZXk+IHtcbiAgICByZXR1cm4gdGhpcy5waWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKGlzTXBjdjIsIHJlcUlkLCBlbnRlcnByaXNlSWQpO1xuICB9XG59XG5cbmNsYXNzIFRlc3RFZGRzYU1wY3YxVXRpbHMgZXh0ZW5kcyBFZGRzYVV0aWxzIHtcbiAgcHVibGljIGFzeW5jIHRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKFxuICAgIGlzTXBjdjI6IGJvb2xlYW4sXG4gICAgcmVxSWQ/OiBJUmVxdWVzdFRyYWNlcixcbiAgICBlbnRlcnByaXNlSWQ/OiBzdHJpbmdcbiAgKTogUHJvbWlzZTxvcGVucGdwLktleT4ge1xuICAgIHJldHVybiB0aGlzLnBpY2tCaXRnb1B1YkdwZ0tleUZvclNpZ25pbmcoaXNNcGN2MiwgcmVxSWQsIGVudGVycHJpc2VJZCk7XG4gIH1cbn1cblxuZGVzY3JpYmUoJ1RTUyBNUEMgUGljayBCaXRHbyBHUEcgUHViIEtleSBVdGlsczonLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IHdhbGxldElkID0gJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJztcbiAgY29uc3QgZW50ZXJwcmlzZUlkID0gJzY0NDkxNTNhNmY2YmMyMDAwNmQ2Njc3MWNkYmUxNWQzJztcbiAgY29uc3QgZWNkc2FDb2luTmFtZSA9ICdodGV0aCc7XG4gIGNvbnN0IGVkZHNhQ29pbk5hbWUgPSAndHNvbCc7XG4gIGNvbnN0IGVjZHNhV2FsbGV0RGF0YSA9IHtcbiAgICBpZDogd2FsbGV0SWQsXG4gICAgZW50ZXJwcmlzZTogZW50ZXJwcmlzZUlkLFxuICAgIGNvaW46IGVjZHNhQ29pbk5hbWUsXG4gICAgY29pblNwZWNpZmljOiB7fSxcbiAgICBtdWx0aXNpZ1R5cGU6ICd0c3MnLFxuICAgIGtleXM6IFsna2V5MScsICdrZXkyJywgJ2tleTMnXSxcbiAgfTtcbiAgY29uc3QgZWRkc2FXYWxsZXREYXRhID0ge1xuICAgIGlkOiB3YWxsZXRJZCxcbiAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlSWQsXG4gICAgY29pbjogZWRkc2FDb2luTmFtZSxcbiAgICBjb2luU3BlY2lmaWM6IHt9LFxuICAgIG11bHRpc2lnVHlwZTogJ3RzcycsXG4gICAga2V5czogWydrZXkxJywgJ2tleTInLCAna2V5MyddLFxuICB9O1xuICBjb25zdCBlbnZzOiBFbnZpcm9ubWVudE5hbWVbXSA9IFsndGVzdCcsICdzdGFnaW5nJywgJ3Byb2QnXTtcbiAgY29uc3QgZWNkc2FNcGN2MlV0aWxzOiBUZXN0RWNkc2FNcGN2MlV0aWxzW10gPSBbXTtcbiAgY29uc3QgZWRkc2FNcGN2MVV0aWxzOiBUZXN0RWRkc2FNcGN2MVV0aWxzW10gPSBbXTtcblxuICBiZWZvcmUoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICBmb3IgKGNvbnN0IGVudiBvZiBlbnZzKSB7XG4gICAgICBjb25zdCBiaXRnb0luc3RhbmNlID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudiB9KTtcbiAgICAgIGJpdGdvSW5zdGFuY2UuaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBsZXQgY29pbkluc3RhbmNlID0gYml0Z29JbnN0YW5jZS5jb2luKGVjZHNhQ29pbk5hbWUpO1xuICAgICAgZWNkc2FNcGN2MlV0aWxzLnB1c2goXG4gICAgICAgIG5ldyBUZXN0RWNkc2FNcGN2MlV0aWxzKGJpdGdvSW5zdGFuY2UsIGNvaW5JbnN0YW5jZSwgbmV3IFdhbGxldChiaXRnb0luc3RhbmNlLCBjb2luSW5zdGFuY2UsIGVjZHNhV2FsbGV0RGF0YSkpXG4gICAgICApO1xuICAgICAgY29pbkluc3RhbmNlID0gYml0Z29JbnN0YW5jZS5jb2luKGVkZHNhQ29pbk5hbWUpO1xuICAgICAgZWRkc2FNcGN2MVV0aWxzLnB1c2goXG4gICAgICAgIG5ldyBUZXN0RWRkc2FNcGN2MVV0aWxzKGJpdGdvSW5zdGFuY2UsIGNvaW5JbnN0YW5jZSwgbmV3IFdhbGxldChiaXRnb0luc3RhbmNlLCBjb2luSW5zdGFuY2UsIGVkZHNhV2FsbGV0RGF0YSkpXG4gICAgICApO1xuICAgIH1cbiAgfSk7XG5cbiAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgZm9yIChjb25zdCBlbnYgb2YgZW52cykge1xuICAgICAgY29uc3QgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2Vudl0udXJpO1xuICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyLyR7ZWNkc2FDb2luTmFtZX0va2V5L2tleTNgKS50aW1lcyhlbnZzLmxlbmd0aCkucmVwbHkoMjAwLCB7IGhzbVR5cGU6ICdvbnByZW0nIH0pO1xuICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyLyR7ZWRkc2FDb2luTmFtZX0va2V5L2tleTNgKS50aW1lcyhlbnZzLmxlbmd0aCkucmVwbHkoMjAwLCB7IGhzbVR5cGU6ICduaXRybycgfSk7XG4gICAgfVxuICB9KTtcblxuICBlbnZzLmZvckVhY2goYXN5bmMgZnVuY3Rpb24gKGVudiwgaW5kZXgpIHtcbiAgICBpdChgc2hvdWxkIHBpY2sgY29ycmVjdCBNcGN2MiBCaXRHbyBHUEcgUHViIEtleSBmb3IgJHtlbnZ9IGVudmAsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJpdGdvR3BnUHViS2V5ID0gYXdhaXQgZWNkc2FNcGN2MlV0aWxzW2luZGV4XS50ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyh0cnVlKTtcbiAgICAgIGJpdGdvR3BnUHViS2V5XG4gICAgICAgIC5hcm1vcigpXG4gICAgICAgIC5zaG91bGQuZXF1YWwoQml0Z29NcGNHcGdQdWJLZXlzLmJpdGdvTXBjR3BnUHViS2V5c1snbXBjdjInXVsnb25wcmVtJ11bZW52ID09PSAnc3RhZ2luZycgPyAndGVzdCcgOiBlbnZdKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZW52cy5mb3JFYWNoKGFzeW5jIGZ1bmN0aW9uIChlbnYsIGluZGV4KSB7XG4gICAgaXQoYHNob3VsZCBwaWNrIGNvcnJlY3QgTXBjdjEgQml0R28gR1BHIFB1YiBLZXkgZm9yICR7ZW52fSBlbnZgLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiaXRnb0dwZ1B1YktleSA9IGF3YWl0IGVkZHNhTXBjdjFVdGlsc1tpbmRleF0udGVzdFBpY2tCaXRnb1B1YkdwZ0tleUZvclNpZ25pbmcoZmFsc2UpO1xuICAgICAgYml0Z29HcGdQdWJLZXlcbiAgICAgICAgLmFybW9yKClcbiAgICAgICAgLnNob3VsZC5lcXVhbChCaXRnb01wY0dwZ1B1YktleXMuYml0Z29NcGNHcGdQdWJLZXlzWydtcGN2MSddWyduaXRybyddW2VudiA9PT0gJ3N0YWdpbmcnID8gJ3Rlc3QnIDogZW52XSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KGBzaG91bGQgcGljayBCaXRHbyBHUEcgUHViIEtleSBiYXNlZCBvbiBlbnRlcnByaXNlIGZsYWcgZm9yIG1vY2sgZW52YCwgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1snbW9jayddLnVyaTtcbiAgICBjb25zdCB0ZXN0Qml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgY29uc3QgdGVzdENvaW4gPSB0ZXN0Qml0Z28uY29pbihlY2RzYUNvaW5OYW1lKTtcbiAgICBjb25zdCBiaXRnb0dQR0tleSA9IGF3YWl0IG9wZW5wZ3AuZ2VuZXJhdGVLZXkoe1xuICAgICAgdXNlcklEczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ2JpdGdvJyxcbiAgICAgICAgICBlbWFpbDogJ2JpdGdvQHRlc3QuY29tJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gICAgbm9jayhiZ1VybClcbiAgICAgIC5nZXQoYC9hcGkvdjIvJHtlY2RzYUNvaW5OYW1lfS90c3MvcHVia2V5YClcbiAgICAgIC5xdWVyeSh7IGVudGVycHJpc2VJZCB9KVxuICAgICAgLnJlcGx5KDIwMCwgeyBtcGN2MlB1YmxpY0tleTogYml0Z29HUEdLZXkucHVibGljS2V5IH0pO1xuICAgIGNvbnN0IGVjZHNhTXBjdjJVdGlsID0gbmV3IFRlc3RFY2RzYU1wY3YyVXRpbHMoXG4gICAgICB0ZXN0Qml0Z28sXG4gICAgICB0ZXN0Q29pbixcbiAgICAgIG5ldyBXYWxsZXQodGVzdEJpdGdvLCB0ZXN0Q29pbiwgZWNkc2FXYWxsZXREYXRhKVxuICAgICk7XG4gICAgY29uc3QgYml0Z29HcGdQdWJLZXkgPSBhd2FpdCBlY2RzYU1wY3YyVXRpbC50ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyh0cnVlLCB1bmRlZmluZWQsIGVudGVycHJpc2VJZCk7XG4gICAgYml0Z29HcGdQdWJLZXkuYXJtb3IoKS5zaG91bGQuZXF1YWwoYml0Z29HUEdLZXkucHVibGljS2V5KTtcbiAgfSk7XG5cbiAgaXQoYHNob3VsZCBwaWNrIEJpdEdvIEdQRyBQdWIgS2V5IGJhc2VkIG9uIGNvbnN0YW50cyBhcGkgZm9yIG1vY2sgZW52IGlmIGVudGVycHJpc2UgZmxhZyBiYXNlZCBmZXRjaCBmYWlsc2AsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgY29uc3QgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzWydtb2NrJ10udXJpO1xuICAgIGNvbnN0IHRlc3RCaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBjb25zdCB0ZXN0Q29pbiA9IHRlc3RCaXRnby5jb2luKGVjZHNhQ29pbk5hbWUpO1xuICAgIGNvbnN0IGJpdGdvR1BHS2V5ID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICB1c2VySURzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnYml0Z28nLFxuICAgICAgICAgIGVtYWlsOiAnYml0Z29AdGVzdC5jb20nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgICBjb25zdCBjb25zdGFudHMgPSB7XG4gICAgICBtcGM6IHtcbiAgICAgICAgYml0Z29NUEN2MlB1YmxpY0tleTogYml0Z29HUEdLZXkucHVibGljS2V5LFxuICAgICAgICBiaXRnb1B1YmxpY0tleTogYml0Z29HUEdLZXkucHVibGljS2V5LFxuICAgICAgfSxcbiAgICB9O1xuICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykudGltZXMoMikucmVwbHkoMjAwLCB7IHR0bDogMzYwMCwgY29uc3RhbnRzIH0pO1xuICAgIGNvbnN0IGVjZHNhTXBjdjJVdGlsID0gbmV3IFRlc3RFY2RzYU1wY3YyVXRpbHMoXG4gICAgICB0ZXN0Qml0Z28sXG4gICAgICB0ZXN0Q29pbixcbiAgICAgIG5ldyBXYWxsZXQodGVzdEJpdGdvLCB0ZXN0Q29pbiwgZWNkc2FXYWxsZXREYXRhKVxuICAgICk7XG4gICAgY29uc3QgYml0Z29HcGdQdWJLZXkgPSBhd2FpdCBlY2RzYU1wY3YyVXRpbC50ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyh0cnVlLCB1bmRlZmluZWQsIGVudGVycHJpc2VJZCk7XG4gICAgYml0Z29HcGdQdWJLZXkuYXJtb3IoKS5zaG91bGQuZXF1YWwoYml0Z29HUEdLZXkucHVibGljS2V5KTtcbiAgfSk7XG5cbiAgaXQoYHNob3VsZCB0aHJvdyBhbiBlcnJvciBpZiBjb25maWcgaXMgbm90IGF2YWlsYWJsZSBpbiBvbmUgb2YgdGVzdCwgc3RhZ2luZywgb3IgcHJvZGAsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgY29uc3QgdGVzdEJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGNvbnN0IHRlc3RDb2luID0gdGVzdEJpdGdvLmNvaW4oZWNkc2FDb2luTmFtZSk7XG4gICAgY29uc3QgZWNkc2FNcGN2MlV0aWwgPSBuZXcgVGVzdEVjZHNhTXBjdjJVdGlscyhcbiAgICAgIHRlc3RCaXRnbyxcbiAgICAgIHRlc3RDb2luLFxuICAgICAgbmV3IFdhbGxldCh0ZXN0Qml0Z28sIHRlc3RDb2luLCBlY2RzYVdhbGxldERhdGEpXG4gICAgKTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBhd2FpdCBlY2RzYU1wY3YyVXRpbC50ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZyh0cnVlKSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgc2VsZWN0IHRoZSBjb3JyZWN0IEdQRyBrZXkgZm9yIHZlcmlmeVdhbGxldFNpZ25hdHVyZXMgd2l0aCBoYXJkY29kZWQgb3B0aW9ucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBUZXN0IGVudmlyb25tZW50IHNldHVwXG4gICAgY29uc3QgZW52ID0gJ3Rlc3QnO1xuICAgIGNvbnN0IGJpdGdvSW5zdGFuY2UgPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52IH0pO1xuICAgIGJpdGdvSW5zdGFuY2UuaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgY29uc3QgY29pbkluc3RhbmNlID0gYml0Z29JbnN0YW5jZS5jb2luKGVkZHNhQ29pbk5hbWUpO1xuICAgIGNvbnN0IGVkZHNhTXBjdjFVdGlsID0gbmV3IFRlc3RFZGRzYU1wY3YxVXRpbHMoXG4gICAgICBiaXRnb0luc3RhbmNlLFxuICAgICAgY29pbkluc3RhbmNlLFxuICAgICAgbmV3IFdhbGxldChiaXRnb0luc3RhbmNlLCBjb2luSW5zdGFuY2UsIGVkZHNhV2FsbGV0RGF0YSlcbiAgICApO1xuXG4gICAgLy8gR2V0IHRoZSBrZXkgdGhhdCB3b3VsZCBiZSBzZWxlY3RlZCB3aGVuIHVzaW5nIGhhcmRjb2RlZCBCaXRHbyBrZXlzXG4gICAgLy8gbXBjdjEgYW5kIG5pdHJvIGFyZSBwYXNzZWQgYXMgb3B0aW9uc1xuICAgIGNvbnN0IGdwZ0tleSA9IGF3YWl0IGVkZHNhTXBjdjFVdGlsLnRlc3RQaWNrQml0Z29QdWJHcGdLZXlGb3JTaWduaW5nKGZhbHNlLCB1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG5cbiAgICAvLyBNb2NrIGltcGxlbWVudGF0aW9uIG9mIHZlcmlmeVdhbGxldFNpZ25hdHVyZXMgdG8gY2FwdHVyZSB0aGUgYml0Z29HcGdLZXkgdGhhdCBnZXRzIHVzZWRcbiAgICBsZXQgY2FwdHVyZWRLZXk7XG4gICAgZWRkc2FNcGN2MVV0aWwudmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyA9IGFzeW5jIGZ1bmN0aW9uIChcbiAgICAgIHVzZXJHcGdQdWIsXG4gICAgICBiYWNrdXBHcGdQdWIsXG4gICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgZGVjcnlwdGVkU2hhcmUsXG4gICAgICB2ZXJpZmllckluZGV4LFxuICAgICAgdXNlSGFyZGNvZGVkQml0R29LZXlzXG4gICAgKSB7XG4gICAgICAvLyBTYXZlIHRoZSBrZXkgdGhhdCB3b3VsZCBiZSB1c2VkIHdoZW4gc3BlY2lmeWluZyBoYXJkY29kZWQgb3B0aW9uc1xuICAgICAgaWYgKHVzZUhhcmRjb2RlZEJpdEdvS2V5cykge1xuICAgICAgICBjb25zdCBoYXJkY29kZWRLZXkgPSBhd2FpdCBvcGVucGdwLnJlYWRLZXkoe1xuICAgICAgICAgIGFybW9yZWRLZXk6IEJpdGdvTXBjR3BnUHViS2V5cy5iaXRnb01wY0dwZ1B1YktleXNbJ21wY3YxJ11bJ25pdHJvJ11bJ3Rlc3QnXSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNhcHR1cmVkS2V5ID0gaGFyZGNvZGVkS2V5LmFybW9yKCk7XG4gICAgICB9XG4gICAgICAvLyBOb3QgYWN0dWFsbHkgdmVyaWZ5aW5nIGluIHRoaXMgdGVzdFxuICAgICAgcmV0dXJuO1xuICAgIH07XG5cbiAgICAvLyBDYWxsIHdpdGggaGFyZGNvZGVkIGtleSBvcHRpb25zXG4gICAgYXdhaXQgZWRkc2FNcGN2MVV0aWwudmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyhcbiAgICAgICdtb2NrLXVzZXIta2V5JyxcbiAgICAgICdtb2NrLWJhY2t1cC1rZXknLFxuICAgICAge1xuICAgICAgICBjb21tb25LZXljaGFpbjogJ21vY2sta2V5Y2hhaW4nLFxuICAgICAgICB3YWxsZXRIU01HUEdQdWJsaWNLZXlTaWdzOiAnJyxcbiAgICAgICAgaWQ6ICcnLFxuICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgIH0sXG4gICAgICAnZGVjcnlwdGVkLXNoYXJlJyxcbiAgICAgIDEsXG4gICAgICB7IGVudjogJ3Rlc3QnLCBwdWJLZXlUeXBlOiAnbml0cm8nIH1cbiAgICApO1xuXG4gICAgLy8gVmVyaWZ5IHRoZSBoYXJkY29kZWQga2V5IG1hdGNoZXMgd2hhdCB3ZSBleHBlY3RcbiAgICBjYXB0dXJlZEtleS5zaG91bGQuZXF1YWwoQml0Z29NcGNHcGdQdWJLZXlzLmJpdGdvTXBjR3BnUHViS2V5c1snbXBjdjEnXVsnbml0cm8nXVsndGVzdCddKTtcbiAgICAvLyBBbHNvIHZlcmlmeSBpdCdzIHRoZSBzYW1lIGFzIHdoYXQncyByZXR1cm5lZCBieSB0ZXN0UGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZ1xuICAgIGdwZ0tleS5hcm1vcigpLnNob3VsZC5lcXVhbChjYXB0dXJlZEtleSk7XG4gIH0pO1xufSk7XG4iXX0=