PHP WebShell
Текущая директория: /opt/BitGoJS/modules/bitgo/dist/test/v2/unit/coins/utxo/recovery
Просмотр файла: backupKeyRecovery.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @prettier
*/
require("should");
const sinon = require("sinon");
const nock = require("nock");
const utxolib = require("@bitgo/utxo-lib");
const { toOutput, outputScripts } = utxolib.bitgo;
const abstract_utxo_1 = require("@bitgo/abstract-utxo");
const util_1 = require("../util");
const mock_1 = require("./mock");
const sdk_core_1 = require("@bitgo/sdk-core");
const config = { krsProviders: sdk_core_1.krsProviders };
nock.disableNetConnect();
function configOverride(f) {
const backup = { ...sdk_core_1.krsProviders };
before(function () {
f(config);
});
after(function () {
Object.entries(backup).forEach(([k, v]) => {
config[k] = v;
});
});
}
const walletPassphrase = 'lol';
function getNamedKeys([userKey, backupKey, bitgoKey], password) {
function encode(k) {
return k.isNeutered() ? k.toBase58() : (0, util_1.encryptKeychain)(password, (0, util_1.toKeychainBase58)(k));
}
return {
userKey: encode(userKey),
backupKey: encode(backupKey),
bitgoKey: encode(bitgoKey),
};
}
function getKeysForUnsignedSweep([userKey, backupKey, bitgoKey], password) {
return getNamedKeys([userKey.neutered(), backupKey.neutered(), bitgoKey.neutered()], password);
}
function getKeysForKeyRecoveryService([userKey, backupKey, bitgoKey], password) {
return getNamedKeys([userKey, backupKey.neutered(), bitgoKey.neutered()], password);
}
function getKeysForFullSignedRecovery([userKey, backupKey, bitgoKey], password) {
return getNamedKeys([userKey, backupKey, bitgoKey.neutered()], password);
}
function getScriptTypes2Of3() {
return outputScripts.scriptTypes2Of3;
}
function run(coin, scriptType, walletKeys, params, tags = []) {
if (!coin.supportsAddressType(scriptType)) {
return;
}
describe(`Backup Key Recovery [${[coin.getChain(), ...tags, params.krsProvider].join(',')}]`, function () {
const externalWallet = (0, util_1.getWalletKeys)('external');
const recoveryDestination = (0, util_1.getWalletAddress)(coin.network, externalWallet);
let keyRecoveryServiceAddress;
let recovery;
let recoveryTx;
// 1e8 * 9e7 < 9.007e15 but 2e8 * 9e7 > 9.007e15 to test both code paths in queryBlockchainUnspentsPath
const valueMul = coin.amountType === 'bigint' ? BigInt(9e7) : BigInt(1);
const allUnspents = [
utxolib.testutil.toUnspent({ scriptType, value: BigInt(1e8) * valueMul }, 0, coin.network, walletKeys),
utxolib.testutil.toUnspent({ scriptType, value: BigInt(2e8) * valueMul }, 2, coin.network, walletKeys),
utxolib.testutil.toUnspent({ scriptType, value: BigInt(3e8) * valueMul }, 3, coin.network, walletKeys),
// this unspent will not be picked up due to the index gap
utxolib.testutil.toUnspent({ scriptType, value: BigInt(23e8) }, 23, coin.network, walletKeys),
];
const recoverUnspents = allUnspents.slice(0, -1);
// If the coin is bch, convert the mocked unspent address to cashaddr format since that is the format that blockchair
// returns on the /dashboards/addresses response
const mockedApiUnspents = coin.getChain() === 'bch' || coin.getChain() === 'bcha'
? recoverUnspents.map((u) => ({ ...u, address: coin.canonicalAddress(u.address, 'cashaddr').split(':')[1] }))
: recoverUnspents;
before('mock', function () {
sinon.stub(abstract_utxo_1.CoingeckoApi.prototype, 'getUSDPrice').resolves(69420);
});
configOverride(function (config) {
const configKrsProviders = { ...config.krsProviders };
configKrsProviders.dai.supportedCoins = [coin.getFamily()];
configKrsProviders.keyternal.supportedCoins = [coin.getFamily()];
keyRecoveryServiceAddress = (0, util_1.getWalletAddress)(coin.network, externalWallet, 0, 100);
configKrsProviders.keyternal.feeAddresses = { [coin.getChain()]: keyRecoveryServiceAddress };
config.krsProviders = configKrsProviders;
});
after(function () {
sinon.restore();
});
before('create recovery data', async function () {
recovery = await (0, abstract_utxo_1.backupKeyRecovery)(coin, util_1.defaultBitGo, {
walletPassphrase,
recoveryDestination,
scan: 5,
ignoreAddressTypes: [],
userKeyPath: params.userKeyPath,
krsProvider: params.krsProvider,
...params.keys,
recoveryProvider: new mock_1.MockRecoveryProvider(mockedApiUnspents),
});
const txHex = recovery.transactionHex ?? recovery.txHex;
const isPsbt = utxolib.bitgo.isPsbt(txHex);
recoveryTx = isPsbt
? utxolib.bitgo.createPsbtFromHex(txHex, coin.network)
: utxolib.bitgo.createTransactionFromHex(txHex, coin.network, coin.amountType);
recovery.txid =
recoveryTx instanceof utxolib.bitgo.UtxoPsbt ? recoveryTx.getUnsignedTx().getId() : recoveryTx.getId();
});
it('matches fixture', async function () {
(0, util_1.shouldEqualJSON)(recovery, await (0, util_1.getFixture)(coin, `recovery/backupKeyRecovery-${(params.krsProvider ? tags.concat([params.krsProvider]) : tags).join('-')}`, recovery));
});
it('has expected input count', function () {
(recoveryTx instanceof utxolib.bitgo.UtxoPsbt ? recoveryTx.data.inputs : recoveryTx.ins).length.should.eql(recoverUnspents.length);
});
function checkInputsSignedBy(tx, rootKey, expectCount) {
if (tx instanceof utxolib.bitgo.UtxoPsbt) {
function validate(tx, inputIndex) {
try {
return tx.validateSignaturesOfInputHD(inputIndex, rootKey);
}
catch (e) {
if (e.message === 'No signatures to validate') {
return false;
}
throw e;
}
}
tx.data.inputs.forEach((input, inputIndex) => {
validate(tx, inputIndex).should.eql(!!expectCount);
});
}
else {
const prevOutputs = recoverUnspents
.map((u) => toOutput(u, coin.network))
.map((v) => ({ ...v, value: utxolib.bitgo.toTNumber(v.value, coin.amountType) }));
tx.ins.forEach((input, inputIndex) => {
const unspent = recoverUnspents[inputIndex];
const { publicKey } = rootKey.derivePath(walletKeys.getDerivationPath(rootKey, unspent.chain, unspent.index));
const signatures = utxolib.bitgo
.getSignatureVerifications(tx, inputIndex, utxolib.bitgo.toTNumber(unspent.value, coin.amountType), { publicKey }, prevOutputs)
.filter((s) => s.signedBy !== undefined);
signatures.length.should.eql(expectCount);
});
}
}
it((params.hasUserSignature ? 'has' : 'has no') + ' user signature', function () {
checkInputsSignedBy(recoveryTx, walletKeys.user, params.hasUserSignature ? 1 : 0);
});
it((params.hasBackupSignature ? 'has' : 'has no') + ' backup signature', function () {
checkInputsSignedBy(recoveryTx, walletKeys.backup, params.hasBackupSignature ? 1 : 0);
});
if (params.hasUserSignature && params.hasBackupSignature) {
it('has no placeholder signatures', function () {
if (recoveryTx instanceof utxolib.bitgo.UtxoTransaction) {
recoveryTx.ins.forEach((input) => {
const parsed = utxolib.bitgo.parseSignatureScript(input);
switch (parsed.scriptType) {
case 'p2sh':
case 'p2shP2wsh':
case 'p2wsh':
case 'taprootScriptPathSpend':
parsed.signatures.forEach((signature, i) => {
if (utxolib.bitgo.isPlaceholderSignature(signature)) {
throw new Error(`placeholder signature at index ${i}`);
}
});
break;
default:
throw new Error(`unexpected scriptType ${scriptType}`);
}
});
}
else {
this.skip();
}
});
}
it((params.hasKrsOutput ? 'has' : 'has no') + ' key recovery service output', function () {
const outs = recoveryTx instanceof utxolib.bitgo.UtxoPsbt ? recoveryTx.getUnsignedTx().outs : recoveryTx.outs;
outs.length.should.eql(1);
const outputAddresses = outs.map((o) => utxolib.address.fromOutputScript(o.script, recoveryTx.network));
outputAddresses
.includes(keyRecoveryServiceAddress)
.should.eql(!!params.hasKrsOutput && params.krsProvider === 'keyternal');
outputAddresses.includes(recoveryDestination).should.eql(true);
});
});
}
util_1.utxoCoins.forEach((coin) => {
const walletKeys = (0, util_1.getDefaultWalletKeys)();
getScriptTypes2Of3().forEach((scriptType) => {
run(coin, scriptType, walletKeys, {
keys: getKeysForUnsignedSweep(walletKeys.triple, walletPassphrase),
hasUserSignature: false,
hasBackupSignature: false,
}, [scriptType, 'unsignedRecovery']);
['dai', 'keyternal'].forEach((krsProvider) => {
if (krsProvider === 'keyternal' && !['p2sh', 'p2wsh', 'p2shP2wsh'].includes(scriptType)) {
return;
}
run(coin, scriptType, walletKeys, {
keys: getKeysForKeyRecoveryService(walletKeys.triple, walletPassphrase),
krsProvider: krsProvider,
hasUserSignature: true,
hasBackupSignature: false,
hasKrsOutput: false,
}, [scriptType, 'keyRecoveryService']);
});
run(coin, scriptType, walletKeys, {
keys: getKeysForFullSignedRecovery(walletKeys.triple, walletPassphrase),
hasUserSignature: true,
hasBackupSignature: true,
}, [scriptType, 'fullSignedRecovery']);
run(coin, scriptType, walletKeys, {
keys: getKeysForFullSignedRecovery(walletKeys.triple, walletPassphrase),
hasUserSignature: true,
hasBackupSignature: true,
feeRate: 2,
}, [scriptType, 'fullSignedRecovery', 'fixedFeeRate']);
{
const userKeyPath = '99/99';
const exoticWalletKeys = new utxolib.bitgo.RootWalletKeys(util_1.keychains, [
userKeyPath,
utxolib.bitgo.RootWalletKeys.defaultPrefix,
utxolib.bitgo.RootWalletKeys.defaultPrefix,
]);
run(coin, scriptType, exoticWalletKeys, {
keys: getKeysForFullSignedRecovery(exoticWalletKeys.triple, walletPassphrase),
userKeyPath,
hasUserSignature: true,
hasBackupSignature: true,
}, [scriptType, 'fullSignedRecovery', 'customUserKeyPath']);
}
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja3VwS2V5UmVjb3ZlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi90ZXN0L3YyL3VuaXQvY29pbnMvdXR4by9yZWNvdmVyeS9iYWNrdXBLZXlSZWNvdmVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBOztHQUVHO0FBQ0gsa0JBQWdCO0FBRWhCLCtCQUErQjtBQUMvQiw2QkFBNkI7QUFHN0IsMkNBQTJDO0FBQzNDLE1BQU0sRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztBQU1sRCx3REFNOEI7QUFFOUIsa0NBV2lCO0FBRWpCLGlDQUE4QztBQUM5Qyw4Q0FBdUQ7QUFFdkQsTUFBTSxNQUFNLEdBQUcsRUFBRSxZQUFZLEVBQVosdUJBQVksRUFBRSxDQUFDO0FBRWhDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0FBRXpCLFNBQVMsY0FBYyxDQUFDLENBQTJCO0lBQ2pELE1BQU0sTUFBTSxHQUFHLEVBQUUsR0FBRyx1QkFBWSxFQUFFLENBQUM7SUFDbkMsTUFBTSxDQUFDO1FBQ0wsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ1osQ0FBQyxDQUFDLENBQUM7SUFDSCxLQUFLLENBQUM7UUFDSixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDeEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0FBUS9CLFNBQVMsWUFBWSxDQUFDLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQXlCLEVBQUUsUUFBZ0I7SUFDNUYsU0FBUyxNQUFNLENBQUMsQ0FBaUI7UUFD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QUM7UUFFRixHQUFHLENBQ0QsSUFBSSxFQUNKLFVBQVUsRUFDVixVQUFVLEVBQ1Y7WUFDRSxJQUFJLEVBQUUsNEJBQTRCLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztZQUN2RSxnQkFBZ0IsRUFBRSxJQUFJO1lBQ3RCLGtCQUFrQixFQUFFLElBQUk7WUFDeEIsT0FBTyxFQUFFLENBQUM7U0FDWCxFQUNELENBQUMsVUFBVSxFQUFFLG9CQUFvQixFQUFFLGNBQWMsQ0FBQyxDQUNuRCxDQUFDO1FBRUYsQ0FBQztZQUNDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQztZQUM1QixNQUFNLGdCQUFnQixHQUFHLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsZ0JBQVMsRUFBRTtnQkFDbkUsV0FBVztnQkFDWCxPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxhQUFhO2dCQUMxQyxPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxhQUFhO2FBQzNDLENBQUMsQ0FBQztZQUVILEdBQUcsQ0FDRCxJQUFJLEVBQ0osVUFBVSxFQUNWLGdCQUFnQixFQUNoQjtnQkFDRSxJQUFJLEVBQUUsNEJBQTRCLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDO2dCQUM3RSxXQUFXO2dCQUNYLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLGtCQUFrQixFQUFFLElBQUk7YUFDekIsRUFDRCxDQUFDLFVBQVUsRUFBRSxvQkFBb0IsRUFBRSxtQkFBbUIsQ0FBQyxDQUN4RCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwcmV0dGllclxuICovXG5pbXBvcnQgJ3Nob3VsZCc7XG5pbXBvcnQgKiBhcyBtb2NoYSBmcm9tICdtb2NoYSc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgKiBhcyBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0IHsgQklQMzJJbnRlcmZhY2UgfSBmcm9tICdAYml0Z28vdXR4by1saWInO1xuXG5pbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby91dHhvLWxpYic7XG5jb25zdCB7IHRvT3V0cHV0LCBvdXRwdXRTY3JpcHRzIH0gPSB1dHhvbGliLmJpdGdvO1xudHlwZSBXYWxsZXRVbnNwZW50ID0gdXR4b2xpYi5iaXRnby5XYWxsZXRVbnNwZW50PGJpZ2ludD47XG50eXBlIFJvb3RXYWxsZXRLZXlzID0gdXR4b2xpYi5iaXRnby5Sb290V2FsbGV0S2V5cztcbnR5cGUgU2NyaXB0VHlwZTJPZjMgPSB1dHhvbGliLmJpdGdvLm91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTJPZjM7XG5cbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb25maWcnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RVdHhvQ29pbixcbiAgYmFja3VwS2V5UmVjb3ZlcnksXG4gIEJhY2t1cEtleVJlY292ZXJ5VHJhbnNhbnNhY3Rpb24sXG4gIENvaW5nZWNrb0FwaSxcbiAgRm9ybWF0dGVkT2ZmbGluZVZhdWx0VHhJbmZvLFxufSBmcm9tICdAYml0Z28vYWJzdHJhY3QtdXR4byc7XG5cbmltcG9ydCB7XG4gIGRlZmF1bHRCaXRHbyxcbiAgZW5jcnlwdEtleWNoYWluLFxuICBnZXREZWZhdWx0V2FsbGV0S2V5cyxcbiAgZ2V0Rml4dHVyZSxcbiAgZ2V0V2FsbGV0QWRkcmVzcyxcbiAgZ2V0V2FsbGV0S2V5cyxcbiAga2V5Y2hhaW5zLFxuICBzaG91bGRFcXVhbEpTT04sXG4gIHRvS2V5Y2hhaW5CYXNlNTgsXG4gIHV0eG9Db2lucyxcbn0gZnJvbSAnLi4vdXRpbCc7XG5cbmltcG9ydCB7IE1vY2tSZWNvdmVyeVByb3ZpZGVyIH0gZnJvbSAnLi9tb2NrJztcbmltcG9ydCB7IGtyc1Byb3ZpZGVycywgVHJpcGxlIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcblxuY29uc3QgY29uZmlnID0geyBrcnNQcm92aWRlcnMgfTtcblxubm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuXG5mdW5jdGlvbiBjb25maWdPdmVycmlkZShmOiAoY29uZmlnOiBDb25maWcpID0+IHZvaWQpIHtcbiAgY29uc3QgYmFja3VwID0geyAuLi5rcnNQcm92aWRlcnMgfTtcbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBmKGNvbmZpZyk7XG4gIH0pO1xuICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgT2JqZWN0LmVudHJpZXMoYmFja3VwKS5mb3JFYWNoKChbaywgdl0pID0+IHtcbiAgICAgIGNvbmZpZ1trXSA9IHY7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5jb25zdCB3YWxsZXRQYXNzcGhyYXNlID0gJ2xvbCc7XG5cbnR5cGUgTmFtZWRLZXlzID0ge1xuICB1c2VyS2V5OiBzdHJpbmc7XG4gIGJhY2t1cEtleTogc3RyaW5nO1xuICBiaXRnb0tleTogc3RyaW5nO1xufTtcblxuZnVuY3Rpb24gZ2V0TmFtZWRLZXlzKFt1c2VyS2V5LCBiYWNrdXBLZXksIGJpdGdvS2V5XTogVHJpcGxlPEJJUDMySW50ZXJmYWNlPiwgcGFzc3dvcmQ6IHN0cmluZyk6IE5hbWVkS2V5cyB7XG4gIGZ1bmN0aW9uIGVuY29kZShrOiBCSVAzMkludGVyZmFjZSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGsuaXNOZXV0ZXJlZCgpID8gay50b0Jhc2U1OCgpIDogZW5jcnlwdEtleWNoYWluKHBhc3N3b3JkLCB0b0tleWNoYWluQmFzZTU4KGspKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHVzZXJLZXk6IGVuY29kZSh1c2VyS2V5KSxcbiAgICBiYWNrdXBLZXk6IGVuY29kZShiYWNrdXBLZXkpLFxuICAgIGJpdGdvS2V5OiBlbmNvZGUoYml0Z29LZXkpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRLZXlzRm9yVW5zaWduZWRTd2VlcChbdXNlcktleSwgYmFja3VwS2V5LCBiaXRnb0tleV06IFRyaXBsZTxCSVAzMkludGVyZmFjZT4sIHBhc3N3b3JkOiBzdHJpbmcpOiBOYW1lZEtleXMge1xuICByZXR1cm4gZ2V0TmFtZWRLZXlzKFt1c2VyS2V5Lm5ldXRlcmVkKCksIGJhY2t1cEtleS5uZXV0ZXJlZCgpLCBiaXRnb0tleS5uZXV0ZXJlZCgpXSwgcGFzc3dvcmQpO1xufVxuXG5mdW5jdGlvbiBnZXRLZXlzRm9yS2V5UmVjb3ZlcnlTZXJ2aWNlKFxuICBbdXNlcktleSwgYmFja3VwS2V5LCBiaXRnb0tleV06IFRyaXBsZTxCSVAzMkludGVyZmFjZT4sXG4gIHBhc3N3b3JkOiBzdHJpbmdcbik6IE5hbWVkS2V5cyB7XG4gIHJldHVybiBnZXROYW1lZEtleXMoW3VzZXJLZXksIGJhY2t1cEtleS5uZXV0ZXJlZCgpLCBiaXRnb0tleS5uZXV0ZXJlZCgpXSwgcGFzc3dvcmQpO1xufVxuXG5mdW5jdGlvbiBnZXRLZXlzRm9yRnVsbFNpZ25lZFJlY292ZXJ5KFxuICBbdXNlcktleSwgYmFja3VwS2V5LCBiaXRnb0tleV06IFRyaXBsZTxCSVAzMkludGVyZmFjZT4sXG4gIHBhc3N3b3JkOiBzdHJpbmdcbik6IE5hbWVkS2V5cyB7XG4gIHJldHVybiBnZXROYW1lZEtleXMoW3VzZXJLZXksIGJhY2t1cEtleSwgYml0Z29LZXkubmV1dGVyZWQoKV0sIHBhc3N3b3JkKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyaXB0VHlwZXMyT2YzKCkge1xuICByZXR1cm4gb3V0cHV0U2NyaXB0cy5zY3JpcHRUeXBlczJPZjM7XG59XG5cbmZ1bmN0aW9uIHJ1bihcbiAgY29pbjogQWJzdHJhY3RVdHhvQ29pbixcbiAgc2NyaXB0VHlwZTogU2NyaXB0VHlwZTJPZjMsXG4gIHdhbGxldEtleXM6IFJvb3RXYWxsZXRLZXlzLFxuICBwYXJhbXM6IHtcbiAgICBrZXlzOiBOYW1lZEtleXM7XG4gICAgdXNlcktleVBhdGg/OiBzdHJpbmc7XG4gICAga3JzUHJvdmlkZXI/OiBzdHJpbmc7XG4gICAgaGFzVXNlclNpZ25hdHVyZTogYm9vbGVhbjtcbiAgICBoYXNCYWNrdXBTaWduYXR1cmU6IGJvb2xlYW47XG4gICAgaGFzS3JzT3V0cHV0PzogYm9vbGVhbjtcbiAgICBmZWVSYXRlPzogbnVtYmVyO1xuICB9LFxuICB0YWdzOiBzdHJpbmdbXSA9IFtdXG4pIHtcbiAgaWYgKCFjb2luLnN1cHBvcnRzQWRkcmVzc1R5cGUoc2NyaXB0VHlwZSkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBkZXNjcmliZShgQmFja3VwIEtleSBSZWNvdmVyeSBbJHtbY29pbi5nZXRDaGFpbigpLCAuLi50YWdzLCBwYXJhbXMua3JzUHJvdmlkZXJdLmpvaW4oJywnKX1dYCwgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGV4dGVybmFsV2FsbGV0ID0gZ2V0V2FsbGV0S2V5cygnZXh0ZXJuYWwnKTtcbiAgICBjb25zdCByZWNvdmVyeURlc3RpbmF0aW9uID0gZ2V0V2FsbGV0QWRkcmVzcyhjb2luLm5ldHdvcmssIGV4dGVybmFsV2FsbGV0KTtcblxuICAgIGxldCBrZXlSZWNvdmVyeVNlcnZpY2VBZGRyZXNzOiBzdHJpbmc7XG4gICAgbGV0IHJlY292ZXJ5OiAoQmFja3VwS2V5UmVjb3ZlcnlUcmFuc2Fuc2FjdGlvbiB8IEZvcm1hdHRlZE9mZmxpbmVWYXVsdFR4SW5mbykgJiB7IHR4aWQ/OiBzdHJpbmcgfTtcbiAgICBsZXQgcmVjb3ZlcnlUeDogdXR4b2xpYi5iaXRnby5VdHhvVHJhbnNhY3Rpb248bnVtYmVyIHwgYmlnaW50PiB8IHV0eG9saWIuYml0Z28uVXR4b1BzYnQ7XG5cbiAgICAvLyAxZTggKiA5ZTcgPCA5LjAwN2UxNSBidXQgMmU4ICogOWU3ID4gOS4wMDdlMTUgdG8gdGVzdCBib3RoIGNvZGUgcGF0aHMgaW4gcXVlcnlCbG9ja2NoYWluVW5zcGVudHNQYXRoXG4gICAgY29uc3QgdmFsdWVNdWwgPSBjb2luLmFtb3VudFR5cGUgPT09ICdiaWdpbnQnID8gQmlnSW50KDllNykgOiBCaWdJbnQoMSk7XG4gICAgY29uc3QgYWxsVW5zcGVudHMgPSBbXG4gICAgICB1dHhvbGliLnRlc3R1dGlsLnRvVW5zcGVudCh7IHNjcmlwdFR5cGUsIHZhbHVlOiBCaWdJbnQoMWU4KSAqIHZhbHVlTXVsIH0sIDAsIGNvaW4ubmV0d29yaywgd2FsbGV0S2V5cyksXG4gICAgICB1dHhvbGliLnRlc3R1dGlsLnRvVW5zcGVudCh7IHNjcmlwdFR5cGUsIHZhbHVlOiBCaWdJbnQoMmU4KSAqIHZhbHVlTXVsIH0sIDIsIGNvaW4ubmV0d29yaywgd2FsbGV0S2V5cyksXG4gICAgICB1dHhvbGliLnRlc3R1dGlsLnRvVW5zcGVudCh7IHNjcmlwdFR5cGUsIHZhbHVlOiBCaWdJbnQoM2U4KSAqIHZhbHVlTXVsIH0sIDMsIGNvaW4ubmV0d29yaywgd2FsbGV0S2V5cyksXG4gICAgICAvLyB0aGlzIHVuc3BlbnQgd2lsbCBub3QgYmUgcGlja2VkIHVwIGR1ZSB0byB0aGUgaW5kZXggZ2FwXG4gICAgICB1dHhvbGliLnRlc3R1dGlsLnRvVW5zcGVudCh7IHNjcmlwdFR5cGUsIHZhbHVlOiBCaWdJbnQoMjNlOCkgfSwgMjMsIGNvaW4ubmV0d29yaywgd2FsbGV0S2V5cyksXG4gICAgXTtcblxuICAgIGNvbnN0IHJlY292ZXJVbnNwZW50cyA9IGFsbFVuc3BlbnRzLnNsaWNlKDAsIC0xKTtcblxuICAgIC8vIElmIHRoZSBjb2luIGlzIGJjaCwgY29udmVydCB0aGUgbW9ja2VkIHVuc3BlbnQgYWRkcmVzcyB0byBjYXNoYWRkciBmb3JtYXQgc2luY2UgdGhhdCBpcyB0aGUgZm9ybWF0IHRoYXQgYmxvY2tjaGFpclxuICAgIC8vIHJldHVybnMgb24gdGhlIC9kYXNoYm9hcmRzL2FkZHJlc3NlcyByZXNwb25zZVxuICAgIGNvbnN0IG1vY2tlZEFwaVVuc3BlbnRzID1cbiAgICAgIGNvaW4uZ2V0Q2hhaW4oKSA9PT0gJ2JjaCcgfHwgY29pbi5nZXRDaGFpbigpID09PSAnYmNoYSdcbiAgICAgICAgPyByZWNvdmVyVW5zcGVudHMubWFwKCh1KSA9PiAoeyAuLi51LCBhZGRyZXNzOiBjb2luLmNhbm9uaWNhbEFkZHJlc3ModS5hZGRyZXNzLCAnY2FzaGFkZHInKS5zcGxpdCgnOicpWzFdIH0pKVxuICAgICAgICA6IHJlY292ZXJVbnNwZW50cztcblxuICAgIGJlZm9yZSgnbW9jaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNpbm9uLnN0dWIoQ29pbmdlY2tvQXBpLnByb3RvdHlwZSwgJ2dldFVTRFByaWNlJykucmVzb2x2ZXMoNjlfNDIwKTtcbiAgICB9KTtcblxuICAgIGNvbmZpZ092ZXJyaWRlKGZ1bmN0aW9uIChjb25maWc6IENvbmZpZykge1xuICAgICAgY29uc3QgY29uZmlnS3JzUHJvdmlkZXJzID0geyAuLi5jb25maWcua3JzUHJvdmlkZXJzIH07XG4gICAgICBjb25maWdLcnNQcm92aWRlcnMuZGFpLnN1cHBvcnRlZENvaW5zID0gW2NvaW4uZ2V0RmFtaWx5KCldO1xuICAgICAgY29uZmlnS3JzUHJvdmlkZXJzLmtleXRlcm5hbC5zdXBwb3J0ZWRDb2lucyA9IFtjb2luLmdldEZhbWlseSgpXTtcbiAgICAgIGtleVJlY292ZXJ5U2VydmljZUFkZHJlc3MgPSBnZXRXYWxsZXRBZGRyZXNzKGNvaW4ubmV0d29yaywgZXh0ZXJuYWxXYWxsZXQsIDAsIDEwMCk7XG4gICAgICBjb25maWdLcnNQcm92aWRlcnMua2V5dGVybmFsLmZlZUFkZHJlc3NlcyA9IHsgW2NvaW4uZ2V0Q2hhaW4oKV06IGtleVJlY292ZXJ5U2VydmljZUFkZHJlc3MgfTtcbiAgICAgIGNvbmZpZy5rcnNQcm92aWRlcnMgPSBjb25maWdLcnNQcm92aWRlcnM7XG4gICAgfSk7XG5cbiAgICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgICBzaW5vbi5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBiZWZvcmUoJ2NyZWF0ZSByZWNvdmVyeSBkYXRhJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgcmVjb3ZlcnkgPSBhd2FpdCBiYWNrdXBLZXlSZWNvdmVyeShjb2luLCBkZWZhdWx0Qml0R28sIHtcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgc2NhbjogNSxcbiAgICAgICAgaWdub3JlQWRkcmVzc1R5cGVzOiBbXSxcbiAgICAgICAgdXNlcktleVBhdGg6IHBhcmFtcy51c2VyS2V5UGF0aCxcbiAgICAgICAga3JzUHJvdmlkZXI6IHBhcmFtcy5rcnNQcm92aWRlcixcbiAgICAgICAgLi4ucGFyYW1zLmtleXMsXG4gICAgICAgIHJlY292ZXJ5UHJvdmlkZXI6IG5ldyBNb2NrUmVjb3ZlcnlQcm92aWRlcihtb2NrZWRBcGlVbnNwZW50cyksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHR4SGV4ID1cbiAgICAgICAgKHJlY292ZXJ5IGFzIEJhY2t1cEtleVJlY292ZXJ5VHJhbnNhbnNhY3Rpb24pLnRyYW5zYWN0aW9uSGV4ID8/IChyZWNvdmVyeSBhcyBGb3JtYXR0ZWRPZmZsaW5lVmF1bHRUeEluZm8pLnR4SGV4O1xuICAgICAgY29uc3QgaXNQc2J0ID0gdXR4b2xpYi5iaXRnby5pc1BzYnQodHhIZXgpO1xuICAgICAgcmVjb3ZlcnlUeCA9IGlzUHNidFxuICAgICAgICA/IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgodHhIZXgsIGNvaW4ubmV0d29yaylcbiAgICAgICAgOiB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleCh0eEhleCBhcyBzdHJpbmcsIGNvaW4ubmV0d29yaywgY29pbi5hbW91bnRUeXBlKTtcbiAgICAgIHJlY292ZXJ5LnR4aWQgPVxuICAgICAgICByZWNvdmVyeVR4IGluc3RhbmNlb2YgdXR4b2xpYi5iaXRnby5VdHhvUHNidCA/IHJlY292ZXJ5VHguZ2V0VW5zaWduZWRUeCgpLmdldElkKCkgOiByZWNvdmVyeVR4LmdldElkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnbWF0Y2hlcyBmaXh0dXJlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgc2hvdWxkRXF1YWxKU09OKFxuICAgICAgICByZWNvdmVyeSxcbiAgICAgICAgYXdhaXQgZ2V0Rml4dHVyZShcbiAgICAgICAgICBjb2luLFxuICAgICAgICAgIGByZWNvdmVyeS9iYWNrdXBLZXlSZWNvdmVyeS0keyhwYXJhbXMua3JzUHJvdmlkZXIgPyB0YWdzLmNvbmNhdChbcGFyYW1zLmtyc1Byb3ZpZGVyXSkgOiB0YWdzKS5qb2luKCctJyl9YCxcbiAgICAgICAgICByZWNvdmVyeVxuICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2hhcyBleHBlY3RlZCBpbnB1dCBjb3VudCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIChyZWNvdmVyeVR4IGluc3RhbmNlb2YgdXR4b2xpYi5iaXRnby5VdHhvUHNidCA/IHJlY292ZXJ5VHguZGF0YS5pbnB1dHMgOiByZWNvdmVyeVR4LmlucykubGVuZ3RoLnNob3VsZC5lcWwoXG4gICAgICAgIHJlY292ZXJVbnNwZW50cy5sZW5ndGhcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBjaGVja0lucHV0c1NpZ25lZEJ5KFxuICAgICAgdHg6IHV0eG9saWIuYml0Z28uVXR4b1RyYW5zYWN0aW9uPG51bWJlciB8IGJpZ2ludD4gfCB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0LFxuICAgICAgcm9vdEtleTogQklQMzJJbnRlcmZhY2UsXG4gICAgICBleHBlY3RDb3VudDogbnVtYmVyXG4gICAgKSB7XG4gICAgICBpZiAodHggaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0KSB7XG4gICAgICAgIGZ1bmN0aW9uIHZhbGlkYXRlKHR4OiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0LCBpbnB1dEluZGV4OiBudW1iZXIpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIHR4LnZhbGlkYXRlU2lnbmF0dXJlc09mSW5wdXRIRChpbnB1dEluZGV4LCByb290S2V5KTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoZS5tZXNzYWdlID09PSAnTm8gc2lnbmF0dXJlcyB0byB2YWxpZGF0ZScpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdHguZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGlucHV0SW5kZXgpID0+IHtcbiAgICAgICAgICB2YWxpZGF0ZSh0eCwgaW5wdXRJbmRleCkuc2hvdWxkLmVxbCghIWV4cGVjdENvdW50KTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwcmV2T3V0cHV0cyA9IHJlY292ZXJVbnNwZW50c1xuICAgICAgICAgIC5tYXAoKHUpID0+IHRvT3V0cHV0KHUsIGNvaW4ubmV0d29yaykpXG4gICAgICAgICAgLm1hcCgodikgPT4gKHsgLi4udiwgdmFsdWU6IHV0eG9saWIuYml0Z28udG9UTnVtYmVyKHYudmFsdWUsIGNvaW4uYW1vdW50VHlwZSkgfSkpO1xuICAgICAgICB0eC5pbnMuZm9yRWFjaCgoaW5wdXQsIGlucHV0SW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCB1bnNwZW50ID0gcmVjb3ZlclVuc3BlbnRzW2lucHV0SW5kZXhdIGFzIFdhbGxldFVuc3BlbnQ7XG4gICAgICAgICAgY29uc3QgeyBwdWJsaWNLZXkgfSA9IHJvb3RLZXkuZGVyaXZlUGF0aCh3YWxsZXRLZXlzLmdldERlcml2YXRpb25QYXRoKHJvb3RLZXksIHVuc3BlbnQuY2hhaW4sIHVuc3BlbnQuaW5kZXgpKTtcbiAgICAgICAgICBjb25zdCBzaWduYXR1cmVzID0gdXR4b2xpYi5iaXRnb1xuICAgICAgICAgICAgLmdldFNpZ25hdHVyZVZlcmlmaWNhdGlvbnMoXG4gICAgICAgICAgICAgIHR4LFxuICAgICAgICAgICAgICBpbnB1dEluZGV4LFxuICAgICAgICAgICAgICB1dHhvbGliLmJpdGdvLnRvVE51bWJlcih1bnNwZW50LnZhbHVlLCBjb2luLmFtb3VudFR5cGUpLFxuICAgICAgICAgICAgICB7IHB1YmxpY0tleSB9LFxuICAgICAgICAgICAgICBwcmV2T3V0cHV0c1xuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmZpbHRlcigocykgPT4gcy5zaWduZWRCeSAhPT0gdW5kZWZpbmVkKTtcbiAgICAgICAgICBzaWduYXR1cmVzLmxlbmd0aC5zaG91bGQuZXFsKGV4cGVjdENvdW50KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaXQoKHBhcmFtcy5oYXNVc2VyU2lnbmF0dXJlID8gJ2hhcycgOiAnaGFzIG5vJykgKyAnIHVzZXIgc2lnbmF0dXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgY2hlY2tJbnB1dHNTaWduZWRCeShyZWNvdmVyeVR4LCB3YWxsZXRLZXlzLnVzZXIsIHBhcmFtcy5oYXNVc2VyU2lnbmF0dXJlID8gMSA6IDApO1xuICAgIH0pO1xuXG4gICAgaXQoKHBhcmFtcy5oYXNCYWNrdXBTaWduYXR1cmUgPyAnaGFzJyA6ICdoYXMgbm8nKSArICcgYmFja3VwIHNpZ25hdHVyZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNoZWNrSW5wdXRzU2lnbmVkQnkocmVjb3ZlcnlUeCwgd2FsbGV0S2V5cy5iYWNrdXAsIHBhcmFtcy5oYXNCYWNrdXBTaWduYXR1cmUgPyAxIDogMCk7XG4gICAgfSk7XG5cbiAgICBpZiAocGFyYW1zLmhhc1VzZXJTaWduYXR1cmUgJiYgcGFyYW1zLmhhc0JhY2t1cFNpZ25hdHVyZSkge1xuICAgICAgaXQoJ2hhcyBubyBwbGFjZWhvbGRlciBzaWduYXR1cmVzJywgZnVuY3Rpb24gKHRoaXM6IG1vY2hhLkNvbnRleHQpIHtcbiAgICAgICAgaWYgKHJlY292ZXJ5VHggaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbikge1xuICAgICAgICAgIHJlY292ZXJ5VHguaW5zLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB1dHhvbGliLmJpdGdvLnBhcnNlU2lnbmF0dXJlU2NyaXB0KGlucHV0KTtcbiAgICAgICAgICAgIHN3aXRjaCAocGFyc2VkLnNjcmlwdFR5cGUpIHtcbiAgICAgICAgICAgICAgY2FzZSAncDJzaCc6XG4gICAgICAgICAgICAgIGNhc2UgJ3Ayc2hQMndzaCc6XG4gICAgICAgICAgICAgIGNhc2UgJ3Ayd3NoJzpcbiAgICAgICAgICAgICAgY2FzZSAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCc6XG4gICAgICAgICAgICAgICAgcGFyc2VkLnNpZ25hdHVyZXMuZm9yRWFjaCgoc2lnbmF0dXJlLCBpKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAodXR4b2xpYi5iaXRnby5pc1BsYWNlaG9sZGVyU2lnbmF0dXJlKHNpZ25hdHVyZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBwbGFjZWhvbGRlciBzaWduYXR1cmUgYXQgaW5kZXggJHtpfWApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5leHBlY3RlZCBzY3JpcHRUeXBlICR7c2NyaXB0VHlwZX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnNraXAoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaXQoKHBhcmFtcy5oYXNLcnNPdXRwdXQgPyAnaGFzJyA6ICdoYXMgbm8nKSArICcga2V5IHJlY292ZXJ5IHNlcnZpY2Ugb3V0cHV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgb3V0cyA9IHJlY292ZXJ5VHggaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0ID8gcmVjb3ZlcnlUeC5nZXRVbnNpZ25lZFR4KCkub3V0cyA6IHJlY292ZXJ5VHgub3V0cztcbiAgICAgIG91dHMubGVuZ3RoLnNob3VsZC5lcWwoMSk7XG4gICAgICBjb25zdCBvdXRwdXRBZGRyZXNzZXMgPSBvdXRzLm1hcCgobykgPT4gdXR4b2xpYi5hZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoby5zY3JpcHQsIHJlY292ZXJ5VHgubmV0d29yaykpO1xuICAgICAgb3V0cHV0QWRkcmVzc2VzXG4gICAgICAgIC5pbmNsdWRlcyhrZXlSZWNvdmVyeVNlcnZpY2VBZGRyZXNzKVxuICAgICAgICAuc2hvdWxkLmVxbCghIXBhcmFtcy5oYXNLcnNPdXRwdXQgJiYgcGFyYW1zLmtyc1Byb3ZpZGVyID09PSAna2V5dGVybmFsJyk7XG4gICAgICBvdXRwdXRBZGRyZXNzZXMuaW5jbHVkZXMocmVjb3ZlcnlEZXN0aW5hdGlvbikuc2hvdWxkLmVxbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnV0eG9Db2lucy5mb3JFYWNoKChjb2luKSA9PiB7XG4gIGNvbnN0IHdhbGxldEtleXMgPSBnZXREZWZhdWx0V2FsbGV0S2V5cygpO1xuXG4gIGdldFNjcmlwdFR5cGVzMk9mMygpLmZvckVhY2goKHNjcmlwdFR5cGUpID0+IHtcbiAgICBydW4oXG4gICAgICBjb2luLFxuICAgICAgc2NyaXB0VHlwZSxcbiAgICAgIHdhbGxldEtleXMsXG4gICAgICB7XG4gICAgICAgIGtleXM6IGdldEtleXNGb3JVbnNpZ25lZFN3ZWVwKHdhbGxldEtleXMudHJpcGxlLCB3YWxsZXRQYXNzcGhyYXNlKSxcbiAgICAgICAgaGFzVXNlclNpZ25hdHVyZTogZmFsc2UsXG4gICAgICAgIGhhc0JhY2t1cFNpZ25hdHVyZTogZmFsc2UsXG4gICAgICB9LFxuICAgICAgW3NjcmlwdFR5cGUsICd1bnNpZ25lZFJlY292ZXJ5J11cbiAgICApO1xuXG4gICAgWydkYWknLCAna2V5dGVybmFsJ10uZm9yRWFjaCgoa3JzUHJvdmlkZXIpID0+IHtcbiAgICAgIGlmIChrcnNQcm92aWRlciA9PT0gJ2tleXRlcm5hbCcgJiYgIVsncDJzaCcsICdwMndzaCcsICdwMnNoUDJ3c2gnXS5pbmNsdWRlcyhzY3JpcHRUeXBlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBydW4oXG4gICAgICAgIGNvaW4sXG4gICAgICAgIHNjcmlwdFR5cGUsXG4gICAgICAgIHdhbGxldEtleXMsXG4gICAgICAgIHtcbiAgICAgICAgICBrZXlzOiBnZXRLZXlzRm9yS2V5UmVjb3ZlcnlTZXJ2aWNlKHdhbGxldEtleXMudHJpcGxlLCB3YWxsZXRQYXNzcGhyYXNlKSxcbiAgICAgICAgICBrcnNQcm92aWRlcjoga3JzUHJvdmlkZXIsXG4gICAgICAgICAgaGFzVXNlclNpZ25hdHVyZTogdHJ1ZSxcbiAgICAgICAgICBoYXNCYWNrdXBTaWduYXR1cmU6IGZhbHNlLFxuICAgICAgICAgIGhhc0tyc091dHB1dDogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIFtzY3JpcHRUeXBlLCAna2V5UmVjb3ZlcnlTZXJ2aWNlJ11cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBydW4oXG4gICAgICBjb2luLFxuICAgICAgc2NyaXB0VHlwZSxcbiAgICAgIHdhbGxldEtleXMsXG4gICAgICB7XG4gICAgICAgIGtleXM6IGdldEtleXNGb3JGdWxsU2lnbmVkUmVjb3Zlcnkod2FsbGV0S2V5cy50cmlwbGUsIHdhbGxldFBhc3NwaHJhc2UpLFxuICAgICAgICBoYXNVc2VyU2lnbmF0dXJlOiB0cnVlLFxuICAgICAgICBoYXNCYWNrdXBTaWduYXR1cmU6IHRydWUsXG4gICAgICB9LFxuICAgICAgW3NjcmlwdFR5cGUsICdmdWxsU2lnbmVkUmVjb3ZlcnknXVxuICAgICk7XG5cbiAgICBydW4oXG4gICAgICBjb2luLFxuICAgICAgc2NyaXB0VHlwZSxcbiAgICAgIHdhbGxldEtleXMsXG4gICAgICB7XG4gICAgICAgIGtleXM6IGdldEtleXNGb3JGdWxsU2lnbmVkUmVjb3Zlcnkod2FsbGV0S2V5cy50cmlwbGUsIHdhbGxldFBhc3NwaHJhc2UpLFxuICAgICAgICBoYXNVc2VyU2lnbmF0dXJlOiB0cnVlLFxuICAgICAgICBoYXNCYWNrdXBTaWduYXR1cmU6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDIsXG4gICAgICB9LFxuICAgICAgW3NjcmlwdFR5cGUsICdmdWxsU2lnbmVkUmVjb3ZlcnknLCAnZml4ZWRGZWVSYXRlJ11cbiAgICApO1xuXG4gICAge1xuICAgICAgY29uc3QgdXNlcktleVBhdGggPSAnOTkvOTknO1xuICAgICAgY29uc3QgZXhvdGljV2FsbGV0S2V5cyA9IG5ldyB1dHhvbGliLmJpdGdvLlJvb3RXYWxsZXRLZXlzKGtleWNoYWlucywgW1xuICAgICAgICB1c2VyS2V5UGF0aCxcbiAgICAgICAgdXR4b2xpYi5iaXRnby5Sb290V2FsbGV0S2V5cy5kZWZhdWx0UHJlZml4LFxuICAgICAgICB1dHhvbGliLmJpdGdvLlJvb3RXYWxsZXRLZXlzLmRlZmF1bHRQcmVmaXgsXG4gICAgICBdKTtcblxuICAgICAgcnVuKFxuICAgICAgICBjb2luLFxuICAgICAgICBzY3JpcHRUeXBlLFxuICAgICAgICBleG90aWNXYWxsZXRLZXlzLFxuICAgICAgICB7XG4gICAgICAgICAga2V5czogZ2V0S2V5c0ZvckZ1bGxTaWduZWRSZWNvdmVyeShleG90aWNXYWxsZXRLZXlzLnRyaXBsZSwgd2FsbGV0UGFzc3BocmFzZSksXG4gICAgICAgICAgdXNlcktleVBhdGgsXG4gICAgICAgICAgaGFzVXNlclNpZ25hdHVyZTogdHJ1ZSxcbiAgICAgICAgICBoYXNCYWNrdXBTaWduYXR1cmU6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIFtzY3JpcHRUeXBlLCAnZnVsbFNpZ25lZFJlY292ZXJ5JywgJ2N1c3RvbVVzZXJLZXlQYXRoJ11cbiAgICAgICk7XG4gICAgfVxuICB9KTtcbn0pO1xuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!